Skip to content

C3: consent keeps a record, on the Ora row that already had the switch - #95

Merged
matthewpmunger merged 5 commits into
mainfrom
chunk-c3
Aug 27, 2026
Merged

C3: consent keeps a record, on the Ora row that already had the switch#95
matthewpmunger merged 5 commits into
mainfrom
chunk-c3

Conversation

@matthewpmunger

Copy link
Copy Markdown
Collaborator

Base sha 95d77a9, verified green before building: lint, typecheck, test (1335), build.
This branch: lint ✓ typecheck ✓ 1357 tests (105 files) ✓ build ✓

Merge after #94 (chunk-f6). Both branches add an entry to REPAIRS.md, so this one will need that one conflict resolved by keeping both entries. Nothing else conflicts.

What this does

Item 1 of the brief was withdrawn before building: a consent control already existed inside Connected systems, so a sixth Settings group would have put two controls and two public-scan disclosures over one boolean — the duplication this chunk exists to prevent. The Ora row is the control. Its heading, note and inline "Connected" / "Not connected" are untouched.

What it gains:

  • the retention sentence its disclosure did not say, rendered above the control because that is what somebody needs before deciding;
  • beneath it, an append-only history of who changed the setting and when.

The gate is untouched

agent-audit-isolation.test.ts and api/agent-audits/refresh are byte-identical to base, and the consent-defaults-closed line in normalize.ts is unchanged. The consent check still precedes the first target resolution.

Consent moves as one thing

The boolean and the history are written in a single withState; there is no path that writes either alone. A call that does not change the value appends nothing — an entry says what was decided, and re-selecting the position a project is already in is not a decision.

Withdrawal is not a retraction: every stored reading stays present and legible, and one predating the current withdrawal gains a clause the ledger imports rather than restates. The clause is computed against the history, not the boolean, because a project that connected, disconnected and reconnected has readings on both sides of the question — asserted both ways.

Two things corrected after review

  • consent.unrecorded (approved seventh string). A project connected before this record existed has a grant with no date. Suppressing the block treated that absence as nothing to report, which is rule 18. Two empty states now get two lines.
  • The Ora card is stacked. .settings-system is a flex row, so the history first rendered as a third column beside the toggle. Every structural test passed while it did; only opening the page showed it. Fixed with S8's existing --stacked modifier, with the original row reproduced inside so the Ora row itself is unchanged, and guarded by a test.

Verified against a running app

Grant appends with the verified identity rather than the request body; a repeat of the current value appends nothing; a withdrawal keeps the grant; both lines render beneath the control with absolute dates.

Not verified live: the ledger clause. The demo seed stores no Ora reading, so that path cannot be reached from the seeded app — it rests on unit tests, which assert both sides.

A scope note

The brief's "no src/ path outside Settings" cannot hold alongside its own item 3: an append-only history is storage, so types.ts, normalize.ts and mutations.ts necessarily move. Outside those and Settings, the only change is the one ledger clause and the prop feeding it. Confirmed as correct by the brief's author.

Not a repair

The REPAIRS.md entry records a finding — the retention doc-comment in mutations.ts sits above the wrong function — as explicitly not claimed and not fixed. No repair label, so the base-branch-green gate applies normally.

🤖 Generated with Claude Code

matthewpmunger and others added 5 commits August 26, 2026 19:18
Base sha 95d77a9, green on lint, typecheck, test (1335) and build.

Item 1 was withdrawn before building: a consent control already existed inside
Connected systems, so a sixth group would have put two controls and two
public-scan disclosures over one boolean — the duplication this chunk exists to
avoid. The Ora row IS the control. Its heading, note and inline "Connected" /
"Not connected" are untouched.

What it gains: the retention sentence its disclosure did not say, rendered above
the control because that is what somebody needs before deciding; and beneath it,
an append-only history of who changed the setting and when.

The boolean and the history are written in one `withState` and there is no path
that writes either alone. A call that changes nothing appends nothing — an entry
says what was decided, and re-selecting the position a project is already in is
not a decision.

The gate is untouched: the isolation test, the refresh route and the
consent-defaults-closed line in normalize are byte-identical to base.

Withdrawal is not a retraction. Every stored reading stays present, legible and
in place; a reading taken before the current withdrawal gains one clause, which
the ledger imports from the settings module rather than restating. The clause is
computed against the history, not the boolean, because a project that connected,
disconnected and connected again has readings on both sides of the question.

The brief's "no src/ path outside Settings" cannot hold alongside its own item 3:
an append-only history is storage, so types, normalize and mutations necessarily
move. Outside those and Settings, the only change is the one ledger clause and
the prop that feeds it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Found while reading for C3, at base 95d77a9. Not claimed and not fixed here.

Also records that C3's other reported leftover, addAgentIssueTask, is not one:
it has two live consumers and writes into state.recs. Noted so the next session
does not repeat the search.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two corrections after review and after actually looking at the screen.

`consent.unrecorded` (approved, seventh string): a project connected before this
record existed has a grant with no date. Suppressing the block treated that
absence as nothing to report, which is rule 18 exactly. Two empty states now get
two lines — "never connected" would be a flat lie about a project that is
connected right now.

The Ora card is stacked. `.settings-system` is a flex row, so the history was
rendering as a third column BESIDE the toggle rather than beneath it. Every
structural test passed while it did; only opening the page showed it. Guarded
now, using S8's existing `--stacked` modifier with the original row reproduced
inside, so the Ora row itself is unchanged.

Verified against a running app: the route appends with the verified identity and
not the request body, re-selecting the current position appends nothing, a
withdrawal keeps the grant, and both lines render with absolute dates beneath
the control. The ledger clause could not be exercised live — the demo seed
stores no Ora reading — so it rests on its unit tests, which assert both sides.

Dropped the REPAIRS note about addAgentIssueTask: the claim was withdrawn from
the C3 doc, so the correction has no subject left.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts:
#	src/app/(app)/settings/page.tsx
#	src/app/globals.css
#	src/lib/settings-copy.ts
@matthewpmunger
matthewpmunger merged commit 7a7a63d into main Aug 27, 2026
6 checks passed
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