Skip to content

fix(proof): reject only explicit Decision alternatives - #279

Merged
tonyketcham merged 1 commit into
mainfrom
fix/proof-decision-alternatives
Sep 25, 2026
Merged

tonyketcham merged 1 commit into
mainfrom
fix/proof-decision-alternatives

Conversation

@tonyketcham

@tonyketcham tonyketcham commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

fix(proof): reject only explicit Decision alternatives AcceptDecision now rejects proposed Decisions only when they share a question Issue, whether open or closed, or when the caller lists them in rejects. It refuses another accepted answer to the same question and refuses a reopened alternative while its prior rejector remains accepted. The result names every changed and rejected Decision; dry run previews those changes without advancing the journal generation. ReopenDecision returns a rejected Decision to proposed and retains its rejection history. Supersede the hard mutation-enum Constraint through Proof's journaled writer to account for the seventeenth mutation. Update the source and bundled skills, API reference, README, and Unreleased changelog. Fixes #277 Validation: - Pinned pnpm 10.33.0 install and workspace build passed. - Writer suite: 21 tests passed, including the two review regressions. - Focused lifecycle, planner, schema, and CLI tests passed earlier. - Repository typecheck, skills:check, changed-file Prettier, and diff check passed. - Full verify stops at skills:pack-check on Windows: its Node child cannot launch npm, while direct npm pack --dry-run --json succeeds. - Repository lint flags unchanged root README.md. - Broad Proof tests have existing Windows path-separator failures.


Note

High Risk
Changes core Proof write semantics for Decision acceptance (breaking for Effort-wide rejection) and adds lifecycle mutations that affect journal integrity and agent workflows.

Overview
Tightens Proof Decision lifecycle so accepting one choice no longer silently rejects every other proposed Decision in the same Effort.

AcceptDecision now rejects only explicit alternatives: proposed Decisions that share the same question Issue (via derives_from, even if that Issue is closed) or ids listed in rejects. Responses include changedDecisionIds and rejectedIds, and dryRun: true / flatbread proof write --dry-run previews the same plan without committing or bumping journal generation.

Adds the 17th mutation ReopenDecision to move a rejected Decision back to proposed while keeping prior rejection in reopen_history. Acceptance is refused when a question already has an accepted winner, or when a reopened alternative is still blocked by an accepted rejector.

CLI, writer, schemas, digests/read projection, skills, README, changelog, and a superseded Proof Constraint document the new contract; callers that relied on Effort-wide sibling rejection get a breaking behavior change.

Reviewed by Cursor Bugbot for commit 9d6e84f. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6b6c44a. Configure here.

Comment thread packages/proof/src/decision-lifecycle.ts
@tonyketcham
tonyketcham force-pushed the fix/proof-decision-alternatives branch 2 times, most recently from eaf8346 to fb741e9 Compare September 25, 2026 09:41
cursor[bot]
cursor Bot previously requested changes Sep 25, 2026

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

REQUEST_CHANGES

The #277 sibling rule is the right AcceptDecision contract. Default rejectSiblings: true now rejects only proposed Decisions that share an open question Issue, plus ids in rejects. Dry-run, result ids, and the read allowlist for reopen_history match that design.

ReopenDecision is the half that is not ready. It is a 17th mutation and a Restore path. The live hard Constraint still says v1 has sixteen mutations and that Git is the undo story. This PR journals nothing. Either drop Reopen from this fix, or supersede that Constraint and fix the leftover "16" / "no Restore" lines in the same PR.

Prior notes closed: none from this automation (no threads to resolve). Bugbot's earlier reopen_history read miss is already resolved on this HEAD.

Domain verdicts

  • architecture: REQUEST_CHANGES
  • quality / simplify: COMMENT
  • proof journal: REQUEST_CHANGES (incomplete; superseding Constraint is 4/4, a new AcceptDecision Decision is 3/4 — do not write it)
  • correctness: COMMENT

Also fix while here (not blocking)

  • After reopen, or after the shared question is no longer open, a second Accept can leave two accepted answers.
  • Root CHANGELOG.md Unreleased is empty; Retract got a write-contract note.
  • Skill opener still says "16 typed mutations"; workflow still says "mind rejectSiblings".
  • reference.md mutation-result JSON still omits dryRun, changedDecisionIds, and rejectedIds.

Models: architecture / proof / correctness inherit (latest Cursor Grok); quality composer-2.5. Oven missing; Task fallback.

Open in Web View Automation 

Sent by Cursor Automation: Flatbread PR Review

