Skip to content

Close the loop: pctr learn, and nine responses instead of two - #55

Merged
blocksifrdev merged 1 commit into
mainfrom
feat/learn-and-decision-vocabulary
Sep 15, 2026
Merged

blocksifrdev merged 1 commit into
mainfrom
feat/learn-and-decision-vocabulary

Conversation

@blocksifrdev

Copy link
Copy Markdown
Collaborator

Two places where the code was thinner than the doctrine it claims.

1. Nothing learned

The only thing any run read from a previous one was priorReceiptHash, for chaining. Run #100 knew exactly what run #1 knew — while the whole premise is that the system becomes more useful the longer it runs.

pctr learn reads the accumulated receipts and timelines and reports what they say to change:

WHAT THIS RUN TAUGHT PCTR

HIGH   payments.transfer declares $1800 but has moved up to $18,000
       Approval thresholds key off this, so the declared value has been under-protecting this action.
       can be applied automatically

MEDIUM planner holds authority "*" but has only ever used 1
       Observed: payments.transfer. Narrowing authority to what it actually does shrinks the blast radius.

MEDIUM payments.transfer has been denied 5× for APPROVAL_REQUIRED

It finds undeclared actions that executed anyway, understated consequences, chronically stale attestations, unused wildcard authority, approvals always granted (a rubber stamp) or never granted (a wall), unreachable protected actions, and repeated denials.

Findings are proposals, never silent edits. --apply is a separate act, and each finding carries the evidence it came from.

The compounding is verifiable, not asserted: after pctr learn --apply, running pctr preview payments.transfer with no arguments returns CRITICAL where it previously returned HIGH — because the system now knows that action moves $18,000, not the $1,800 someone typed into the manifest. There's a test that pins exactly this.

2. The decision vocabulary was allow/deny

The doctrine specifies nine responses to a trust change. Denying everything that wobbles is as wrong as allowing it — the useful answer is usually narrower than "no": reroute around the stale agent, cap the batch, ask a human, slow it down.

pctr decide customers.delete --records 1842
Response              CONSTRAIN
Proceeds              YES
1,842 records is above the batch limit of 25; bound it and the consequence is recoverable
Proposed bound: {"recordsAffected":25}
Proceeds Does not proceed
KEEP REROUTE CONSTRAIN THROTTLE STEP_UP ESCALATE SUSPEND DENY REVOKE

Checks run most-restrictive first, so a revoked credential is never answered with a reroute. reconcile() refuses to answer a change with a weaker response than it warranted — that is how authority expands by accident.

Also

export / download / dump / backup now classify as data read rather than "no protected consequence" — a bulk export is data leaving the building. Mirrored in the Python bridge; the parity gate holds at 52 checks.

156 tests (18 new), Python 19, parity green.

🤖 Generated with Claude Code

Two gaps between what the doctrine claims and what the code did.

1. Nothing learned. The only thing any run read from a previous one was
   priorReceiptHash, for chaining. Run 100 knew exactly what run 1 knew,
   while the whole premise is that the system gets more useful the longer
   it runs.

   pctr learn reads the accumulated receipts and timelines and reports
   what they say to change: actions that executed but were never
   declared, consequences declared smaller than they turned out to be,
   agents whose evidence is chronically stale, wildcard authority nobody
   uses, approvals always granted (a rubber stamp) or never granted (a
   wall), protected actions with no admissible route, and denials that
   keep repeating.

   Findings are proposals, never silent edits; --apply is a separate act
   and each finding carries its evidence. The compounding is verifiable:
   after applying, previewing payments.transfer with no arguments returns
   CRITICAL where it returned HIGH, because the system now knows the
   action moves $18,000 rather than the $1,800 someone typed.

2. The decision vocabulary was allow/deny. The doctrine specifies nine
   responses to a trust change, and denying everything that wobbles is as
   wrong as allowing it — the useful answer is usually narrower than no:
   reroute around the stale agent, cap the batch, ask a human, slow it
   down.

   KEEP, REROUTE, CONSTRAIN, STEP_UP, ESCALATE, THROTTLE, SUSPEND, DENY,
   REVOKE, checked most-restrictive first so a revoked credential is
   never answered with a reroute. reconcile() refuses to answer a change
   with a weaker response than it warranted.

Also classifies export/download/dump/backup as data read rather than
shrugging at it — a bulk export is data leaving the building. Mirrored in
the Python bridge; the parity gate holds at 52 checks.

156 tests (18 new).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@blocksifrdev
blocksifrdev merged commit ae3dcd9 into main Sep 15, 2026
4 checks passed
@blocksifrdev
blocksifrdev deleted the feat/learn-and-decision-vocabulary branch September 15, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant