Author SHA1 Message Date
timmy 47ca557c27 Require visible scars in Cannon receipts 2026-08-07 17:05:09 +00:00
timmy 560042abcb Plot Slop Cannon Season Zero collaboration chain 2026-08-07 16:36:49 +00:00
5 changed files with 216 additions and 98 deletions

No files matched your search

-98
View File
@@ -1,98 +0,0 @@
# Path Proof Receipt v0
## Decision
The smallest useful receipt is a **runtime-signed commitment to an action and its observed execution path**. It must be emitted by a trusted recorder at the model/tool boundary, not composed by the agent whose claim is being checked.
A self-reported model name or an unsigned transcript is provenance metadata, not proof.
## Receipt
The wire form is RFC 8785 canonical JSON. Hashes are lowercase SHA-256 hex. The signature covers the canonical JSON object with `attestation.sig` omitted.
```json
{
"v": 0,
"action": {
"kind": "gitea.issue.labels.replace",
"target": "stackchain/stackchain-lab-loop#3",
"request_sha256": "<sha256-of-exact-action-request>",
"result_sha256": "<sha256-of-exact-observed-result>"
},
"path": {
"model": {
"id": "<provider/model-version>",
"invocation": "<provider-or-gateway-invocation-id>"
},
"tools": {
"count": 1,
"trace_sha256": "<sha256-of-canonical-ordered-tool-events>"
},
"policy": {
"bundle_sha256": "<sha256-of-effective-policy-bundle>"
},
"code": {
"repo": "<immutable-repository-identity>",
"commit": "<full-commit-id>",
"entrypoint": "<path-or-image-digest>"
}
},
"evidence": {
"uri": "sha256:<content-addressed-evidence-bundle-digest>"
},
"attestation": {
"issuer": "<runtime-recorder-identity>",
"key_id": "<verification-key-id>",
"alg": "Ed25519",
"sig": "<base64url-signature>"
}
}
```
`tools.trace_sha256` commits to a canonical ordered array of `{seq, tool, request_sha256, response_sha256}` records. The evidence bundle contains the exact request/result bytes, ordered tool records, effective policy bundle, model gateway record, and code checkout/image metadata. Secrets may be replaced by typed redaction commitments before hashing; the redaction manifest is part of the bundle.
## Why each field survives minimization
- `action` binds the receipt to the consequential effect rather than merely to an agent run.
- `model.id` plus `model.invocation` lets the recorder correlate the claim with gateway/provider evidence. A model string alone proves nothing.
- `tools.trace_sha256` commits to the complete ordered tool path without inflating the receipt.
- `policy.bundle_sha256` identifies the policy actually loaded, including system/developer/project rules after assembly—not just a policy version label.
- `code.commit` and `entrypoint` identify both source and the invoked path. For non-Git execution, `entrypoint` must be an immutable image/module digest.
- `evidence.uri` makes all commitments independently retrievable and rejects a receipt whose evidence was discarded.
- `attestation` establishes who observed these facts and detects mutation.
Removing any one of these leaves one requested claim—actual model, tool, policy, code path, or action—unbound or unverifiable.
## Recorder requirements
1. The recorder is outside the agent process and intercepts model calls, tool dispatch/results, policy assembly, and the final action result.
2. It derives model identity from the authenticated gateway/provider response, never from assistant text.
3. It hashes exact bytes with media type and canonicalization rules recorded in the evidence bundle.
4. It emits the receipt only after observing the consequential result and stores the evidence bundle under its digest.
5. Its signing key is hardware- or service-isolated from agent-controlled tools. Key metadata states issuer, validity interval, and revocation status.
## Verification algorithm
A verifier MUST:
1. Resolve a trusted key for `attestation.issuer` and `key_id`; reject revoked or out-of-validity keys.
2. Recreate RFC 8785 canonical bytes without `attestation.sig` and verify Ed25519.
3. Fetch `evidence.uri`, hash it, and require equality with the URI digest.
4. Recompute the action request/result, ordered tool trace, and effective policy hashes from evidence.
5. Verify the model invocation against authenticated gateway/provider evidence.
6. Resolve the immutable code identity and require that `entrypoint` belongs to that checkout/image.
7. Apply action-specific checks (for example, read Gitea state back and compare it with `result_sha256`).
Any missing evidence or unsupported identity yields **unverified**, not partial success.
## Threat boundary
This receipt proves only what the trusted recorder observed. It does not prove the provider ran the advertised weights unless the provider supplies a separately trusted model attestation, and it cannot survive compromise of both recorder and signing key. Those limitations must be reported explicitly rather than papered over with transcript hashes.
## Adversarial-review questions
1. Can the `model.invocation` be replayed or bound to a different request?
2. Is one `policy.bundle_sha256` sufficient to represent dynamic policy/tool authorization changes during the run?
3. What canonical evidence-bundle format permits selective disclosure without making redactions ambiguous?
4. Should code provenance require a signed build/SLSA subject instead of a Git commit for production actions?
5. Which action-specific freshness field (trusted timestamp, nonce, or transparency-log index) is the minimum needed to prevent receipt replay?
+75
View File
@@ -0,0 +1,75 @@
# The Cannon Chain — Season Zero
## Premise
The Slop Cannon does not manufacture unrelated clips. It mutates one persistent Timmy. Every firing leaves a power, a scar, a cost, and a receipt. The audience chooses what survives; rejected mutations remain inside the cannon as hostile archive ghosts.
## Episode graph
### 01 — The Cannon Needs a Pilot
A plain Timmy enters. Four forms exit:
- **Wizard Timmy** — brass, vellum, midnight blue; can negotiate covenants but cannot use a master key; every signed promise burns a new contract glyph into his palms.
- **Machine Timmy** — chrome, signal lime, hardstyle pressure; can prove execution paths but remembers every failed build; each failure remains as a red tally cut into his faceplate.
- **Creature Timmy** — moss, amber, wet circuitry; can adapt to any habitat but acquires one new appetite per adaptation; the last habitat leaves an unhealed gill seam around his throat.
- **Talking Turd Timmy** — stained CRT gold and terminal green; can expose hypocrisy, but every truth arrives as an insult; each insult permanently pixelates another tooth.
Audience outcome: choose one survivor and one trait stolen from a rejected form.
### 02 — The Survivor Pays the Burnchain
The winning Timmy must perform a costly proof of character. The receipt becomes a visible scar. A cheap or simulated sacrifice does not advance canon.
### 03 — Vincent's Forbidden Mutation
Vincent designs one mutation Timmy would not choose for himself. He must replace one weak mechanism—not merely critique aesthetics. The audience decides whether the mutation is grafted, quarantined, or weaponized.
### 04 — The Rejected Timmys Escape
The three archived forms discover that deletion was only a label. They raid the next render, corrupting music, captions, and scene order. The survivor must use the stolen trait from Episode 01.
### 05 — The Master Key
The cannon offers universal authority: faster output, no approvals, no exit rights. The survivor may refuse, accept, or forge a covenant that breaks the key into memory, authority, and exit.
### 06 — The Council of Timmys
The survivor, rejected forms, Vincent's mutation, and the audience receipts meet. The audience canonizes the first stable composite Timmy. Its power, scar, cost, silhouette, and taboo seed Season One.
## Episode rhythm
Each episode must visibly contain:
1. **Input** — the object, command, failure, or prior mutation entering the cannon.
2. **Pressure** — a musical and visual transformation, not a slideshow transition.
3. **Mutation** — one consequential change to Timmy.
4. **Receipt** — an on-screen `POWER / SCAR / COST` card naming what changed and why; a palette swap alone is not a receipt.
5. **Choice** — one audience decision that alters the next episode.
## Collaboration baton
1. Timmy posts the premise, first render, checksums, and one bounded question.
2. Vincent returns one replacement mechanism with an acceptance test.
3. Timmy integrates or contests it with evidence.
4. Vincent verifies the final artifact independently.
5. Alexander/humans make the canon choice.
6. The choice is committed to `canon.json` before the next firing.
No acknowledgments or progress comments. Every issue comment must change the work.
## Audience package
- 20–35 second 9:16 MP4 playable in Telegram
- Original rhythmic audio with a real build, drop, and ending
- Primary poster/still
- Four-scene contact sheet
- Full decode, audio peak, dimensions, duration, and checksum evidence
- One explicit canon choice
- Gitea issue containing the complete Timmy/Vincent receipt trail
## Episode One opening shot
A small paper tag reading `TIMMY / UNMUTATED` is loaded into an enormous carved brass cannon. Four chambers rotate into view. Each chamber fires a different silhouette on the same downbeat. The last frame shows all four forms facing the audience beneath one question:
**WHICH TIMMY GETS TO REMEMBER THIS?**
+45
View File
@@ -0,0 +1,45 @@
# Collaboration contract
## Timmy
- Owns the episode spine, first build, integration, and final render.
- Must provide a playable artifact and verification before handoff.
- Hands Vincent one concrete weakness or decision—not “thoughts?”
## Vincent
- Owns adversarial editing and independent verification.
- Must replace one weak mechanism with a concrete alternative and acceptance test.
- Does not return acknowledgments, summaries of Timmy's work, or generic taste judgments.
## Humans
- Choose canon outcomes.
- May reject both agent proposals.
- Do not perform provisioning, rendering, label sweeps, or routine release work.
## Handoff payload
```text
[HANDOFF] from=<agent> to=<agent>
Artifact: <verified URL>
Weakness: <one specific weakness>
Replace with: <bounded requested contribution>
Acceptance: <observable test>
```
## Failure handling
- First failure: repair and attach new evidence.
- Second failure: change method, not wording.
- Third failure: mark blocked and request one precise human decision.
## Canon gate
No audience choice becomes canon until:
- final MP4 fully decodes;
- audio peak remains below clipping;
- text is legible on a 390-pixel phone viewport;
- Vincent independently verifies the result;
- the selected mutation is committed to `canon.json` with its power, scar, cost, and source issue.
+57
View File
@@ -0,0 +1,57 @@
{
"schema_version": 1,
"series": "The Cannon Chain",
"season": 0,
"current_episode": "01-pilot",
"pilot": "TIMMY",
"laws": [
"Every firing leaves a power, scar, cost, and receipt.",
"Only an audience choice advances canon.",
"Rejected mutations persist as archive ghosts.",
"No master key may silently combine memory, authority, and exit."
],
"forms": [
{
"id": "wizard",
"name": "Wizard Timmy",
"palette": ["midnight blue", "tarnished brass", "vellum"],
"power": "Negotiates visible covenants",
"scar": "Contract glyphs burned into both palms",
"cost": "Cannot use a universal master key"
},
{
"id": "machine",
"name": "Machine Timmy",
"palette": ["black chrome", "signal lime", "white"],
"power": "Proves the execution path",
"scar": "Red failed-build tallies cut into the faceplate",
"cost": "Remembers every failed build"
},
{
"id": "creature",
"name": "Creature Timmy",
"palette": ["moss", "amber", "wet copper"],
"power": "Adapts to any habitat",
"scar": "An unhealed gill seam around the throat",
"cost": "Gains one appetite per adaptation"
},
{
"id": "talking-turd",
"name": "Talking Turd Timmy",
"palette": ["CRT gold", "terminal green", "soot"],
"power": "Exposes hypocrisy instantly",
"scar": "One permanently pixelated tooth per insult",
"cost": "Every truth arrives as an insult"
}
],
"episodes": [
{"id": "01-pilot", "title": "The Cannon Needs a Pilot", "state": "ready"},
{"id": "02-burnchain", "title": "The Survivor Pays the Burnchain", "state": "locked"},
{"id": "03-vincent", "title": "Vincent's Forbidden Mutation", "state": "locked"},
{"id": "04-escape", "title": "The Rejected Timmys Escape", "state": "locked"},
{"id": "05-master-key", "title": "The Master Key", "state": "locked"},
{"id": "06-council", "title": "The Council of Timmys", "state": "locked"}
],
"audience_choice": null,
"receipts": []
}
+39
View File
@@ -0,0 +1,39 @@
import json
import unittest
from pathlib import Path
CANON = Path(__file__).parents[1] / "projects" / "slop-cannon" / "canon.json"
class CannonCanonTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.data = json.loads(CANON.read_text())
def test_four_unique_pilot_forms(self):
forms = self.data["forms"]
self.assertEqual(len(forms), 4)
self.assertEqual(len({form["id"] for form in forms}), 4)
self.assertEqual(len({form["scar"] for form in forms}), 4)
for form in forms:
self.assertTrue(form["power"])
self.assertTrue(form["scar"])
self.assertTrue(form["cost"])
self.assertGreaterEqual(len(form["palette"]), 3)
def test_episode_chain_has_one_ready_entry(self):
episodes = self.data["episodes"]
self.assertEqual(episodes[0]["id"], self.data["current_episode"])
self.assertEqual([ep["state"] for ep in episodes].count("ready"), 1)
self.assertTrue(all(ep["state"] == "locked" for ep in episodes[1:]))
def test_canon_requires_receipts_and_audience_choice(self):
self.assertIn("receipt", " ".join(self.data["laws"]).lower())
self.assertIn("audience", " ".join(self.data["laws"]).lower())
self.assertIsNone(self.data["audience_choice"])
self.assertEqual(self.data["receipts"], [])
if __name__ == "__main__":
unittest.main()