Skip to content

feat: add revision-bound signal decisions - #76

Merged
roodboi merged 17 commits into
mainfrom
codex/hack-1033-decision-lifecycle
Sep 14, 2026
Merged

roodboi merged 17 commits into
mainfrom
codex/hack-1033-decision-lifecycle

Conversation

@roodboi

@roodboi roodboi commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Adds revision-bound signal-family decisions through fclt ai loop decide and the typed MCP activity router. Accept, redirect, reject, and defer record machine-local lifecycle receipts after validating the current locator, queue revision, scope identity, and explicit approval. Resolve plans advertise the required approval. Decision context must match the issued queue identity and lifecycle; copied verification data includes only validated fields. CLI home resolution falls back to the OS home when HOME is absent.

The receipt records a decision; it does not implement it, apply a proposal, mutate canonical capability, create work in an external system, or hide a deferred signal. Coverage completeness and cursor freshness remain separate.

Also preserves a detected mise installation during self-update: the npm launcher’s package-manager hint no longer redirects the update to a separate global npm installation.

Related: HACK-1033.

Validation on the current integration:

  • 73 CLI, activity-decision, and self-update regression tests passed after review fixes; 64 combined decision, output, CLI, and path integration tests passed before those additional checks.
  • Linux CI and macOS/Windows binary verification passed.
  • Typecheck, lint, compiled binary verification, package dry-run, diff checks, and changed-surface privacy review passed.
  • The broader local integration run had a slow MCP audit fixture timeout and the environment-restoration test issue fixed by fix: recover scheduled evolution reviews and close render locks #82; it is not claimed as a clean full local run. The existing feature tests and current CI validate the release behavior.

Reverting this feature leaves existing receipts as history; no canonical or external data migration is introduced.

@linear-code

linear-code Bot commented Aug 5, 2026

Copy link
Copy Markdown

HACK-1033

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cdd978a658

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/activity-action.ts
Comment on lines +558 to +560
resource.kind === "signal"
? "Record an approved signal decision only through loop decide with this locator and the exact expected queue revision; the receipt does not implement the decision."
: "Do not invoke a mutation from this plan; proposal and coverage lifecycle changes remain separate closed workflows.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Mark signal decisions as approval-required

When the locator is for a signal item, activityActionClass() returns handoff, so this new signal-specific resolve plan still serializes mutation.approvalRequired: false even though decideActivityAction() rejects every decision without approve=true. Consumers that use the resolve JSON to decide whether to show or require approval will suppress the required approval prompt or misstate the safety boundary for signal decisions; set the approval flag true for signal resources.

AGENTS.md reference: AGENTS.md:L130-L130

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-14T15:57:10.512400Z 99252e6 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8d13e2cc5d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/ai.ts Outdated
"./activity-action"
);
const result = await decideActivityAction({
homeDir: process.env.HOME ?? "",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Fall back to the OS home for decisions

When HOME is unset—as is common in native Windows shells—this passes an empty home directory, so locator discovery searches relative .ai and .local/state/fclt paths instead of the user's actual home-backed state. Consequently, otherwise valid loop decide calls return locator_not_found; use homedir() as the fallback, as the path helpers do.

AGENTS.md reference: AGENTS.md:L129-L129

Useful? React with 👍 / 👎.

Comment thread src/activity-action.ts Outdated
typeof desiredOutcome === "string"
? redactPortableActivityText(desiredOutcome)
: null,
verification: item.verification ?? null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Copy only validated verification fields

When an embedded activity report contains extra verification metadata, this copies the entire object into the durable receipt and returned CLI/MCP JSON. Both isActivityItem and isActivityDecisionWorkUnit permit unknown verification properties, so a future or malformed report containing a local path, token, or other private field passes validation and leaks it unredacted; reconstruct the verification object from the explicitly validated timestamp/state/attempt fields or reject unknown keys.

AGENTS.md reference: AGENTS.md:L131-L131

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6969a87fa9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/activity-action.ts
next: "Refresh activity and decide only a newer signal revision.",
});
}
const workUnit = decisionWorkUnit(match.issuedItem);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bind the copied work unit to the queue item

When the persisted activity snapshot is malformed or locally corrupted, this copies the first feed item matching only actionLocator and technical.queueId, without checking that its id, kind, family identity, or lifecycle fields correspond to the queue item used to compute the binding digest. Because isActivityFeed validates those objects independently, a mismatched item can pass validation and cause an approved decision for one signal to return and persist another item's targets, evidence, and next action; validate the issued item against the matched queue candidate before constructing the receipt.

Useful? React with 👍 / 👎.

@roodboi
roodboi merged commit 035db08 into main Sep 14, 2026
5 checks passed
@roodboi
roodboi deleted the codex/hack-1033-decision-lifecycle branch September 14, 2026 15:55

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99252e6f72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/activity-action.ts
Comment on lines +603 to +606
JSON.stringify(issued.linkedWork) ===
JSON.stringify(item.linkedWork.map(redactPortableActivityText)) &&
JSON.stringify(portableVerification(issued.verification)) ===
JSON.stringify(portableVerification(item.verification))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bind every copied work-unit field to the locator

When an embedded activity report is corrupted or modified after the locator was issued, this predicate still accepts changes to context.targets, evidence, observation desiredOutcome, and nextAction, even though decisionWorkUnit() later copies all of them into the durable receipt and CLI/MCP JSON. Fresh evidence after the earlier mismatch fix is that the new predicate binds linkedWork and verification but omits these remaining copied fields; therefore an approval for an unchanged queue item can persist misleading handoff instructions without making the locator stale. Include the complete portable work-unit context in the issued binding or reconstruct and compare it against authoritative current inputs.

AGENTS.md reference: AGENTS.md:L130-L130

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.31.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant