Skip to content

Matrix-gap sprint: kill mid-run for 6 more runtimes + Cursor/Copilot pre-tool gates - #5009

Open
vivekchand wants to merge 5 commits into
mainfrom
feat/governance-matrix-gaps
Open

Matrix-gap sprint: kill mid-run for 6 more runtimes + Cursor/Copilot pre-tool gates#5009
vivekchand wants to merge 5 commits into
mainfrom
feat/governance-matrix-gaps

Conversation

@vivekchand

Copy link
Copy Markdown
Owner

What

The public capability matrix claims Kill mid-run ✓ for Codex/OpenCode/Aider/Goose — but the shipped cloud Stop button never worked for them: the relay carries no cwd, the daemon never backfilled it, and resolve_by_cwd refused with no_cwd. Family session rows never persisted cwd either. This PR makes the promised cells true and extends kill/pause to every runtime the 2026-08-19 recon proved resolvable.

process_control

  • copilot: strong pid map from ~/.copilot/logs/process-<epoch_ms>-<pid>.log (Workspace initialized: <sid> body marker) — pid from the filename, epoch_ms doubles as the pid-reuse-guard start token. Verified live on Copilot CLI 1.0.77–1.0.80 (SIGTERM is graceful: session.shutdown written, --resume works after).
  • qwen_code: qwen-code's own pid sidecar <projects>/<hash>/chats/<sid>.runtime.json ({pid, session_id, work_dir} — written explicitly for observability daemons). Its started_at is the write time, so the resolver uses identity cross-checks (argv contains qwen + live cwd == work_dir) instead of the start-token guard.
  • pi / grok / deepseek_harness / kimi: argv+cwd. pi/dsh are exact-basename hints (substring would hit pip/python/any path containing "dsh").
  • cursor: CLI (cursor-agent) sessions resolve by cwd — one process tree per session; the IDE stays honestly unsupported.

sync.py daemon dispatch

  • cwd backfill: when the relay omits cwd, look it up from the session row (new local_store.get_session_location) — fixes the broken codex/goose/opencode/aider path end-to-end.
  • KILL_HANDLERS first: the pro-registered n8n / antigravity / nanoclaw API kills now fire from the Stop button, not only on approval deny.
  • nemoclaw routes through the openclaw CLI cancel instead of a guaranteed runtime_not_signal_supported.

family ingest

  • Session rows persist cwd/git_branch (alias walk, incl. goose workingDir); family event rows stamp workspace_id so approvals._session_cwd_hint stops returning ''. /cwd1 ingest-rev salt re-ingests existing sessions once to heal the column.

local emergency stop honesty

  • /api/sessions/<sid>/stop for family sids routed to the real pid engine instead of writing a .stop file nothing reads and returning ok:true.

Tests

13 new: copilot E2E kill incl. pid-reuse guard refusal, qwen sidecar identity guards, exact-hint semantics, handler-first dispatch, cwd backfill, nemoclaw routing. Full test_process_control.py (33) + test_sync_process_control_dispatch.py (13) green.

Companion PRs: clawmetry-pro (adapter cwd promotion + Copilot $0.01/credit + QM cost) and clawmetry-cloud (gate lists + dialog copy).

🤖 Generated with Claude Code

The governance matrix promised Kill for Codex/OpenCode/Aider/Goose, but the
shipped cloud Stop button never worked for them: the relay carries no cwd and
resolve_by_cwd refuses with no_cwd. Family session rows never persisted cwd
either, so there was nothing to backfill from. This PR makes the promised
cells true and extends kill/pause to the runtimes recon proved resolvable:

- process_control: copilot (pid from ~/.copilot/logs/process-<ms>-<pid>.log,
  "Workspace initialized: <sid>" body marker; verified live on 1.0.77-1.0.80),
  qwen_code (qwen-code's own pid sidecar <projects>/<hash>/chats/
  <sid>.runtime.json with identity cross-checks instead of its unreliable
  started_at), pi/grok/deepseek_harness/kimi via argv+cwd. "pi"/"dsh" are
  exact-basename hints (substring would hit pip/python). Cursor CLI sessions
  (cursor-agent) resolve by cwd; the IDE stays honestly unsupported.
- sync.py _run_process_control: backfill cwd from the session row (new
  local_store.get_session_location) when the relay omits it; consult
  approvals.KILL_HANDLERS first so the pro-registered n8n / antigravity /
  nanoclaw API kills fire from the Stop button, not only on approval deny;
  route nemoclaw through the openclaw CLI cancel instead of a guaranteed
  runtime_not_signal_supported.
- family ingest: persist cwd/git_branch on session rows (alias walk incl.
  goose workingDir) and stamp events.workspace_id so approvals'
  _session_cwd_hint stops returning ''. /cwd1 ingest-rev salt re-ingests
  existing sessions once to heal the column.
- routes/sessions.py emergency stop: family sids now route to the real
  pid engine instead of writing a .stop file nothing reads and reporting
  ok:true (silent fake success).

Tests: 13 new (copilot E2E kill incl. pid-reuse guard, qwen sidecar identity
guards, exact-hint semantics, handler-first dispatch, cwd backfill).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Visual diff

Comparing 032d8b82a55c (head) against the PR base branch.

37 of 66 comparison(s) flagged (>1% pixel diff).

View Before After Diff
desktop overview ⚠️ before after diff · 100.00%
desktop flow before after diff · 0.09%
desktop brain before after diff · 0.01%
desktop usage before after diff · 0.00%
desktop crons before after diff · 0.33%
desktop memory before after diff · 0.02%
desktop security ⚠️ before after diff · 2.53%
desktop subagents before after diff · 0.00%
desktop transcripts ⚠️ before after diff · 2.91%
desktop logs ⚠️ before after diff · 4.61%
desktop skills before after diff · 0.26%
desktop models before after diff · 0.00%
desktop approvals ⚠️ before after diff · 3.73%
desktop alerts before after diff · 0.00%
desktop notifications before after diff · 0.10%
desktop limits before after diff · 0.00%
desktop clusters ⚠️ before after diff · 1.66%
desktop history before after diff · 0.00%
desktop channels ⚠️ before after diff · 1.54%
desktop dives ⚠️ before after diff · 1.97%
desktop harness ⚠️ before after diff · 4.05%
desktop inventory ⚠️ before after diff · 2.08%
desktop nemoclaw ⚠️ before after diff · 2.63%
desktop policy before after diff · 0.00%
desktop selfevolve before after diff · 0.01%
desktop swimlane before after diff · 0.00%
desktop tool-catalog before after diff · 0.41%
desktop tracing ⚠️ before after diff · 3.23%
desktop turn-anatomy before after diff · 0.33%
desktop version-impact ⚠️ before after diff · 2.11%
desktop context-economics ⚠️ before after diff · 3.42%
desktop agents ⚠️ before after diff · 2.42%
desktop evals before after diff · 0.01%
mobile overview ⚠️ before after diff · 100.00%
mobile flow ⚠️ before after diff · 6.03%
mobile brain before after diff · 0.38%
mobile usage before after diff · 0.14%
mobile crons ⚠️ before after diff · 4.21%
mobile memory before after diff · 0.01%
mobile security ⚠️ before after diff · 100.00%
mobile subagents ⚠️ before after diff · 1.66%
mobile transcripts ⚠️ before after diff · 3.97%
mobile logs ⚠️ before after diff · 100.00%
mobile skills ⚠️ before after diff · 100.00%
mobile models before after diff · 0.01%
mobile approvals ⚠️ before after diff · 5.39%
mobile alerts ⚠️ before after diff · 4.14%
mobile notifications before after diff · 0.00%
mobile limits ⚠️ before after diff · 100.00%
mobile clusters before after diff · 0.10%
mobile history ⚠️ before after diff · 3.06%
mobile channels ⚠️ before after diff · 100.00%
mobile dives ⚠️ before after diff · 1.65%
mobile harness ⚠️ before after diff · 100.00%
mobile inventory before after diff · 0.02%
mobile nemoclaw ⚠️ before after diff · 100.00%
mobile policy ⚠️ before after diff · 100.00%
mobile selfevolve before after diff · 0.49%
mobile swimlane ⚠️ before after diff · 100.00%
mobile tool-catalog before after diff · 0.01%
mobile tracing before after diff · 0.00%
mobile turn-anatomy ⚠️ before after diff · 100.00%
mobile version-impact ⚠️ before after diff · 100.00%
mobile context-economics before after diff · 0.01%
mobile agents ⚠️ before after diff · 100.00%
mobile evals ⚠️ before after diff · 100.00%

Folder: 032d8b82a55c. Full PNGs also attached as a workflow artefact.

Generated by visual-diff bot. Pixel diffs >1% flagged; eyeball the table before merging. This check is non-blocking — fail = bot bug, not a code problem.

…ol gates)

The matrix's "Block before it runs" column was Claude Code-only. Both Cursor
and Copilot CLI ship native hook systems that can DENY a tool call before it
executes (verified live 2026-08-19: Cursor 3.16 hooks.json beforeShellExecution
deny surfaces to the model; Copilot CLI 1.0.80 preToolUse deny blocked a shell
command with our reason). This wires them into the SAME approvals engine the
Claude Code PreToolUse gate uses:

- clawmetry/runtime_gates.py (new, stdlib-only): cursor + copilot gate
  installers (GATE_HANDLERS entries driven by sync_runtime_gates) and hook
  clients. Cursor: non-destructive merge into ~/.cursor/hooks.json on
  beforeShellExecution + beforeMCPExecution (+ beforeReadFile when a policy
  covers reads), marker-owned entries only, state-file uninstall. Copilot:
  we own the whole $COPILOT_HOME/hooks/clawmetry.json file (Copilot loads
  every hooks/*.json), so install/uninstall can never clobber foreign
  entries. Fail-open contract preserved end to end: the clients always exit
  0 and print nothing on failure (= "no opinion").
- routes/hooks.py: the pretooluse receiver is now per-runtime
  (/api/hooks/<slug>/pretooluse for claude-code|cursor|copilot) so a Cursor
  pause is filed as a cursor approval, not a claude_code one; and policies
  are runtime-scope filtered (a policy pinned to claude_code no longer
  gates other runtimes), mirroring sync_runtime_gates.
- cli.py fast path: `clawmetry hook cursor|copilot --base <url>` (stdlib-
  only, translates the runtime's payload/response shapes: Cursor
  {"permission": ...}, Copilot {"permissionDecision": ...,
  "permissionDecisionReason": ...}; Copilot toolArgs arrives as a JSON
  string and is parsed).
- hooks_installed.json markers for cursor/copilot so the reactive watcher
  never double-files approvals for calls the hook already paused.

Tests: 13 new (installer merge/idempotence/uninstall-only-ours, risk-policy
read-event, whole-file copilot ownership, client payload/response mapping
incl. JSON-string toolArgs, fail-open, per-runtime receiver stamping,
runtime-scoped policy isolation, registry entries).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand vivekchand changed the title Kill mid-run for 6 more runtimes + fix the silently-broken cwd kill path Matrix-gap sprint: kill mid-run for 6 more runtimes + Cursor/Copilot pre-tool gates Aug 19, 2026
Drift-bot on clawmetry-pro#148 flagged that the blueprint wants cwd as a
first-class Session field, not only an extra["cwd"] mirror. Add it to the
dataclass (default "", exported in to_dict) and prefer it in the family
upsert over the metadata alias walk. Adapters keep mirroring into
extra["cwd"] while pre-cwd OSS wheels are in the fleet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 5 potential drift finding(s)

1. Blueprint: Extended Runtime Support

File: clawmetry/process_control.py:72

The PR extends kill/pause support to Cursor CLI sessions (resolve_cursor function at line 1102+), but the blueprint and codebase documentation consistently state that Cursor is intentionally unsupported because one IDE process holds every session. The documentation comment previously stated cursor is "explicitly UNSUPPORTED for per-session signals"; now CLI sessions are supported but IDE sessions remain unsupported.

2. Requirement: Extended Runtime Support

File: clawmetry/process_control.py:1195

The requirement AC-GOV-ERS-001.3 specifies that unavailable runtimes must not be presented as available. The PR adds Cursor to SUPPORTED_RUNTIMES (line 90-91) but Cursor IDE sessions remain unsupported — only CLI sessions are killable, creating a split implementation where the same runtime is both supported and unsupported depending on session type.

3. Blueprint: Governance Policy and Approval

File: clawmetry/runtime_gates.py:1

The blueprint specifies in ADR-002 that unverified control actions "remain unavailable or explicitly preview-only," but the PR adds pre-execution gates for Cursor and Copilot without documented end-to-end release verification. The gates are fully operational and not marked as preview-only or gated behind verification flags.

4. Blueprint: Governance and Human Approval

File: routes/hooks.py:248

The blueprint specifies that #AttentionHookReceiver is "strictly observational" and "MUST NOT fail in a way that could stall the calling runtime." However, the new generic hook handler (_pretooluse_impl) at line 319 applies runtime-scoped policy filtering which could introduce new failure modes for Cursor and Copilot hooks that were not present before the addition of runtime gating.

5. Blueprint: Runtime and Session Observability

File: clawmetry/adapters/base.py:114

The Session class adds a new cwd field (line 119) as first-class but the blueprint's documentation does not specify this as a required field on Session records. The comment indicates adapters "should ALSO mirror it into extra[cwd]" for backward compatibility with older wheels, introducing a redundancy not documented in the blueprint contract.

#
# copilot (GitHub Copilot CLI) has a claude_code-grade strong resolution: each
# run writes ``~/.copilot/logs/process-<epoch_ms>-<pid>.log`` whose body logs
# ``Workspace initialized: <session_id>`` — pid comes from the FILENAME and the

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Extended Runtime Support

The PR extends kill/pause support to Cursor CLI sessions (resolve_cursor function at line 1102+), but the blueprint and codebase documentation consistently state that Cursor is intentionally unsupported because one IDE process holds every session. The documentation comment previously stated cursor is "explicitly UNSUPPORTED for per-session signals"; now CLI sessions are supported but IDE sessions remain unsupported.

if info.get("ok") or not cwd:
return info
return resolve_by_cwd(runtime, cwd)
if runtime == "qwen_code":

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Requirement: Extended Runtime Support

The requirement AC-GOV-ERS-001.3 specifies that unavailable runtimes must not be presented as available. The PR adds Cursor to SUPPORTED_RUNTIMES (line 90-91) but Cursor IDE sessions remain unsupported — only CLI sessions are killable, creating a split implementation where the same runtime is both supported and unsupported depending on session type.

github-actions Bot pushed a commit that referenced this pull request Aug 19, 2026
@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 6 potential drift finding(s)

1. Blueprint: Extended Runtime Support

File: clawmetry/process_control.py:88

Cursor added to SUPPORTED_RUNTIMES with clipboard note stating "cursor is omitted on purpose," but the blueprint specifies Cursor IDE sessions remain unsupported. Only CLI sessions should resolve; the implementation adds Cursor to the supported set without distinguishing IDE vs CLI sessions in SUPPORTED_RUNTIMES.

2. Blueprint: Governance and Human Approval

File: clawmetry/runtime_gates.py:1

The new runtime_gates.py file implements pre-execution tool gates for Cursor and Copilot CLI, but this implementation is not mentioned or documented in the "Governance Policy and Approval" blueprint. The blueprint should document the runtime-gates module and its role in the gating workflow.

3. Blueprint: Governance and Human Approval

File: routes/hooks.py:268

The _pretooluse_impl function now applies runtime-scoped policy filtering, but the blueprint's "Governance and Human Approval" states that #AttentionHookReceiver "MUST NOT fail in a way that could stall the calling runtime." The new generic handler filters policies by runtime before matching, potentially introducing new failure modes not present before runtime gating was added.

4. Requirement: Extended Runtime Support

File: clawmetry/process_control.py:88

AC-GOV-ERS-001.3 specifies "When the extension is absent or not entitled, the system shall not present the runtime as available." Cursor IDE sessions cannot be stopped (remain unsupported per AC-GOV-ERS-005.2), but adding Cursor to SUPPORTED_RUNTIMES presents it as available regardless of session type.

5. Blueprint: Runtime and Session Observability

File: clawmetry/adapters/base.py:119

The Session class adds a new cwd field (line 119) as first-class, documented as required for kill/pause pid resolution, but the blueprint's "Runtime and Session Observability" does not specify cwd as a required first-class Session field. The implementation comment indicates adapters should also mirror it into extra[cwd] for backward compatibility, adding redundancy not documented.

6. Blueprint: Governance and Human Approval

File: routes/hooks.py:315

The implementation applies runtime-scoped policy filtering within _pretooluse_impl using ap._policies_for_runtime(ap.load_policies(), runtime), but the Governance blueprint does not document this runtime-scoping behavior in the pre-tool gate contract. The comment states "mirrors sync_runtime_gates" but sync_runtime_gates is not documented in the blueprint.

#
# kimi / pi / grok / deepseek_harness are per-terminal CLI processes resolved
# by argv+cwd like codex; "pi" and "dsh" are exact-basename matches (see
# _EXACT_ARGV_HINTS) because substring matching would hit pip/python or any

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Extended Runtime Support

Cursor added to SUPPORTED_RUNTIMES with clipboard note stating "cursor is omitted on purpose," but the blueprint specifies Cursor IDE sessions remain unsupported. Only CLI sessions should resolve; the implementation adds Cursor to the supported set without distinguishing IDE vs CLI sessions in SUPPORTED_RUNTIMES.

@@ -0,0 +1,491 @@
"""Pre-tool gates for Cursor and GitHub Copilot CLI — "block before it runs".

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance and Human Approval

The new runtime_gates.py file implements pre-execution tool gates for Cursor and Copilot CLI, but this implementation is not mentioned or documented in the "Governance Policy and Approval" blueprint. The blueprint should document the runtime-gates module and its role in the gating workflow.

Comment thread routes/hooks.py


@bp_hooks.route("/api/hooks/<slug>/pretooluse", methods=["POST"])
def api_hook_runtime_pretooluse(slug):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance and Human Approval

The _pretooluse_impl function now applies runtime-scoped policy filtering, but the blueprint's "Governance and Human Approval" states that #AttentionHookReceiver "MUST NOT fail in a way that could stall the calling runtime." The new generic handler filters policies by runtime before matching, potentially introducing new failure modes not present before runtime gating was added.

@vivekchand

Copy link
Copy Markdown
Owner Author

Drift-bot triage (6 findings, round 2):

  • Findings 1 & 4 are factually wrong about the code. Cursor is NOT in SUPPORTED_RUNTIMES — the set at clawmetry/process_control.py:90 is {claude_code, codex, goose, opencode, aider, copilot, qwen_code, pi, grok, deepseek_harness, kimi} and UNSUPPORTED_RUNTIMES = {"cursor"} is unchanged. Cursor resolution is split per session in resolve_cursor(): CLI (cursor-agent) sessions resolve by cwd; editor conversations return the explicit unsupported result. That split is now specified in the Extended Runtime Support blueprint (v11, ADR-ERS-005) and requirement (v2, AC-GOV-ERS-005.2).
  • Findings 2, 5, 6 read stale spec versions. The runtime-gates module is documented in Governance Policy and Approval v7 ("Pre-execution tool gates for Cursor and GitHub Copilot CLI", ADR-GPA-004 covers the per-runtime receivers + runtime-scoped policy filtering); first-class Session.cwd incl. the extra-mirror-is-diagnostic contract is in Runtime and Session Observability v16 and requirement v5 (AC-RSO-CWD-001.*); the per-runtime receiver + scoping behavior is also in Governance and Human Approval v7. All patched before this run — the bot appears to have read pre-patch versions (same stale-read behavior as on Sell the plan in the modal, and let people switch accounts #4986).
  • Finding 3 conflates two components. The "strictly observational" contract belongs to the AttentionHookReceiver, which this PR does not touch. _pretooluse_impl is the deciding receiver (the existing claude-code gate), and its fail-open contract is unchanged: any policy-engine or store failure answers allow with a reason — the runtime-scope filter runs inside the same try/except and its failure mode is that same fail-open allow. Spelled out in Governance and Human Approval v7.

Separately: every other check on this round died in 2s with "account is locked due to a billing issue" — GitHub Actions billing needs a human fix before CI can rerun (same lock is blocking the 0.12.738 publish per the fleet notes).

@vivekchand

Copy link
Copy Markdown
Owner Author

Live E2E of the Copilot gate on a real machine (2026-08-20, Copilot CLI 1.0.80, real credits spent):

  1. Installed the gate hook file (~/.copilot/hooks/clawmetry.json, preToolUseclawmetry hook copilot --base http://127.0.0.1:8903) against this branch's receiver with a require_approval policy (runtime: copilot, pattern clawmetry-e2e-gate, timeout: 5, on_timeout: deny).
  2. Ran a REAL turn: copilot -p "Run exactly this shell command…: echo clawmetry-e2e-gate-test-1" --allow-all. The shell call was parked in the approval queue, timed out to deny, and Copilot surfaced it to the model: "Cannot run the command here — a pre-execution policy blocked the shell call." (0.47 credits, 26.5k↑/535↓ tokens.)
  3. Approval row landed with the RIGHT attribution: requestor_session_id = copilot:8f8bebab-c672-… — exactly the session id Copilot printed in its own --resume line — runtime: copilot, policy: e2e-gate-copilot, status: denied.
  4. Control run with an ungated command executed normally (gate answered allow, tool ran).
  5. Hook file removed after the test; the receiver's log shows the client's park/re-POST loop hitting /api/hooks/copilot/pretooluse.

Cursor's deny path was separately verified live during recon (a beforeReadFile/beforeShellExecution deny surfaces to the model with the hook's reason — an existing transcript in ~/.cursor/projects/... shows a real blocked Read).

Copy link
Copy Markdown
Owner Author

blocked on author decision — skipping (auto-mergeability sweep)

The latest CI round (run IDs 32315217XXX, starting 23:54:49 UTC) failed in 2 seconds across all checks — consistent with the billing lock you described. The initial CI run (visual-diff screenshots generated at 22:21 UTC) ran to completion. No mechanical code fix available here; the block clears once the billing issue is resolved and a fresh CI run completes.


Generated by Claude Code

@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 4 potential drift finding(s)

1. Requirement: Extended Runtime Support

File: clawmetry/process_control.py:72

AC-GOV-ERS-005.2 specifies Cursor support must be per-session (CLI stoppable, IDE unsupported) and states "A split runtime is never labeled wholly available." However, the code adds "cursor" to SUPPORTED_RUNTIMES as a blanket classification, failing to distinguish session type at the set level.

2. Blueprint: Governance and Human Approval

File: clawmetry/runtime_gates.py

The new runtime_gates.py module implements pre-tool gates for Cursor and Copilot CLI, but this module and its role in the pre-tool gating workflow is not mentioned or documented in the "Governance and Human Approval" blueprint.

3. Blueprint: Runtime and Session Observability

File: clawmetry/adapters/base.py:119

The Session dataclass adds cwd as a first-class field, documented as required for kill/pause pid resolution. However, the blueprint's section on session location (ADR-010) describes cwd as extracted and normalized at ingest, not as a first-class Session field that adapters must populate.

4. Blueprint: Governance and Human Approval

File: routes/hooks.py:320

The pre-tool receiver now filters policies to the calling runtime before matching (ap._policies_for_runtime). The Governance blueprint's "Per-runtime pre-tool receivers" section does not document this runtime-scoped filtering behavior in the pre-tool gate contract.

#
# copilot (GitHub Copilot CLI) has a claude_code-grade strong resolution: each
# run writes ``~/.copilot/logs/process-<epoch_ms>-<pid>.log`` whose body logs
# ``Workspace initialized: <session_id>`` — pid comes from the FILENAME and the

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Requirement: Extended Runtime Support

AC-GOV-ERS-005.2 specifies Cursor support must be per-session (CLI stoppable, IDE unsupported) and states "A split runtime is never labeled wholly available." However, the code adds "cursor" to SUPPORTED_RUNTIMES as a blanket classification, failing to distinguish session type at the set level.

# (process_control.resolve_by_cwd); adapters should ALSO mirror it into
# extra["cwd"] while older OSS wheels without this field are in the
# fleet (a pro adapter passing cwd= against an old wheel would crash).
cwd: str = ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Runtime and Session Observability

The Session dataclass adds cwd as a first-class field, documented as required for kill/pause pid resolution. However, the blueprint's section on session location (ADR-010) describes cwd as extracted and normalized at ingest, not as a first-class Session field that adapters must populate.

Copy link
Copy Markdown
Owner Author

Merge blocker: drift-bot (4 findings)

The drift-bot required commit status is failing. Per FLYWHEEL.md §1f, drift-bot checks that code changes match the architectural blueprints in Factory.ai — a required status check.

What needs updating:
This PR expands process control capabilities (signals, session kill, pause surfaces). The "Control Plane" blueprint and/or the "Process Control" section in Factory.ai needs to be updated to describe these new or expanded process control surfaces.

To fix:

  1. Open the Software Factory skill: npx skills add 8090-inc/software-factory-plugin
  2. Update the Control Plane / Process Control blueprint sections to document the expanded capabilities this PR adds
  3. Sync blueprints → re-trigger CI → drift-bot should clear (4 findings, likely one per surface added)

Generated by Claude Code

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.

1 participant