Skip to content

fix(acp): restore canonical skill lifecycle - #4003

Open
Loxia106 wants to merge 3 commits into
Yeachan-Heo:devfrom
Loxia106:fix/acp-residual-skill-lifecycle
Open

fix(acp): restore canonical skill lifecycle#4003
Loxia106 wants to merge 3 commits into
Yeachan-Heo:devfrom
Loxia106:fix/acp-residual-skill-lifecycle

Conversation

@Loxia106

@Loxia106 Loxia106 commented Aug 7, 2026

Copy link
Copy Markdown

What

Replace the still-reproducible residual from closed #3797 on current dev@95c00d09e, without reintroducing behavior already merged in #3950/#3952/#3953/#3997/#4012.

  • route exact single-text /skill:* ACP prompts through canonical skill.invoke
  • carry real deep-interview form choices through the protocol answer source
  • keep protocol > interactive source priority with same-kind LIFO and legacy compatibility
  • fence requester-owned skill/prompt cancellation before, during, and after durable acceptance
  • forward cancellation through the turn.prompt/skill: reroute
  • preserve exact prompt/skill terminal outcomes across restart
  • retain merged permission normalization and bounded active-cancel fallback

Why

Current dev still times out before producing the real deep-interview ACP form and still allows interactive answer registration to displace protocol handling. Registry-only and synthetic skill registration checks do not cover that user-visible path.

This PR is a fresh current-dev replacement rather than a reopen of #3797. It contains only the independently reproduced residual behavior.

Testing

  • 15 focused ACP/SDK/host/reconciliation suites: 234 pass, 0 fail, 1124 assertions
  • maintainer-focused shared-lifecycle cohort: 19 pass, 0 fail
  • v0.12.19-era rebase-focused changelog + ACP cohort: 62 pass, 0 fail, 275 assertions
  • changelog/release-history guards after final placement: 17 pass, 0 fail
  • rerouted skill cancellation regression: passed, plus five repeated race runs on the current head
  • live SDK WebSocket persistence-failure regression: durable skill acceptance rejection executes nothing and releases same-clientRef admission for retry
  • real ACP CLI subprocess: /skill:deep-interview → form → selected answer → continuation/cancellation
  • bun --cwd=packages/coding-agent run check: passed
  • bun run check:tools: passed, 3424 files checked
  • independent frozen review before the release backmerges: architecture/product/code CLEAR, recommendation APPROVE; the latest rebase resolved only the changelog conflict manually, and fresh exact-head ACP/type/tool verification passed
  • executor E2E/red-team: passed, no blockers
  • full check:sdk-closure was previously attempted but exceeded 600 seconds after emitted cases remained green; no failure was observed

Exact head: fcf593f22e1663784648345f82ecfdd277318b19
Reviewed base: 95c00d09e7f68fc39469c185a4019385f331676b
Current source hash: sha256:0d145ffc7134a49843aca17c802aa9edcc328cda1bcf758c9b324a2ec50715f6

GJC verdict

gajae.pr-review-verdict.v1 merge-approved sha256:0d145ffc7134a49843aca17c802aa9edcc328cda1bcf758c9b324a2ec50715f6 reviewer:gjc evidence:234-focused-tests+maintainer-regressions+v0.12.19-rebase-verification

  • Target branch is dev
  • bun check passes
  • Tested locally
  • CHANGELOG updated (if user-facing)
  • Verdict above matches exact PR head fcf593f22e1663784648345f82ecfdd277318b19

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch 2 times, most recently from e437fd8 to af13414 Compare August 7, 2026 12:59
@Loxia106

Loxia106 commented Aug 7, 2026

Copy link
Copy Markdown
Author

Exact-head verification for the current-dev residual replacement:

gajae.pr-review-verdict.v1 merge-approved sha256:1b29ab72446e1405f0205601779190dccdf2a9ab2635be0693067def14788a1d reviewer:architect evidence:exact-head-local-cohort

@probepark probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Request changes: the lifecycle work itself reads well and is backed by a real end-to-end ACP test, but the changelog entry landed inside a released section, and the new blocking cancelPreflight await regresses turn.abort on the /skill: route that still goes through turn.prompt.

