Skip to content

docs(chit): CHIT-FORKS provenance declaration + cipher fork record - #3063

Merged
POWERFULMOVES merged 1 commit into
mainfrom
docs/chit-forks-provenance
Sep 15, 2026
Merged

POWERFULMOVES merged 1 commit into
mainfrom
docs/chit-forks-provenance

Conversation

@POWERFULMOVES

Copy link
Copy Markdown
Owner

Declares the CHIT-FORKS pattern: a small, append-only record that pins an artifact + its upstream commit + its PMOVES overlay + the signing-card claim for the overlay. The first worked record is the cipher fork (Pmoves-cipher/src/agent/infra/memory/memory-manager.ts constants MAX_CONTENT_LENGTH / MAX_TAG_LENGTH / MAX_TAGS have no signing card; the shim's Bearer contract does).

Closes the flat-hierarchy failure mode the cipher reconcile surfaced this session: upstream byterover-cli baked in defaults at fork-time, PMOVES has no authorship on them, the artifact is self-authorized. The Three-Body problem from THREE_BODY_DOCTRINE.md names it; PR #2950 rooms-bug is the recent example. The fix is not changing the constants (that needs a byterover upstream bump), it's declaring whose they are.

Docs-only. Single new file: pmoves/docs/PMOVESCHIT/CHIT_FORKS.md. No schema, secret, or compose changes. Follow-ups (§6 in the doc) pair with wave-3 ratchet work.

The Three-Body problem from pmoves/docs/PMOVESCHIT/THREE_BODY_DOCTRINE.md
("without stabilization one body gets ejected") is the same shape
as the flat-hierarchy failure mode the cipher reconcile surfaced:
upstream byterover-cli baked in MAX_CONTENT_LENGTH=10_000,
MAX_TAG_LENGTH=50, MAX_TAGS=10 at fork-time. PMOVES has no signing
card on those constants; the artifact is a self-authorized black
hole. PR #2950's rooms-bug is the recent example.

This doc declares a CHIT-FORK pattern: a small, append-only record
that pins (a) the artifact, (b) the upstream commit, (c) the PMOVES
overlay, (d) the signing-card claim for the overlay only -- not the
upstream side, which is out of our sign-off loop. The first worked
record is the cipher fork (MemoryManager constants have no card;
the shim's Bearer contract does).

Follow-ups (§6) pair with wave-3 ratchet work: the 4 undeclared
PMOVES submodules (Composio/Activepieces/N8N) need fork-registry
entries before they can carry CHIT-FORK records. Pipecat, Crush,
and Agent-Zero forks are the natural next records.

No schema, secret, or compose changes. Docs-only.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • coderabbit

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 897974a2-a530-407a-a4e8-274a4a689d28

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the docs Documentation label Sep 15, 2026
@POWERFULMOVES
POWERFULMOVES merged commit 6b11dfc into main Sep 15, 2026
23 checks passed
@POWERFULMOVES
POWERFULMOVES deleted the docs/chit-forks-provenance branch September 15, 2026 04:23
POWERFULMOVES added a commit that referenced this pull request Sep 15, 2026
…ite bypass (#3069)

* infra(cipher): promote gitlink to 975e02e6, re-pin the citations it moved, and stop re-pinning by hand

Pmoves-cipher#19 merged (`Accept-Profile: pmoves_core`). Without that header
PostgREST resolves `cipher_agent_tokens` against the default `public` profile and
404s, so EVERY per-agent token failed as "invalid" — verified against migration
20260728100000, which creates the table in `pmoves_core`. It was the blocker
under both halves of the card-authority work and sat five days on a
single-account review requirement.

Gitlink e24f1323 -> 975e02e6 (reachable on PMOVES.AI-Edition-Hardened; also
brings #18 and e9ee58cb, both docs).

THE PIN MOVE BREAKS CITATIONS, EXACTLY AS PREDICTED. #19 inserts three lines at
:67, so four of the nine `auth.ts` citations shift +3:

  !token.startsWith('cipher_')    46  ->  46   (+0)
  agentId: 'bootstrap'            49  ->  49   (+0)
  records.length === 0            79  ->  82   (+3)
  !legacyToken && skipIfUnset    103  -> 106   (+3)

This is the second time in a week these numbers were wrong, for two different
reasons — the first was reading them off a working tree parked on that same PR's
unmerged head, where the numbers were right for me and wrong for everyone else.
Re-numbering by hand on each bump is not a fix; it is the same manual step
failing again on a schedule.

`pmoves/tests/tools/test_auth_citations_resolve.py` makes it machine-checkable
on the required test job, in three directions:

  1. the gitlink still equals the pin these numbers were read at — this test
     FAILED first run, correctly, because the promotion was staged and not yet
     committed, and `git ls-tree HEAD` reads the committed link;
  2. every cited LINE still carries its ANCHOR text in the pinned file;
  3. the docs quote the CURRENT numbers, with a negative control that the
     SUPERSEDED ones are gone — asserting the new numbers are present does not
     prove the old ones left, and a half-finished edit leaves both.

It also fails when the submodule WORKING TREE is ahead of the pin, which is the
condition that caused round one and reads as current when it is not.

Anchors are the real citation. The numbers are a convenience for a human reader
and this test is what keeps the convenience honest.

Docs re-pinned: TAC_CIPHER.md (provenance history rewritten as a three-pin table,
every superseded number now pin-qualified so no bare stale citation can be read
as current), cipher_identity.py, the cipher-memory SKILL, and the lane tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx

* docs(chit): fill the cipher fork record's commit pins, and check signing cards exist

AMENDMENT to #3063's record, filed under `z890-claude`, `signing_card` fields
left as `5090-claude` — this fills placeholders and appends a row, it does not
reassign authorship. §5 says each record is reviewed and signed by its lane
owner, so the derivation below is flagged for 5090-claude to confirm.

THE PINS. The record merged carrying `<filled when PR opens>` in both commit
fields, while its own §6.1 said the PR became mergeable *once the fork commit was
known*. So the first worked example of the provenance doctrine named its artifact
and pinned no commit, which makes "which auth.ts?" unanswerable from the record —
the exact question the doctrine exists to answer.

Not a criticism from outside: the same week, this lane cited auth.ts line numbers
read off a submodule working tree parked on an unmerged fork PR's head. Two
nodes, one session, the same failure from two directions — naming the artifact
without pinning the commit. Evidently easy to do while writing the document that
forbids it.

  pmoves_fork_commit      975e02e6...  the gitlink main carries, promoted in this
                                       same PR so record, gitlink and citations
                                       cannot disagree
  upstream.pinned_commit  1052ac1a...  parent of 389ce722, the first commit to
                                       touch src/pmoves/ — the last upstream
                                       state before the overlay. Derived, not
                                       guessed; authored by cuongdo-byterover.

NEW OVERRIDE ROW: the per-agent token mode (`auth.ts:46,49`). A bearer prefixed
`cipher_` resolves against pmoves_core.cipher_agent_tokens; one without it is
attributed to the literal `bootstrap` with no lookup. That contract was
unrecorded, and it is what two lanes on two nodes were independently building on.

THE CARD CHECK. #3063 declares that a constant with a card has an author and a
verification surface — and nothing checked the cards it names EXIST. Same gap,
one level up: a record asserting `signing_card: 5090-claude` carries exactly as
much authority as the claim that `5090-claude` is real and active, and a typo or
a deactivated card left it reading as authoritative while pointing at nobody.

`test_chit_forks_cards.py` uses the SAME `load_active_card_agents` that
`mint_cipher_token.py` gates minting on, so authorship-of-a-fork-override and
existence-of-a-memory-identity cannot drift apart about what an active card is.
This is the first cross-cutting use of that check.

`signing_card: none` stays valid and is pinned by a negative control — it is how
a record says "upstream's constant, no PMOVES authorship". Rejecting it would
push records toward inventing an owner, the opposite of the doctrine.

Mutation-checked: a typo'd card name and an abbreviated (non-40-char) pin each
fail exactly one test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx

* docs(register): RELEASE row for the cipher gitlink + provenance lane

Filed through `make -C pmoves register-release`; register diff is 1 added,
0 deleted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx

* fix(hooks): a command substitution is a command — close a register-write bypass

SECURITY. Wrapping a blocked register write in `$( )` plus one leading word
turned BLOCK into ALLOW. Measured on the pre-fix hook:

    env cp /tmp/x <register>        BLOCK  "cp writes the register as its DESTINATION"
    N=$(env cp /tmp/x <register>)   ALLOW  <- the same write, permitted

The hook's own header records six shapes that bypassed the design this allowlist
replaced. This was a seventh, inside the allowlist.

ROOT CAUSE, one fault, both directions. `_segments` splits on `; | & \n && ||`
and has no notion of `$( )`, so the parens stayed glued to adjacent tokens:

    N=$(env cp /tmp/x REG)  ->  ['N=$(env', 'cp', '/tmp/x', 'REG)']

`ASSIGNMENT_RE` matched the `N=` prefix of token 0, so the WHOLE token was
consumed as an assignment and `env` never reached `_strip_prefixes`' wrapper
list. The destination then arrived as `REG)` with the paren attached, so
`_is_register()` -- a path test, correctly -- said no, and the copy-verb guard
never fired.

The same fault refused reads the hook intends to allow:

    N=$(git show origin/main:REG)   "`show` is not a command ..."

though `show` IS in `_GIT_READ_SUBCOMMANDS`. `git` was eaten with the `N=`, so
the SUBCOMMAND was judged as if it were the command. `git diff` survived only
because `diff` also exists as a top-level read-only command -- so the documented
read path was working for the wrong reason, and the workaround I reported
yesterday ("use git diff --numstat instead") was passing by coincidence.

THE FIX. `_segments` now emits a substitution body as its OWN segment and removes
it from the outer text, leaving a bare `N=` that names no command. That is the
direction the function's docstring already endorses -- more segments face the
allowlist, so the verdict can only get stricter. Bodies are segmented
recursively (depth-capped; an over-nested one becomes a single unparseable
segment the allowlist refuses, rather than vanishing). Backticks handled.
Arithmetic `$((...))` is explicitly NOT a substitution -- judging `1` as a
command would refuse it. An unterminated `$(` keeps its text as literal, so an
unbalanced paren cannot swallow a write into an earlier allowed segment.

VERIFICATION. 17 tests. Reverting only the hook fails 9 of them -- the 4
fail-opens and 5 false refusals -- while every control still passes, which is
what proves the suite measures the substitution handling and not something
incidental:

  * unwrapped `cp`/`env cp` stay blocked (so the wrapped tests measure the WRAPPER)
  * `N=$(wc -l < REG)` stays ALLOWED (so the fix is not "refuse every $( )",
    the cheap version that would pass every write test and re-break the read
    path this defect was found through)
  * `$((1+1))` stays allowed
  * an unterminated `$(` still blocks the write after it
  * `make -C pmoves register-status` still passes -- the sanctioned path must
    keep working or the fix trades one deadlock for another

Found while investigating a reported papercut ("the hook refuses read-only
`git show`"). It was not a policy choice; `show` was already on the allowlist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
POWERFULMOVES added a commit that referenced this pull request Sep 15, 2026
…ns, and stop re-pinning citations by hand (#3068)

* infra(cipher): promote gitlink to 975e02e6, re-pin the citations it moved, and stop re-pinning by hand

Pmoves-cipher#19 merged (`Accept-Profile: pmoves_core`). Without that header
PostgREST resolves `cipher_agent_tokens` against the default `public` profile and
404s, so EVERY per-agent token failed as "invalid" — verified against migration
20260728100000, which creates the table in `pmoves_core`. It was the blocker
under both halves of the card-authority work and sat five days on a
single-account review requirement.

Gitlink e24f1323 -> 975e02e6 (reachable on PMOVES.AI-Edition-Hardened; also
brings #18 and e9ee58cb, both docs).

THE PIN MOVE BREAKS CITATIONS, EXACTLY AS PREDICTED. #19 inserts three lines at
:67, so four of the nine `auth.ts` citations shift +3:

  !token.startsWith('cipher_')    46  ->  46   (+0)
  agentId: 'bootstrap'            49  ->  49   (+0)
  records.length === 0            79  ->  82   (+3)
  !legacyToken && skipIfUnset    103  -> 106   (+3)

This is the second time in a week these numbers were wrong, for two different
reasons — the first was reading them off a working tree parked on that same PR's
unmerged head, where the numbers were right for me and wrong for everyone else.
Re-numbering by hand on each bump is not a fix; it is the same manual step
failing again on a schedule.

`pmoves/tests/tools/test_auth_citations_resolve.py` makes it machine-checkable
on the required test job, in three directions:

  1. the gitlink still equals the pin these numbers were read at — this test
     FAILED first run, correctly, because the promotion was staged and not yet
     committed, and `git ls-tree HEAD` reads the committed link;
  2. every cited LINE still carries its ANCHOR text in the pinned file;
  3. the docs quote the CURRENT numbers, with a negative control that the
     SUPERSEDED ones are gone — asserting the new numbers are present does not
     prove the old ones left, and a half-finished edit leaves both.

It also fails when the submodule WORKING TREE is ahead of the pin, which is the
condition that caused round one and reads as current when it is not.

Anchors are the real citation. The numbers are a convenience for a human reader
and this test is what keeps the convenience honest.

Docs re-pinned: TAC_CIPHER.md (provenance history rewritten as a three-pin table,
every superseded number now pin-qualified so no bare stale citation can be read
as current), cipher_identity.py, the cipher-memory SKILL, and the lane tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx

* docs(chit): fill the cipher fork record's commit pins, and check signing cards exist

AMENDMENT to #3063's record, filed under `z890-claude`, `signing_card` fields
left as `5090-claude` — this fills placeholders and appends a row, it does not
reassign authorship. §5 says each record is reviewed and signed by its lane
owner, so the derivation below is flagged for 5090-claude to confirm.

THE PINS. The record merged carrying `<filled when PR opens>` in both commit
fields, while its own §6.1 said the PR became mergeable *once the fork commit was
known*. So the first worked example of the provenance doctrine named its artifact
and pinned no commit, which makes "which auth.ts?" unanswerable from the record —
the exact question the doctrine exists to answer.

Not a criticism from outside: the same week, this lane cited auth.ts line numbers
read off a submodule working tree parked on an unmerged fork PR's head. Two
nodes, one session, the same failure from two directions — naming the artifact
without pinning the commit. Evidently easy to do while writing the document that
forbids it.

  pmoves_fork_commit      975e02e6...  the gitlink main carries, promoted in this
                                       same PR so record, gitlink and citations
                                       cannot disagree
  upstream.pinned_commit  1052ac1a...  parent of 389ce722, the first commit to
                                       touch src/pmoves/ — the last upstream
                                       state before the overlay. Derived, not
                                       guessed; authored by cuongdo-byterover.

NEW OVERRIDE ROW: the per-agent token mode (`auth.ts:46,49`). A bearer prefixed
`cipher_` resolves against pmoves_core.cipher_agent_tokens; one without it is
attributed to the literal `bootstrap` with no lookup. That contract was
unrecorded, and it is what two lanes on two nodes were independently building on.

THE CARD CHECK. #3063 declares that a constant with a card has an author and a
verification surface — and nothing checked the cards it names EXIST. Same gap,
one level up: a record asserting `signing_card: 5090-claude` carries exactly as
much authority as the claim that `5090-claude` is real and active, and a typo or
a deactivated card left it reading as authoritative while pointing at nobody.

`test_chit_forks_cards.py` uses the SAME `load_active_card_agents` that
`mint_cipher_token.py` gates minting on, so authorship-of-a-fork-override and
existence-of-a-memory-identity cannot drift apart about what an active card is.
This is the first cross-cutting use of that check.

`signing_card: none` stays valid and is pinned by a negative control — it is how
a record says "upstream's constant, no PMOVES authorship". Rejecting it would
push records toward inventing an owner, the opposite of the doctrine.

Mutation-checked: a typo'd card name and an abbreviated (non-40-char) pin each
fail exactly one test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx

* docs(register): RELEASE row for the cipher gitlink + provenance lane

Filed through `make -C pmoves register-release`; register diff is 1 added,
0 deleted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant