Skip to content

test(engine): assert mutation-context attribution across engine suites (4/5) - #3432

Open
gsxdsm wants to merge 7 commits into
identity/3-engine-srcfrom
identity/4-engine-tests
Open

test(engine): assert mutation-context attribution across engine suites (4/5)#3432
gsxdsm wants to merge 7 commits into
identity/3-engine-srcfrom
identity/4-engine-tests

Conversation

@gsxdsm

@gsxdsm gsxdsm commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Stack 4/5 — 126 files. Base: identity/3-engine-src.

Test-only. Asserts the mutation context positionally rather than waving it through, so the day U9/U11/U13 hand a path a real actor, the assertion fails and names the line instead of silently accepting whatever arrived.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1502b763-df5a-4af9-ab03-7fdb4aa3b9bf

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.

@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR strengthens engine mutation-attribution tests by distinguishing attributed contexts from explicitly unattributed writes and asserting mutation contexts positionally across engine suites.

  • Adds shared matchers and regression controls that reject missing or explicitly unattributed contexts where attribution is required.
  • Uses an explicit matcher for known unresolved attribution paths so those gaps remain visible.
  • Threads the live executor mutation context into branch-conflict worktree-reclaim persistence.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the previously reported generic-matcher issue is directly addressed by rejecting the explicit unattributed actor marker and covering that behavior with dedicated tests.

Important Files Changed

Filename Overview
packages/engine/src/tests/mutation-context-matchers.ts Adds distinct attributed and unattributed context matchers; the attributed matcher now rejects the exact marker identified by the prior review.
packages/engine/src/tests/mutation-context-matchers.test.ts Adds direct controls proving attributed contexts pass while unattributed, missing, and empty contexts fail.
packages/engine/src/executor/worktree-branch-conflict-handle.ts Attributes the reclaimed-worktree task update using the same executor run context used by the recovery log.

Reviews (14): Last reviewed commit: "Merge remote-tracking branch 'origin/ide..." | Re-trigger Greptile

Comment thread packages/engine/src/__tests__/mutation-context-matchers.ts
@gsxdsm
gsxdsm force-pushed the identity/3-engine-src branch from e26a7ef to d407a8d Compare August 14, 2026 03:46
@gsxdsm
gsxdsm force-pushed the identity/4-engine-tests branch from 404e3a8 to be439e7 Compare August 14, 2026 03:46
@gsxdsm
gsxdsm force-pushed the identity/3-engine-src branch from d407a8d to 5ce4b60 Compare August 14, 2026 03:54
@gsxdsm
gsxdsm force-pushed the identity/4-engine-tests branch from be439e7 to a167214 Compare August 14, 2026 03:54
@gsxdsm
gsxdsm force-pushed the identity/3-engine-src branch from 5ce4b60 to 8c23e8c Compare August 14, 2026 04:01
@gsxdsm
gsxdsm force-pushed the identity/4-engine-tests branch from a167214 to 3129138 Compare August 14, 2026 04:01
@gsxdsm

gsxdsm commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gsxdsm