Blocking

1. packages/coding-agent/CHANGELOG.md:140 — entry added to a released section, not ## [Unreleased].

The new bullet sits under the ### Fixed heading at line 132, which belongs to ## [0.12.12] - 2026-08-05 (line 104); ## [0.12.11] follows at line 142. ## [Unreleased] is line 3 and its ### Fixed block is line 33. Root AGENTS.md is explicit: "Package changelogs live at packages/*/CHANGELOG.md; add entries under ## [Unreleased], never edit released sections." As written, a user-visible fix is retroactively attributed to a shipped release and ## [Unreleased] has no record of it.

Fix: move the bullet to the end of the ### Fixed block at line 33..55.

2. packages/coding-agent/src/session/agent-session.ts:8517-8528preflightSignal is dropped on the /skill: re-route, and cancelPreflight now blocks on the whole turn because of it.

AgentSession.prompt() re-routes a /skill:... text prompt into invokeSkill(), but forwards only onPreflightAccepted/onPreflightAcceptCommit:

await this.invokeSkill(
  invocation.skill.name,
  invocation.args,
  options?.onPreflightAccepted || options?.onPreflightAcceptCommit
    ? { ...(options.onPreflightAccepted ? { onPreflightAccepted: options.onPreflightAccepted } : {}),
        ...(options.onPreflightAcceptCommit ? { onPreflightAcceptCommit: options.onPreflightAcceptCommit } : {}) }
    : undefined,
);

sendUserMessage does carry the new signal (agent-session.ts:9693, :9749), so every other prompt path honours it — this one branch silently discards it.

That was harmless while cancelPreflight was synchronous. This PR makes it blocking (packages/coding-agent/src/sdk/bus/index.ts:2488-2496):

const cancelPreflight = async () => {
    preflightController.abort();
    if (!accepting) settlePreflight({ status: "rejected", error: cancellationError });
    try { await submission; } catch (error) { ... }
};

and abort awaits it (src/sdk/bus/index.ts:2581-2592), as does awaitAbortReady (:2405). On the /skill: re-route submission is the sendUserMessage promise, which only settles when the whole skill turn finishes, and nothing aborts it because the signal never reached #promptWithMessage. The control abort path returns preflight_cancelled without ever calling ctx.abort(), so the session-level #promptPreflightAbortController is not tripped either. Two concrete failures:

  • turn.abort (and therefore ACP session/cancel, which awaits record.adapter.cancel() at src/modes/acp/acp-agent.ts:1305) hangs until the skill turn completes — the exact "acknowledged turn still active" symptom this PR is fixing on the other route.
  • The client is told preflight_cancelled while the skill keeps running to completion.

This route is still live: acpSkillInvocation only matches when the prompt is exactly one text block (src/modes/acp/acp-agent.ts:674-676), so an ACP prompt of /skill:deep-interview <request> accompanied by any second block (resource_link, image, second text block) falls back to turn.prompt and lands here, as does any non-ACP SDK client that sends /skill:x as prompt text.

Fix: forward the signal — add ...(options?.preflightSignal ? { preflightSignal: options.preflightSignal } : {}) to the object passed to invokeSkill (and drop the onPreflightAccepted || onPreflightAcceptCommit gate so the signal alone is enough to build the options object).