Comment thread packages/proof/src/schemas.ts
Comment thread packages/proof/src/decision-lifecycle.ts
@tonyketcham
tonyketcham force-pushed the fix/proof-decision-alternatives branch 2 times, most recently from 38a5b7a to 6032a1d Compare September 25, 2026 10:02
AcceptDecision now rejects proposed Decisions only when they share a
question Issue, whether open or closed, or when the caller lists them in
rejects. It refuses another accepted answer to the same question and
refuses a reopened alternative while its prior rejector remains accepted.
The result names every changed and rejected Decision; dry run previews
those changes without advancing the journal generation. ReopenDecision
returns a rejected Decision to proposed and retains its rejection history.

Supersede the hard mutation-enum Constraint through Proof's journaled
writer to account for the seventeenth mutation. Update the source and
bundled skills, API reference, README, and Unreleased changelog.

Fixes #277

Validation:
- Pinned pnpm 10.33.0 install and workspace build passed.
- Writer suite: 21 tests passed, including the two review regressions.
- Focused lifecycle, planner, schema, and CLI tests passed earlier.
- Repository typecheck, skills:check, changed-file Prettier, and diff check passed.
- Full verify stops at skills:pack-check on Windows: its Node child cannot
  launch npm, while direct npm pack --dry-run --json succeeds.
- Repository lint flags unchanged root README.md.
- Broad Proof tests have existing Windows path-separator failures.
@tonyketcham
tonyketcham force-pushed the fix/proof-decision-alternatives branch from 6032a1d to 9d6e84f Compare September 25, 2026 10:06

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

COMMENT

The #277 sibling rule is now the AcceptDecision contract, and the prior REQUEST_CHANGES is closed. Default rejectSiblings: true rejects only proposed Decisions that share a question Issue (even after it closes), plus ids in rejects. Dry-run, result ids, and reopen_history on reads match that design. ReopenDecision is the 17th mutation. The live hard Constraint con-mutation-enum-stays-deliberately-small--3hw451bsedfj6khs supersedes the sixteen-mutation head and states the new undo split: Reopen restores a rejected Decision; Git still undoes Retract.

Prior notes closed

  • HIGH 17th mutation vs live Constraint (PRRT_kwDOGV8TsM6l84lx): fully addressed. Writer-produced Constraint, skills/README/reference/CHANGELOG say 17, no leftover live “sixteen.”
  • MED two accepted answers after reopen or a closed question (PRRT_kwDOGV8TsM6l84mC): fully addressed. Accept refuses a second same-question winner and a reopened Decision whose recorded rejector is still accepted. Writer tests cover both.

Domain verdicts

  • architecture: APPROVE
  • quality / simplify: COMMENT
  • proof journal: APPROVE (Constraint 4/4; no extra Decision — that would be 3/4)
  • correctness: COMMENT

Residual (not blocking)

  • Retract does not walk reopen_history.rejected_by. That field is history, not a live relation, so this does not create two winners. The Retract docs still say survivors should hold none of the retracted id. Document the snapshot exemption, or strip the nested id.
  • rejectSiblings still names Effort-wide siblings. Behavior and docs are question-scoped; the flag is only an opt-out from the auto-set.

Models: architecture / proof / correctness inherit (latest Cursor Grok); quality composer-2.5. Oven missing; Task fallback.

Open in Web View Automation 

Sent by Cursor Automation: Flatbread PR Review

@tonyketcham

Copy link
Copy Markdown
Collaborator Author

Thanks for the final review. The two residual points are intentional:

  • reopen_history.rejected_by is immutable provenance of an earlier rejection, not a live relation. Retract clears live relation fields; retaining the historical id explains why the Decision was previously rejected. The historical id is not traversed as a current graph edge.
  • rejectSiblings remains the existing input name for callers. Its documented behavior is now the question-scoped automatic alternative set, and rejects names additional alternatives explicitly.

The two earlier blocking findings are addressed on this head, and all hosted checks pass.

@tonyketcham
tonyketcham dismissed cursor[bot]’s stale review September 25, 2026 10:20

Superseded by the latest Flatbread PR Review on commit 9d6e84f, which confirms both requested changes are fully addressed. All CI checks pass and the related threads are resolved.

@tonyketcham
tonyketcham marked this pull request as ready for review September 25, 2026 16:50
@tonyketcham
tonyketcham merged commit 0d506bc into main Sep 25, 2026
22 checks passed
@tonyketcham
tonyketcham deleted the fix/proof-decision-alternatives branch September 25, 2026 16:50
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.

proof: AcceptDecision rejectSiblings default rejects unrelated proposals across the whole Effort

1 participant