gsxdsm commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Review feedback addressed in 1fa0961294 on feature/user-accounts (the merge path, #3428).

Fixed — the findings were correct:

Finding Resolution
identityEnabled never reaches the process flag (#3429) Wired in the daemon on startup and on settings:updated. This was a real gap in my own work — identity-enabled.ts says "U5 calls this on startup and on change" and U5 never did. Failure was silent in the dangerous direction: UI reads "on", every gate stays on its disabled allow-branch.
moveTask unattributed at the merge boundary (#3430) Threaded. It was the only write in that file still on the context-free shape, so the move audited as system/unknown while the log entries either side of it carried the real actor.
captureBaseCommitSha drops run identity (#3430) Threaded at both callers — each already resolves a context for every other write on the same path.
FNXC comment documents a call that doesn't exist (#3430) Fixed, and found a second instance: an earlier bulk conversion had rewritten text inside safe-log-entry.ts's comment, corrupting the historical record of the FN-7335 bug that comment exists to explain.
ANY_MUTATION_CONTEXT accepts system:unattributed (#3432) Tightened, with proven-failing controls for the matcher itself. This was the highest-value finding — see below.

The matcher finding deserves its own note. It was exactly right, and the blast radius was real: tightening exposed 15 genuinely unattributed writes across 11 suites that the loose matcher had been passing as attributed. Those now assert UNATTRIBUTED_CONTEXT_MATCHER explicitly, so the remaining gap is countable rather than invisible. Since a wrongly-marked (actually-attributed) site fails the assertion, all-green proves the classification is right rather than merely quiet.

Not applied, with reasons:

Verification. Measured against a baseline of the same tree with these edits reverted, so pre-existing failures aren't attributed to this change: 77 failed files / 258 failed tests before → 77 / 263 after, with no file this change touches newly failing. pnpm test:gate, pnpm lint, and CLI typecheck all green. One new suite-only failure (self-healing-pending-wedge-notification) is unmodified by this change, passes in isolation, and is recorded in the observed-flakes register per the standing rule rather than quarantined on a first sighting.

@gsxdsm

gsxdsm commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Stack rebased so every chunk carries its own review fixes; the stack tip is byte-identical to the full branch (git rev-parse identity/5-dashboard-cli^{tree} == feature/user-accounts^{tree} == 1252e4a096).

One further real finding fixed (d6167be9be): rebaseNewWorktreeOntoRemote's dep type stopped at settingsOverride, so the sole production caller could not pass a run context even though createWorktree resolves one for its other writes — its skip/fetch/success/failure breadcrumbs all persisted unattributed. Notably, that parameter's own doc comment claimed it was "REQUIRED so an unwired caller is a compile error, not a silent unattributed write" while being declared optional, and the one caller was in fact unwired. The comment now describes the code rather than contradicting it.

Re-posted findings that are already fixed in the current tree (the bot re-reviewed against pre-fix line numbers):

  • workflow-merge-boundary.ts:114/:136 — there is exactly one moveTask in that file and it takes the context; verified at the current SHA.
  • worktree-git-refs.ts:149 — both callers now pass a resolved context.
  • mutation-context-matchers.ts:40 "generic matcher accepts unattributed writes" — the matcher no longer uses expect.any(String); it matches /^(?!system:unattributed$).+/ and has its own proven-failing controls.
  • extension.ts "published CLI lacks changeset" — .changeset/u18-stage-d-mutation-context-dashboard-cli.md covers this conversion; it lives in a different chunk of the split.

Still declined: the FNXC-trace requests across the executor files. All ten already carry FNXC comments and the changed blocks are mechanical propagation of a conversion documented once at its seam; ten near-identical "attribution threaded here" notes are noise, not traceability.

CI: #3428 7/7 green, #3429 6/6, #3431#3433 all green. The only red mark is the Greptile check itself, which reports its own open findings rather than a build result.

@gsxdsm
gsxdsm force-pushed the identity/3-engine-src branch from 2127d7d to 1e03e16 Compare August 15, 2026 05:46
@gsxdsm
gsxdsm force-pushed the identity/4-engine-tests branch from 626dc8b to 6b1eba8 Compare August 15, 2026 05:46
@gsxdsm
gsxdsm force-pushed the identity/3-engine-src branch from 1e03e16 to 14d1a33 Compare August 15, 2026 22:55
@gsxdsm
gsxdsm force-pushed the identity/4-engine-tests branch from 6b1eba8 to 2ed6e5f Compare August 15, 2026 22:55
@gsxdsm
gsxdsm force-pushed the identity/3-engine-src branch from 14d1a33 to 621502b Compare August 17, 2026 23:37
@gsxdsm
gsxdsm force-pushed the identity/4-engine-tests branch from 2ed6e5f to ac4c482 Compare August 17, 2026 23:37
@gsxdsm
gsxdsm force-pushed the identity/3-engine-src branch from 621502b to 55db108 Compare August 23, 2026 23:12
…all site (4/5)

Includes the tightened ANY_MUTATION_CONTEXT matcher (it previously accepted the
"system:unattributed" marker, so every assertion using it passed whether the
write was attributed or not) plus its own proven-failing controls.

Fusion-Task-Id: FN-8821

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gsxdsm
gsxdsm force-pushed the identity/4-engine-tests branch from ac4c482 to ab5d8ca Compare August 23, 2026 23:14
gsxdsm added 5 commits August 23, 2026 19:55
Restack 4/5 onto the updated 3/5 base. Conflict resolutions keep both sides:

- executor-worktree.test.ts: 3/5 reclaim provenance (branch + branchWriteOrigin,
  including the operator-owned Fusion-namespaced case) plus 4/5 ANY_MUTATION_CONTEXT.
- identity-permissions-shadow.test.ts (add/add): union 4/5 shadow-evaluation suites
  with the 3/5 gitCases it.each corpus and null-git assertion.
The restacked 3/5 reclaim patch stamps branchWriteOrigin; pass runContextFor
on that updateTask so 4/5 ANY_MUTATION_CONTEXT assertions stay true.

Fusion-Task-Id: FN-8821
# Conflicts:
#	packages/engine/src/__tests__/executor-step-session.test.ts
log: [],
branch: "fusion/fn-permission-denied",
baseBranch: "main",
worktree: "/tmp/fusion-fn-permission-denied",
maxWorktrees: 4,
pollIntervalMs: 15000,
});
const executor = new TaskExecutor(store, "/tmp/test");

function makeExecutor() {
const store = createMockStore();
const executor = new TaskExecutor(store, "/tmp/test") as unknown as {
"FN-050",
expect.stringContaining("Cleaned up conflicting worktree, retrying"),
"/tmp/test/.worktrees/swift-falcon",
"/tmp/test/.worktrees/swift-falcon", ANY_MUTATION_CONTEXT,
expect(execMock).not.toHaveBeenCalledWith(expect.stringContaining("git worktree remove --force"), expect.anything());
expect(execMock).not.toHaveBeenCalledWith(expect.stringContaining("git branch -D"), expect.anything());
expect(store.updateTask).toHaveBeenCalledWith("FN-9001", expect.objectContaining({ worktree: "/tmp/live", branch: "fusion/fn-9001" }));
expect(store.updateTask).toHaveBeenCalledWith("FN-9001", expect.objectContaining({ worktree: "/tmp/live", branch: "fusion/fn-9001" }), UNATTRIBUTED_MUTATION_CONTEXT);
expect(recovered).toBe(1);
expect(execMock).not.toHaveBeenCalledWith(expect.stringContaining("git worktree remove --force"), expect.anything());
expect(store.updateTask).toHaveBeenCalledWith("FN-9001", expect.objectContaining({ worktree: "/tmp/live", branch: "fusion/fn-9001" }));
expect(store.updateTask).toHaveBeenCalledWith("FN-9001", expect.objectContaining({ worktree: "/tmp/live", branch: "fusion/fn-9001" }), UNATTRIBUTED_MUTATION_CONTEXT);

expect(execMock).not.toHaveBeenCalledWith(expect.stringContaining("git worktree remove --force"), expect.anything());
expect(store.updateTask).toHaveBeenCalledWith("FN-9001", expect.objectContaining({ worktree: "/tmp/live", branch: "fusion/fn-other" }));
expect(store.updateTask).toHaveBeenCalledWith("FN-9001", expect.objectContaining({ worktree: "/tmp/live", branch: "fusion/fn-other" }), UNATTRIBUTED_MUTATION_CONTEXT);
Comment thread packages/engine/src/__tests__/self-healing.test.ts Fixed
@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

ThreatCrush Security Scan

4524 finding(s)

HIGH/CRITICAL: 43 | MEDIUM: 3990 | LOW: 491

Severity Rule Location
HIGH secret-database-url .github/workflows/full-suite.yml:55
HIGH secret-generic-credential .github/workflows/full-suite.yml:56
HIGH secret-database-url .github/workflows/full-suite.yml:241
HIGH secret-generic-credential .github/workflows/full-suite.yml:242
HIGH secret-database-url .github/workflows/full-suite.yml:281
HIGH secret-generic-credential .github/workflows/full-suite.yml:282
HIGH secret-database-url .github/workflows/pr-checks.yml:214
HIGH secret-generic-credential .github/workflows/pr-checks.yml:215
HIGH secret-generic-credential .github/workflows/release.yml:522
HIGH secret-generic-credential .github/workflows/release.yml:524
HIGH secret-generic-credential .github/workflows/test-release.yml:445
HIGH secret-generic-credential .github/workflows/test-release.yml:447
HIGH secret-generic-credential docs/cli-reference.md:80
HIGH secret-generic-credential docs/signals-connectors.md:34
HIGH secret-generic-credential docs/signals-connectors.md:77
HIGH secret-generic-credential docs/signals-connectors.md:94
HIGH secret-generic-credential docs/signals-connectors.md:117
HIGH secret-generic-credential docs/signals-connectors.md:159
HIGH secret-generic-credential packages/cli/STANDALONE.md:71
HIGH secret-database-url packages/core/src/postgres/credential-redact.ts:12
HIGH secret-database-url packages/core/src/postgres/credential-redact.ts:30
HIGH secret-database-url packages/core/src/postgres/credential-redact.ts:31
HIGH secret-database-url packages/core/src/postgres/credential-redact.ts:102
HIGH secret-database-url packages/core/src/postgres/credential-redact.ts:103
HIGH secret-generic-credential packages/core/src/postgres/embedded-lifecycle.ts:843
HIGH secret-database-url packages/core/src/postgres/embedded-lifecycle.ts:1574
HIGH secret-database-url packages/core/src/postgres/pg-backup.ts:480
HIGH js-ssrf-outbound-request packages/dashboard/app/public/sw.js:651
HIGH js-ssrf-outbound-request packages/dashboard/app/public/sw.js:727
HIGH js-host-header-trust packages/dashboard/src/cli-session-ws.ts:81
HIGH js-host-header-trust packages/dashboard/src/cli-session-ws.ts:115
HIGH js-ssrf-outbound-request packages/dashboard/src/routes.ts:1857
HIGH js-host-header-trust packages/dashboard/src/server.ts:2613
HIGH js-host-header-trust packages/dashboard/src/server.ts:2638
HIGH js-host-header-trust packages/dashboard/src/server.ts:2949
HIGH js-host-header-trust packages/dashboard/src/server.ts:3117
HIGH secret-slack-webhook plugins/examples/fusion-plugin-notification/README.md:46
HIGH secret-database-url scripts/pg-test-server.mjs:200
HIGH secret-database-url scripts/pg-test-server.mjs:231
HIGH secret-database-url scripts/pg-test-server.mjs:241
HIGH secret-generic-credential scripts/sync-fusion-skill-tools.mjs:550
HIGH secret-generic-credential scripts/verify-windows-elevated-restricted.mjs:81
HIGH secret-generic-credential scripts/verify-windows-encoding-recovery.mjs:41
MEDIUM redos-nested-quantifier docs/agents.md:1710
MEDIUM insecure-temp-file packages/cli/src/__tests__/bin.test.ts:136
MEDIUM insecure-temp-file packages/cli/src/__tests__/dev-with-memory-lib.test.ts:33
MEDIUM insecure-temp-file packages/cli/src/__tests__/dev-with-memory-lib.test.ts:34
MEDIUM insecure-temp-file packages/cli/src/__tests__/dev-with-memory-lib.test.ts:35
MEDIUM insecure-temp-file packages/cli/src/__tests__/dev-with-memory-lib.test.ts:43
MEDIUM insecure-temp-file packages/cli/src/__tests__/dev-with-memory-lib.test.ts:46

…and 4474 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

# Conflicts:
#	packages/engine/src/__tests__/auto-recovery-branch-worktree.test.ts
#	packages/engine/src/__tests__/executor-execution-policy-renamed-columns.test.ts
#	packages/engine/src/__tests__/executor-graph-requeue-gate.test.ts
#	packages/engine/src/__tests__/executor-outer-dispatch-dependency-gate.test.ts
#	packages/engine/src/__tests__/executor-step-session.test.ts
#	packages/engine/src/__tests__/executor-worktree.test.ts
#	packages/engine/src/__tests__/merger-ai.test.ts
#	packages/engine/src/__tests__/merger-finalize-unproven.real-git.test.ts
#	packages/engine/src/__tests__/merger-merge-lifecycle.test.ts
#	packages/engine/src/__tests__/merger-trait-rekey.test.ts
#	packages/engine/src/__tests__/promote-force-unplanned.test.ts
#	packages/engine/src/__tests__/reliability-interactions/auto-revive-and-watchdog.test.ts
#	packages/engine/src/__tests__/reliability-interactions/merge-node-paused-abort-retryable.test.ts
#	packages/engine/src/__tests__/reliability-interactions/todo-inprogress-flapping.test.ts
#	packages/engine/src/__tests__/reliability-interactions/worktree-incomplete-session-start.test.ts
#	packages/engine/src/__tests__/replan-target.test.ts
#	packages/engine/src/__tests__/restart-recovery-coordinator.test.ts
#	packages/engine/src/__tests__/self-healing-ghost-branch-recovery.test.ts
#	packages/engine/src/__tests__/self-healing-in-progress-limbo.test.ts
#	packages/engine/src/__tests__/self-healing-query-filter-blindness.test.ts
#	packages/engine/src/__tests__/self-healing-reclaim-live-zero-commits.test.ts
#	packages/engine/src/__tests__/self-healing-reclaim-paused-review.test.ts
#	packages/engine/src/__tests__/self-healing-trait-rekey.test.ts
#	packages/engine/src/__tests__/self-healing.test.ts
#	packages/engine/src/__tests__/workflow-graph-optional-step-fix.test.ts
import * as worktreePoolModule from "../../worktree/worktree-pool.js";

function git(cwd: string, command: string): string {
return execSync(`git ${command}`, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
logEntry: vi.fn().mockResolvedValue(undefined),
moveTask: vi.fn().mockResolvedValue(undefined),
recordRunAuditEvent: vi.fn().mockResolvedValue(undefined),
getRootDir: vi.fn().mockReturnValue("/tmp/test-project"),
column: "in-progress",
paused: false,
branch: null,
worktree: "/tmp/test-project/.worktrees/missing-fn-5149",
(store.listTasks as ReturnType<typeof vi.fn>).mockResolvedValue([baseTask]);

const manager = new SelfHealingManager(store, {
rootDir: "/tmp/test-project",
vi.mocked(existsSync).mockImplementation((path) => path === baseTask.worktree);
(store.listTasks as ReturnType<typeof vi.fn>).mockResolvedValue([baseTask]);
const manager = new SelfHealingManager(store, {
rootDir: "/tmp/test-project",
it("skips tasks whose branch is still set", async () => {
(store.listTasks as ReturnType<typeof vi.fn>).mockResolvedValue([{ ...baseTask, branch: "fusion/fn-5149" }]);
const manager = new SelfHealingManager(store, {
rootDir: "/tmp/test-project",
it("skips tasks currently claimed by the executor", async () => {
(store.listTasks as ReturnType<typeof vi.fn>).mockResolvedValue([baseTask]);
const manager = new SelfHealingManager(store, {
rootDir: "/tmp/test-project",
it("skips paused tasks", async () => {
(store.listTasks as ReturnType<typeof vi.fn>).mockResolvedValue([{ ...baseTask, paused: true }]);
const manager = new SelfHealingManager(store, {
rootDir: "/tmp/test-project",
it("skips tasks still within the grace window", async () => {
(store.listTasks as ReturnType<typeof vi.fn>).mockResolvedValue([{ ...baseTask, updatedAt: "2026-05-20T12:04:30.000Z" }]);
const manager = new SelfHealingManager(store, {
rootDir: "/tmp/test-project",
});
(store.listTasks as ReturnType<typeof vi.fn>).mockResolvedValue([baseTask]);
const manager = new SelfHealingManager(store, {
rootDir: "/tmp/test-project",
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.

2 participants