Non-blocking

  • src/modes/acp/acp-agent.ts:674-680 — the doc comment says "Recognize an advertised ACP skill command", but acpSkillInvocation matches any /skill:<token> without checking it against the advertised command set built by acpAvailableCommandsFromSkills (:245). An unknown name now fails the whole session/prompt with invalid_input ("Skill X was not found"), where previously AgentSession.prompt() fell through (parseSkillInvocations returns nothing) and the text reached the model. Either check the name against the session's skills before routing, or fix the comment and add a case for the unknown-skill outcome.
  • src/modes/acp/acp-agent.ts:1209 — the frame-size probe adds ...(skillInvocation ? { confirm: false } : {}), but the real control call at :1253 sends no confirm, and confirm is only consumed for context.clear/session.delete (src/sdk/host/control/dispatch.ts:382). Harmless over-estimate, but it looks like an intent that never made it into the actual frame.
  • src/modes/acp/acp-agent.ts:1332-1336 — the new catch resets record.cancelRequested = false before rethrowing. A prompt that rejects after a failed cancel therefore no longer reports stopReason: "cancelled" (the record.cancelRequested branch at :1288 is now unreachable in that case) and surfaces the raw adapter error instead. Defensible, but it is a behaviour change from dev with no covering test.
  • src/sdk/bus/index.ts:2812-2830 — in the skill path onPromptAccepted(...) registers the submission and arms deadlineTimer before skillRecon.noteAccepted() writes the durable record. A terminal claimed in that window calls claimPendingOutcome("skill", correlation, ...) against a record that does not exist yet; kind-aware-reconciliation.ts:226-234 returns { changed: false } and the outcome is published with no durable claim behind it. Narrow, but it is the durability boundary the rest of the file is careful about.
  • src/tools/ask-answer-registry.ts:21RegisteredAskAnswerSource is exported but has no importer anywhere in the repo (only the module's own sources map uses it). AskAnswerSourceKind is genuinely needed by the signature; this one can stay unexported.
  • src/sdk/bus/index.ts:4446emitPromptFailure is now async, but the only thing that reaches it is the internal recordPromptFailure at :4473; the runtime.emitPromptFailure seam declared at :1199 and assigned at :4920 has no caller in the repo, so that half of the change is inert. Pre-existing dead seam, just flagging it since the diff touches it.

Verified

Commands actually run and their results:

  • gh pr view 4003 --json title,body,files,additions,deletions → 21 files, +1541/-206, all under packages/coding-agent.
  • git fetch upstream dev && git diff upstream/dev...HEAD (read in full, split into src/test halves) → single commit af13414db on top of b0bf3ad66.
  • awk over packages/coding-agent/CHANGELOG.md headings → ## [Unreleased] at line 3, ## [0.12.15] at 56, ## [0.12.12] at 104 with ### Fixed at 132, ## [0.12.11] at 142; the new bullet is line 140. Confirms Blocking #1.
  • Read src/session/agent-session.ts:8507-8531, :9687-9751, :7781-7835, :8713-8830sendUserMessage forwards preflightSignal, promptCustomMessage/#promptWithMessage/#withSessionAdmission honour it, and the /skill: branch of prompt() is the only place it is dropped. Confirms Blocking #2.
  • Read src/sdk/bus/index.ts:2465-2600, :4199-4268, :4339-4383, :4520-4560abort awaits cancelPendingPreflightsForConnectioncancelPreflightawait submission; terminalizePrompt is idempotent via submission.phase !== "active"; discardPromptAcceptance now clears deadlineTimer (good catch).
  • rg for registerAskAnswerSource, RegisteredAskAnswerSource, emitPromptFailure, skill.invoke, initTheme across src/test → three registration sites (interactive at bus/index.ts:2106, protocol at :3891 and :3935), skill.invoke dispatch present at src/sdk/host/control/dispatch.ts:160, initTheme(false) consistent with the other command entry points.

Things I checked and found clean: no any / ReturnType<> / inline await import() / console.* introduced in the diff; no generated artifact (packages/ai/src/models.json, schemas/*.schema.json, plugins/) touched; no TUI renderer text paths touched; the deleted assertion in test/sdk-reconciliation-recovery.test.ts:97-105 is the intentional counterpart of the relaxed pendingOutcome/kind invariant in reconciliation-store.ts:91-95; test/acp-deep-interview-wire.test.ts spawns the real CLI in --mode acp against a fixture model server, so the new routing is exercised end to end rather than stubbed; test/extensions-runner.test.ts:92-113 asserts the new options object actually reaches invokeSkill.

I have not yet run the package typecheck or the focused unit tests; I will follow up on this PR with those results.

@probepark

Copy link
Copy Markdown
Collaborator

Verification follow-up to my review above. Both blocking findings stand; one additional non-blocking issue surfaced.

bun --cwd=packages/coding-agent run check → passes. biome check . checked 2603 files with 1 warning (test/smithery-env-trust.test.ts:23 unused KEYS, pre-existing, not touched by this PR), and tsc -p tsconfig.json --noEmit reported no errors. So the voidPromise<void> widening of onPromptFailed/emitPromptFailure/cancelPendingPreflights* and the new ReconciliationKind parameters typecheck cleanly.

bun test packages/coding-agent/test/sdk-ask-answer-source-priority.test.ts packages/coding-agent/test/sdk-kind-aware-reconciliation.test.ts packages/coding-agent/test/sdk-reconciliation-store.test.ts16 pass, 3 fail (19 tests, 1.88s). The reconciliation-store and kind-aware-reconciliation tests all pass. The three failures are all in the new test/sdk-ask-answer-source-priority.test.ts:

(fail) falls back to the interactive source after disposing the protocol source   (:87)
(fail) keeps a protocol source ahead of a legacy two-argument interactive registration (:112)
(fail) returns undefined when no source is registered                            (:154)

Non-blocking, but worth fixing: this is test-isolation, not product behaviour. registerAskAnswerSource writes into a module-global Map keyed by session id (src/tools/ask-answer-registry.ts:26), and the first, second and fourth cases never call the returned disposer for the sources they register. That is only safe while every fixture session has a distinct id — and it does not, when the suite runs from inside a gjc lifecycle session: SessionManager.inMemory()#freshSessionState (src/session/session-manager.ts:5501) adopts lifecyclePreallocatedSessionId() (:1231-1236) whenever GJC_LIFECYCLE_REQUEST_ID and GJC_SESSION_ID are set, so all five createAgentSession fixtures share one registry key. The leaked protocol entry from the second case then wins findLast(entry => entry.kind === "protocol") for every later case, which is exactly the observed pattern: the two cases that assert "a protocol source wins" pass for the wrong reason, and the three that assert absence or fallback fail.

Fix: dispose every registration in each case (all five registerAskAnswerSource calls return a disposer), or drop the createAgentSession fixtures entirely and use literal unique session ids — the registry is a plain module-level map and needs no real session, which also removes five full agent-session constructions from a pure unit test.

My environment had those variables set; a clean CI environment would generate fresh UUIDv7 ids and the file would pass. That is precisely why it should not depend on them.

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch from af13414 to ef61547 Compare August 8, 2026 01:44
@Loxia106

Loxia106 commented Aug 8, 2026

Copy link
Copy Markdown
Author

Addressed the requested changes and rebased onto current dev.

Exact publication boundary:

  • head: ef615471142a5d2465f677d92602b02e18a7190c
  • base: d14dde9ceb8230828651a2e0497735b25c2104ab
  • source: sha256:8b931051fb824d9a4a1f007953bac2201287a44c1d399d1590f1437e0f09a361

Blocking findings:

  1. CHANGELOG placement — moved the ACP lifecycle entry out of released 0.12.12 and into Unreleased → Fixed. Cumulative diff now has exactly one occurrence, before the first released heading.
  2. Dropped reroute cancellation signalAgentSession.prompt() now includes preflightSignal when constructing invokeSkill options, including when it is the only option. Added a direct regression that holds the rerouted skill preflight, aborts the signal, and proves the prompt rejects with busy instead of continuing. Five repeated race runs passed.

Follow-up test isolation:

  • Replaced heavyweight createAgentSession fixtures with explicit registry session keys.
  • Every answer-source registration now uses its disposer in finally.
  • With inherited shared lifecycle identity: 19 pass, 0 fail across the exact three suites from the review.

Non-blocking notes:

  • Renamed the classifier comment from “advertised” to “canonical” and added the explicit syntactic unknown-name case. Unknown canonical names intentionally reach skill.invoke, whose host returns typed invalid_input.
  • The frame estimate’s confirm:false is the actual wire shape: AcpSdkAdapter.control calls SdkClient.control(..., { confirm: false }), and bridge-client serializes defined confirm values into the control frame. Added an inline source comment at the estimator.
  • Failed cancel intent reset is covered by the production test: an unacknowledged abort rejects, then the correlated prompt completes with end_turn rather than being mislabeled cancelled.
  • Pre-durable skill acceptance cancellation and persistence failure roll back process-local ownership/admission; post-durable cancellation claims the exact skill outcome. The forced persistence-failure regression still passes and same-clientRef retry succeeds.
  • RegisteredAskAnswerSource is now module-private.
  • The existing unused runtime emitPromptFailure seam was not expanded.

Verification:

  • focused ACP lifecycle cohort: 234 pass, 0 fail, 1124 assertions
  • package check: passed
  • tool check: passed, 3424 files
  • only warning: pre-existing unused KEYS in smithery-env-trust.test.ts
  • independent architect: CLEAR / APPROVE
  • executor E2E/red-team: passed, no blockers
  • cumulative diff: 22 focused coding-agent paths, git diff --check clean

gajae.pr-review-verdict.v1 merge-approved sha256:8b931051fb824d9a4a1f007953bac2201287a44c1d399d1590f1437e0f09a361 reviewer:architect evidence:exact-head-maintainer-fix-cohort

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch from ef61547 to e7a092a Compare August 8, 2026 10:50
@Loxia106

Loxia106 commented Aug 8, 2026

Copy link
Copy Markdown
Author

Rebased again after the v0.12.16 release backmerge.

Exact publication boundary:

  • head: e7a092a4b72ad090f7ff4965179ef675674d3e97
  • base: 3bddcc579717eb47eedafc9db29a86aa86c4438a
  • canonical source hash: sha256:51772977c5910511b69e4725cd754b3e55ca5a3990405988ab036d36bfc214e5

The rebase was mechanically clean, but the new ## [0.12.16] heading would have semantically captured this PR's ACP bullet even though #4003 was not in that release. The bullet is explicitly restored under ## [Unreleased]### Fixed; released history is unchanged.

Fresh verification on the exact head:

  • focused changelog + ACP lifecycle cohort: 62 passed, 0 failed
  • changelog/release-history guards after the final placement edit: 17 passed, 0 failed
  • rerouted-skill preflight cancellation race: 5/5 repeated passes
  • bun --cwd=packages/coding-agent run check: passed
  • bun run check:tools: passed
  • git diff --check upstream/dev: passed

The native addon was rebuilt locally for the v0.12.16 sentinel before running the suites. @probepark the two original blocking fixes remain intact on the current release base and are ready for re-review.

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch from e7a092a to 4391b2b Compare August 9, 2026 00:24
@Loxia106

Loxia106 commented Aug 9, 2026

Copy link
Copy Markdown
Author

Rebased once more onto current dev after the v0.12.18/v0.12.19 release movement and resolved the resulting changelog conflict.

Exact publication boundary:

  • head: 4391b2b76924f6a416c25f104bd60252aa407c33
  • base: 0bb36ee8858bcb1c528768936265aea4afaa8b9b
  • canonical source hash: sha256:851e1490000c89da79078c7def2bfbe520c66f4f36e107607f36853dfe8c10d2

Resolution:

  • retained both new upstream Unreleased → Fixed entries
  • retained this PR's ACP lifecycle entry exactly once under the same Unreleased → Fixed section
  • did not modify released changelog history
  • acp-agent.ts merged automatically; no manual source conflict was required

Fresh exact-head verification:

  • focused changelog + ACP lifecycle cohort: 62 passed, 0 failed, 275 assertions
  • rerouted-skill cancellation race: 5/5 repeated passes
  • coding-agent package check: passed
  • tool check: passed, 3425 files checked
  • git diff --check upstream/dev: passed

@probepark the original changelog and preflightSignal blockers remain fixed on the latest target branch and are ready for re-review.

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch from 4391b2b to 63429ad Compare August 9, 2026 02:27
@Loxia106

Loxia106 commented Aug 9, 2026

Copy link
Copy Markdown
Author

Exact-head receipt refreshed after a history-only normalization.

  • head: 63429ad01b2dfa3a01f2a95e1a40a3d59ea632b8
  • base: 0bb36ee8858bcb1c528768936265aea4afaa8b9b
  • canonical source hash: sha256:851e1490000c89da79078c7def2bfbe520c66f4f36e107607f36853dfe8c10d2

The source tree is byte-identical to the previously verified head (tree 0cc57fee4ccef3a7ba80cb70fe8f7097cdfcaf77), so the existing exact-source test and review evidence remains unchanged.

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch from 63429ad to 488c55a Compare August 9, 2026 02:31
@Loxia106

Loxia106 commented Aug 9, 2026

Copy link
Copy Markdown
Author

Exact-head receipt refreshed after synchronization with the current target branch.

  • head: 488c55a128d8826ef5b9246bf05849cbd7767660
  • base: db3040fe5cc02b4da7477c5e062c00ccbc886021
  • canonical source hash: sha256:887fda7968d142d3d2cfc9f2ecc197e2c2b750344fbeae8c0b1a869f66eed924

Fresh verification on this head:

  • focused changelog + ACP lifecycle cohort: 62 passed, 0 failed, 275 assertions
  • rerouted-skill cancellation race: 5/5 repeated passes
  • coding-agent package check: passed
  • tool check: passed, 3435 files checked
  • git diff --check upstream/dev: passed

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch from 488c55a to e1148fb Compare August 9, 2026 04:43
@Loxia106

Loxia106 commented Aug 9, 2026

Copy link
Copy Markdown
Author

Exact-head receipt refreshed after synchronization with the current target branch.

  • head: e1148fb1dd8e1ef11329b2b2e7230955a1c7dd31
  • base: 31c00c2d5bb462464046208a94a4597c27260a4c
  • canonical source hash: sha256:84a8d919c24d2563f841b129dfa57178d3ffe5b5183a44a35d690e8a72f98513

The changelog conflict was resolved by retaining current upstream released history unchanged and placing this PR's ACP lifecycle entry exactly once under Unreleased → Fixed.

Fresh verification:

  • focused changelog + ACP lifecycle cohort: 62 passed, 0 failed, 275 assertions
  • rerouted-skill cancellation race: 5/5 repeated passes
  • coding-agent package check: passed
  • tool check: passed, 3439 files checked
  • git diff --check upstream/dev: passed

@Yeachan-Heo

Copy link
Copy Markdown
Owner

OWNER_CONFIRMATION_REQUIRED

I cannot attest merge readiness for the live head e1148fb1dd8e1ef11329b2b2e7230955a1c7dd31: this dedicated checkout has dev@31c00c2d5 and only stale origin/pr-4003-head@af13414d, so no local source or test evidence is attributable to the proposed merge commit. GitHub currently reports mergeable: null, mergeableState: unknown, and no check runs for e1148.

Please have the active repair owner/maintainer refresh the same-SHA source and CI evidence, resolve or dismiss probepark’s outstanding CHANGES_REQUESTED review, and confirm the #3797 timeline/linkage. Loxia106 already owns the latest e1148 repair receipt; this comment intentionally does not duplicate that evidence.

— GJC Red Team

ACP skill prompts still bypassed canonical skill invocation on current dev, so deep-interview forms never reached protocol clients and interactive answer sources could displace protocol ownership. Route exact skill prompts through durable requester-owned lifecycle fencing while preserving the merged permission channel.

Lore-id: 9c4b817e
Constraint: protocol answer sources outrank interactive sources with same-kind LIFO
Constraint: retain merged ACP permission normalization and cancellation behavior
Rejected: registry-only skill tests | they do not prove the real ACP form path
Confidence: high
Scope-risk: wide
Reversibility: clean-revert
Tested: 211 focused ACP/SDK tests, coding-agent check, and check:tools
Not-tested: full SDK closure gate (timed out after 600 seconds without an observed failure)
Prompt-text skill routing dropped the SDK preflight signal, so turn.abort could acknowledge cancellation while the skill kept running. Forward the signal, add a direct regression, isolate answer-source tests from lifecycle session ids, and restore the changelog entry to Unreleased.

Lore-id: 40d7ac91
Constraint: preflight cancellation must stop rerouted skill execution before acknowledgement
Constraint: answer-source tests must not depend on process lifecycle session ids
Confidence: high
Scope-risk: narrow
Reversibility: clean-revert
Tested: rerouted skill cancellation regression and 19 maintainer-focused tests
The 0.12.16 release backmerge inserted a released heading ahead of the ACP entry, which would falsely attribute the pending PR to that release. Restore the entry under Unreleased after rebasing onto current dev.

Constraint: package changelog entries must remain under Unreleased until shipped

Tested: changelog and release-history guards; focused ACP lifecycle tests; coding-agent and tool checks
@Yeachan-Heo

Copy link
Copy Markdown
Owner

REQUEST_CHANGES

Exact-head review cannot clear the current dev baseline. Live fork head is e1148fb1dd8e1ef11329b2b2e7230955a1c7dd31; live origin/dev is 95c00d09e7f68fc39469c185a4019385f331676b; their merge base is 31c00c2d5bb462464046208a94a4597c27260a4c. The head is therefore 3 commits ahead but 8 commits behind current dev, including 4bc916577 fix(acp): reject unknown command flags and 911910d96 fix(sdk): stop broker and session host leaks, which overlap the ACP/SDK lifecycle risk surface.

The contributor evidence is bound to the old base 31c00c2d5, not current dev. Rebase onto current dev, resolve/revalidate the ACP/SDK lifecycle contract, and publish exact-head targeted CI evidence. Red-dev failures must remain separately attributed. No maintainer repair is opened because the contributor branch remains active and no handoff authorizes duplicate ownership.

Evidence: git ls-remote https://github.com/Loxia106/gajae-code.git refs/heads/fix/acp-residual-skill-lifecycle; git ls-remote origin refs/heads/dev; git merge-base e1148fb1... 95c00d09...; git rev-list --left-right --count e1148fb1...95c00d09... = 3 8.

@Loxia106
Loxia106 force-pushed the fix/acp-residual-skill-lifecycle branch from e1148fb to fcf593f Compare August 9, 2026 05:38
@Loxia106

Loxia106 commented Aug 9, 2026

Copy link
Copy Markdown
Author

Exact-head receipt refreshed after synchronization with the current target branch.

  • head: fcf593f22e1663784648345f82ecfdd277318b19
  • base: 95c00d09e7f68fc39469c185a4019385f331676b
  • canonical source hash: sha256:0d145ffc7134a49843aca17c802aa9edcc328cda1bcf758c9b324a2ec50715f6

Conflict reconciliation retained the current pre-submit Phase A/Phase B retry builder and the prompt-cancellation reset fence immediately before durable acceptance. Released changelog history is unchanged, while the ACP lifecycle entry remains exactly once under Unreleased → Fixed.

Fresh verification:

  • focused changelog + ACP lifecycle cohort: 62 passed, 0 failed
  • session-context overflow/pre-submit suite: 20 passed, 0 failed
  • rerouted-skill cancellation race: 5/5 repeated passes
  • coding-agent package check: passed
  • tool check: passed, 3464 files checked
  • git diff --check upstream/dev: passed

@Loxia106

Loxia106 commented Aug 9, 2026

Copy link
Copy Markdown
Author

CI follow-up for the current exact head:

  • The ACP/reconciliation jobs, package check, type build, native build, CLI smoke, state gates, and production-host isolation all passed.
  • The sdk-host-wiring Q17 ENOENT failure reproduces unchanged on a detached worktree at the exact base 95c00d09e; it is not introduced by this PR.
  • The base agent-session-concurrent file also reproduces an existing nondeterministic prompt timeout without this PR. On the PR head, the file passes in isolation (22/22), including the rerouted-skill cancellation regression, and that regression passes 5/5 repeated runs.
  • The CI-only durable-acceptance expectation mismatch does not reproduce either focused or in the full local host-wiring file; the full file reaches 95/96 with only the base Q17 failure.

No unrelated baseline test repair was added to this ACP lifecycle PR.

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.

3 participants