feat(scout): remount the Context Scout producer path and Plan 20 flag - #521
Conversation
Restore the production Context Scout path parked by the V2 authority cutover: the session-lifecycle authority (registration plus exact bounded lookup from canonical durable observations), the bounded coalescing/superseding hook orchestrator behind the per-project registry, and the TraceDecay claim-authority mount/resolve that re-validates the durable address registry and the current Plan 20 configuration at claim time. The advisory hook cycle now runs run_cycle -> bind_and_assemble -> prepare_configured and mounts the claim authority on Enqueued; hook admission resolves live claim authorities instead of None, scout read surfaces answer again, and replay re-resolves native sessions through the lifecycle authority. Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
Surface context_scout.settings.v1 as one project settings flag, default off. Reads render the effective Plan 20 value; writes toggle only the state field through the existing CAS chain (preview_project_settings -> DirectConfigurationMutation::Set -> apply_configuration_batch with expected_revision_id and idempotency_key). The dashboard holds no Scout state of its own; contracts are regenerated. Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
|
Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4240396db5
ℹ️ 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".
| work_cancellation.cancel(); | ||
| false | ||
| }, | ||
| () = &mut work_future => true, |
There was a problem hiding this comment.
Preserve failed hook work for replay
When run_production_hook_cycle returns early because the feedback cycle, configuration read, model installation, lifecycle lookup, or document lookup is unavailable, its Future<Output = ()> still takes this branch and is classified as completed. settle_operation(..., true) then invokes the callback from retain_hook_v2_pending_work, which marks the ledger work completed and acknowledges the durable spool record, so a transient producer failure is permanently lost instead of retried. Return a typed work outcome and clear pending work only after a genuine terminal success.
AGENTS.md reference: AGENTS.md:L95-L97
Useful? React with 👍 / 👎.
| let execution = match cycle | ||
| .run_cycle( |
There was a problem hiding this comment.
Remount the producer after the settings revision changes
When a user enables the new Context Scout checkbox after the project is already open, the PATCH changes the configuration revision and effective digest, but this cycle still uses the FeedbackCycleLspInput pinned during project-open registration. That input rejects the new revision as feedback-cycle-configuration-drift before an execution is returned, and no configuration subscription rebuilds the advisory owner, so the producer never reaches its current-configuration re-pin or installs the enabled state until the project is reopened.
AGENTS.md reference: AGENTS.md:L9-L12
Useful? React with 👍 / 👎.
| scout_registry, | ||
| feedback_runtime: feedback_cycle.feedback_runtime(), | ||
| project_root: project_root.to_path_buf(), | ||
| indexed_files: state.indexed_files.clone(), |
There was a problem hiding this comment.
Resolve files from the current indexed generation
This permanently clones the one-time project-open file census into the producer. If project-open precedes the first sealed generation, state.indexed_files is empty; the deferred mount later computes a local census but never writes it back, so every hook remains unavailable even after indexing finishes. A mounted producer also never learns about files indexed by later generations, causing saved-edit hooks for new files to be skipped until reopen. Resolve against the maintained current generation rather than freezing this vector.
AGENTS.md reference: AGENTS.md:L141-L143
Useful? React with 👍 / 👎.
| envelope.protected_session_id, | ||
| request.lifecycle.as_ref(), |
There was a problem hiding this comment.
Key supersession by stable session identity
When the same native session advances to another tool call or turn, ContextScoutLifecycleAddressV1 changes its turn_id and logical_message_id, so including the full lifecycle here gives the newer boundary a different scheduling address. While the prior cycle holds the production orchestrator's sole permit, the new stop/edit therefore cannot find and cancel the incumbent and is backpressured instead of superseding it; the tests miss this by reusing an identical synthetic lifecycle. Hash only the stable session key while retaining the full lifecycle on the work request.
Useful? React with 👍 / 👎.
…nt-scout-claim-authority-5179
…plan' into codex/fix-pr521
…plan' into cursor/remount-scout-claim-authority-5179 Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
…rity-5179' into codex/fix-pr521
…-remount-census-edca fix(daemon): Scout P1 follow-up after #521
Summary
Recreates the Context Scout remount that was designed but never pushed (the
70b493b5awork oncursor/remount-scout-and-kimi-opencode-handlers-6c4awas lost with its VM). This resolves the A2 audit ruling ("producer parked, owner must remount or retire") by remounting the production path deleted in1caf016e5, adapted to the current lease-based daemon.Production path restored (Plans 09/22/20/37)
src/daemon/context_scout_lifecycle.rs): registration keyed by authenticated hook locators plus exact bounded lookup (64-observation budget) from canonical durable observations, fail-closed with typed lookup-failure reasons. Registered at advisory setup, unregistered exactly (same-client compare) when the published runtime retires.BoundedHookOrchestratorV1behind the per-projecthook_orchestration_registry): exact duplicate boundaries join the running cycle, a newer boundary at the same stable session address supersedes and cancels the incumbent, everything beyond permit/coalescing bounds is backpressured, owner drop cancels without false completions, and a live incumbent keeps its locator pair.run_cycle→bind_and_assemble(canonical input from the latest committed publication) →prepare_configured→ claim-authority mount onEnqueued.prepare_controlledregains its production caller throughprepare_configured.let claim_authority = Nonein hook admission is replaced with live resolution (resolve_current_context_scout_claim_authority), and the mount/resolve re-validates the durable address registry and the current Plan 20 configuration at claim time (a mid-resolve revision change never hands out a stale claim). Ready-guidance claims and the scout read surfaces (recent/explain/capability/budget) are live again; daemon replay re-resolves native sessions through the registered authority.context_scout.settings.v1value isContextScoutSettingsV1::disabled(); a disabled pin suppresses the producer, mounts no claim authority, and surfaces nothing (proven bystock_disabled_configuration_produces_nothing).ContextScoutDeliverySelectionInputV1), never model output; the deterministic path has no LLM, and the model route is typed-unavailable unless the config snapshot explicitly selectsConfiguredModel.Settings UI (Plan 20 flag only)
One project-settings checkbox rendering the effective
context_scout.settings.v1state, default off. Writes toggle only thestatefield (mode/limits/model selection are preserved) through the existing CAS chain:preview_project_settings→DirectConfigurationMutation::Set→apply_configuration_batchwithexpected_revision_id+idempotency_key. The dashboard holds no Scout state and no second flag;dashboard/src/contractsregenerated viacontracts:generate.Already satisfied on this base (verified, no change)
ContextScoutSettingsV1::disabled()is the only stock state (registry default) andvalidatealready rejects model fields outside explicitConfiguredModel.c6058b6f7(fix(hooks): restore live kimi and opencode host handlers) is an ancestor of this base;hook-kimi-event/hook-opencode-event/hook-opencode-tool-afterbypass the capture-only{}path and share thedispatch→hook_v2_admitjourney. The restoredkimi_and_opencode_queued_lifecycle_delivery_prepares_scout_lookuptest proves their lifecycle events resolve Scout lookups.Verification
cargo check --workspace --all-targets: clean, zero warnings.cargo clippy -p tracedecay -p tracedecay-usecases -p tracedecay-api -p tracedecay-dashboard-api --all-targets: clean.cargo fmt --check: clean.tracedecay --libsuite compared against the unmodified base commit in the same VM: the branch's 97 failures are a strict subset of the base's 98 (this VM's overlay filesystem fails store-locality checks for suites that don't use the tmpfs temp dir; the one extra base-only failure is a flaky scheduler-tick test). No new failures introduced.npm run typecheckclean;npm test1680/1680 across 152 files.cargo hawk check: no newdead_public; the four newunnecessary_restricted_visibilityfindings were narrowed to private.