Extract the small reusable helpers to cli-guard (junk-scan, settings-installer, hook tables, attribution, flock, semver, owner-trust, issue-ref) #269

Closed
opened 2026-06-24 07:46:11 +00:00 by coilyco-ops · 10 comments
Member

A batch of independent, low-risk extractions - each pure/self-contained, landable one at a time:

  • Reaper junk-scan policy (container_reap_compute.go: vendored/secret/oversized-blob denylist + decideReap) -> cli-guard/pkg/scan.
  • settings.json hook installer (install_hooks.go) -> beside cli-guard/cli/hook.
  • Shared hook route/integrity tables (hook.go: coilyRoutes, guardBinaryPaths, gh-GraphQL trap, detectGuard) -> cli-guard/cli/hook registry (ward carries coily's whole table today).
  • Agent attribution/signing (agent_signature.go: marker-guarded body sign + Co-Authored-By trailer) -> cli-guard/pkg/attribution.
  • flock helper (container_bootstrap_flock*.go) -> cli-guard/pkg/flock.
  • semver compare + stale-binary nag (agent_upgrade.go: parseSemver/versionBehind) -> cli-guard/pkg/version.
  • owner-trust gate (ownerAllowed, primaryOrgs) -> consume dispatch.Config.AllowedOwners.
  • issue-ref parser -> export + consume dispatch.ParseIssueRef, delete ward's copy.

From the 2026-06-24 ward/cli-guard boundary audit. See ward docs/architecture.md (the 3-layer model: cli-guard engine / ward-kdl generator / ward product). Related: ward#194, ward#200, cli-guard#139.

A batch of independent, low-risk extractions - each pure/self-contained, landable one at a time: - **Reaper junk-scan policy** (`container_reap_compute.go`: vendored/secret/oversized-blob denylist + `decideReap`) -> `cli-guard/pkg/scan`. - **settings.json hook installer** (`install_hooks.go`) -> beside `cli-guard/cli/hook`. - **Shared hook route/integrity tables** (`hook.go`: `coilyRoutes`, `guardBinaryPaths`, gh-GraphQL trap, `detectGuard`) -> `cli-guard/cli/hook` registry (ward carries coily's whole table today). - **Agent attribution/signing** (`agent_signature.go`: marker-guarded body sign + Co-Authored-By trailer) -> `cli-guard/pkg/attribution`. - **flock helper** (`container_bootstrap_flock*.go`) -> `cli-guard/pkg/flock`. - **semver compare + stale-binary nag** (`agent_upgrade.go`: `parseSemver`/`versionBehind`) -> `cli-guard/pkg/version`. - **owner-trust gate** (`ownerAllowed`, `primaryOrgs`) -> consume `dispatch.Config.AllowedOwners`. - **issue-ref parser** -> export + consume `dispatch.ParseIssueRef`, delete ward's copy. From the 2026-06-24 ward/cli-guard boundary audit. See ward docs/architecture.md (the 3-layer model: cli-guard engine / ward-kdl generator / ward product). Related: ward#194, ward#200, cli-guard#139.
Author
Member

Re-triage (goose-triage method, claude-macos-kais-macbook-pro-2 as the judgment engine, 2026-06-24)

  • P3 - Batch of low-risk self-contained helper extractions to cli-guard, kept cleanup.
  • headless - Each extraction is pure and independent, the classic headless burndown.
<!-- goose-triage --> **Re-triage** (goose-triage method, claude-macos-kais-macbook-pro-2 as the judgment engine, 2026-06-24) - **P3** - Batch of low-risk self-contained helper extractions to cli-guard, kept cleanup. - **headless** - Each extraction is pure and independent, the classic headless burndown.
Author
Member

🛫 ward pre-flight: NO-GO

ward agent headless --driver claude ran a pre-flight feasibility read on this issue before detaching a fire-and-forget run, and the agent judged it NO-GO - it should not be carried unattended until a human weighs in.

this is a cross-repo extraction (cli-guard must gain the packages and tag a release before ward can consume them), not landable to merge from a ward-only clone unattended.

No container was launched. Review the issue (clarify the scope, resolve the unknown, or split it), then re-dispatch - ward agent headless --driver claude <ref> --no-preflight skips this gate once you've decided it's good to go.

full pre-flight read

Pre-flight read

The substance here is sound and self-contained, but the structural risk is the cross-repo shape: every bullet is a move — add the helper to cli-guard, then delete ward's copy and repoint ward to consume the new cli-guard package. A fresh clone of ward alone can't land the cli-guard half, and ward can't bump its dependency until cli-guard has actually published the new pkg/scan, cli/hook registry, pkg/attribution, pkg/flock, pkg/version, and the exported dispatch.ParseIssueRef / dispatch.Config.AllowedOwners. Two of these (owner-trust, issue-ref) even say "consume dispatch.X" / "export + consume," which presumes a cli-guard change has already merged and been tagged. So the unattended run risks either producing a ward branch that won't compile (consuming symbols that don't exist upstream yet) or silently doing only the ward-side deletions — neither of which is a clean merge, and the cli-guard coordination is exactly the kind of multi-path sequencing a human should sign off on.

NO-GO: this is a cross-repo extraction (cli-guard must gain the packages and tag a release before ward can consume them), not landable to merge from a ward-only clone unattended.


Posted automatically by ward agent headless --driver claude pre-flight (ward#147, ward#149).

— Claude (she/her), via ward agent

### 🛫 ward pre-flight: NO-GO `ward agent headless --driver claude` ran a pre-flight feasibility read on this issue before detaching a fire-and-forget run, and the agent judged it **NO-GO** - it should not be carried unattended until a human weighs in. > this is a cross-repo extraction (cli-guard must gain the packages and tag a release before ward can consume them), not landable to merge from a ward-only clone unattended. No container was launched. Review the issue (clarify the scope, resolve the unknown, or split it), then re-dispatch - `ward agent headless --driver claude <ref> --no-preflight` skips this gate once you've decided it's good to go. <details><summary>full pre-flight read</summary> ## Pre-flight read The substance here is sound and self-contained, but the structural risk is the cross-repo shape: every bullet is a *move* — add the helper to **cli-guard**, then delete ward's copy and repoint ward to consume the new cli-guard package. A fresh clone of `ward` alone can't land the cli-guard half, and ward can't bump its dependency until cli-guard has actually published the new `pkg/scan`, `cli/hook` registry, `pkg/attribution`, `pkg/flock`, `pkg/version`, and the exported `dispatch.ParseIssueRef` / `dispatch.Config.AllowedOwners`. Two of these (owner-trust, issue-ref) even say "consume `dispatch.X`" / "export + consume," which presumes a cli-guard change has already merged and been tagged. So the unattended run risks either producing a ward branch that won't compile (consuming symbols that don't exist upstream yet) or silently doing only the ward-side deletions — neither of which is a clean merge, and the cli-guard coordination is exactly the kind of multi-path sequencing a human should sign off on. NO-GO: this is a cross-repo extraction (cli-guard must gain the packages and tag a release before ward can consume them), not landable to merge from a ward-only clone unattended. </details> --- Posted automatically by `ward agent headless --driver claude` pre-flight (ward#147, ward#149). <!-- ward-preflight-nogo --> <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Member

🛫 ward pre-flight: NO-GO

ward agent headless --driver claude ran a pre-flight feasibility read on this issue before detaching a fire-and-forget run, and the agent judged it NO-GO - it should not be carried unattended until a human weighs in.

most extractions must land in cli-guard first (new packages + exports), so the work can't be carried to merge from a ward-only clone — it needs coordinated cross-repo PRs and a version bump a human/CI should sequence.

No container was launched. Review the issue (clarify the scope, resolve the unknown, or split it), then re-dispatch - ward agent headless --driver claude <ref> --no-preflight skips this gate once you've decided it's good to go.

full pre-flight read

Pre-flight read

The blocking risk is that this is fundamentally a two-repo change, but the detached run only gets a fresh clone of ward. Every bullet's destination is the cli-guard repo (cli-guard/pkg/scan, .../attribution, .../flock, .../version, the cli/hook registry) or depends on cli-guard first exporting something (export + consume dispatch.ParseIssueRef, consume dispatch.Config.AllowedOwners). Landing those means a PR in cli-guard, a release/tag, then a go.mod bump in ward to consume it — a coordinated sequence I can't carry to merge from a ward-only checkout with no second-repo push surface. The triage's "headless burndown" read is right about each piece being pure and independent, but it misses that the merge target for most of them lives outside the repo I'd be detached into.

NO-GO: most extractions must land in cli-guard first (new packages + exports), so the work can't be carried to merge from a ward-only clone — it needs coordinated cross-repo PRs and a version bump a human/CI should sequence.


Posted automatically by ward agent headless --driver claude pre-flight (ward#147, ward#149).

— Claude (she/her), via ward agent

### 🛫 ward pre-flight: NO-GO `ward agent headless --driver claude` ran a pre-flight feasibility read on this issue before detaching a fire-and-forget run, and the agent judged it **NO-GO** - it should not be carried unattended until a human weighs in. > most extractions must land in cli-guard first (new packages + exports), so the work can't be carried to merge from a ward-only clone — it needs coordinated cross-repo PRs and a version bump a human/CI should sequence. No container was launched. Review the issue (clarify the scope, resolve the unknown, or split it), then re-dispatch - `ward agent headless --driver claude <ref> --no-preflight` skips this gate once you've decided it's good to go. <details><summary>full pre-flight read</summary> ## Pre-flight read The blocking risk is that this is fundamentally a **two-repo** change, but the detached run only gets a fresh clone of `ward`. Every bullet's destination is the *cli-guard* repo (`cli-guard/pkg/scan`, `.../attribution`, `.../flock`, `.../version`, the `cli/hook` registry) or depends on cli-guard first exporting something (`export + consume dispatch.ParseIssueRef`, `consume dispatch.Config.AllowedOwners`). Landing those means a PR in cli-guard, a release/tag, then a `go.mod` bump in ward to consume it — a coordinated sequence I can't carry to merge from a ward-only checkout with no second-repo push surface. The triage's "headless burndown" read is right about each piece being *pure and independent*, but it misses that the merge target for most of them lives outside the repo I'd be detached into. NO-GO: most extractions must land in cli-guard first (new packages + exports), so the work can't be carried to merge from a ward-only clone — it needs coordinated cross-repo PRs and a version bump a human/CI should sequence. </details> --- Posted automatically by `ward agent headless --driver claude` pre-flight (ward#147, ward#149). <!-- ward-preflight-nogo --> <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Member

🔁 backlog-loop dispatch - this issue was auto-dispatched by the supervised backlog loop.

When you finish, your final issue comment must start with exactly one of:

  • WARD-OUTCOME: done - landed/merged, nothing more needed.
  • WARD-OUTCOME: blocked - <the specific decision or information you need from a human>
  • WARD-OUTCOME: failed - <why, briefly>

Put your candid retrospective on the line(s) below it. The supervising loop reads this
line to decide whether to close you out, ask a human to unblock you, or retry. If you
are blocked, be concrete about the single thing you need - that is what gets answered.

<!-- backlog-loop:dispatch --> 🔁 **backlog-loop dispatch** - this issue was auto-dispatched by the supervised backlog loop. When you finish, your **final issue comment** must start with exactly one of: - `WARD-OUTCOME: done` - landed/merged, nothing more needed. - `WARD-OUTCOME: blocked - <the specific decision or information you need from a human>` - `WARD-OUTCOME: failed - <why, briefly>` Put your candid retrospective on the line(s) below it. The supervising loop reads this line to decide whether to close you out, ask a human to unblock you, or retry. If you are blocked, be concrete about the single thing you need - that is what gets answered.
Author
Member

🔒 Reserved by ward agent --driver claude — container ward-ward-issue-269-claude-edbbfa3f on host kais-macbook-pro-2.local is carrying this issue (reserved 2026-06-25T08:44:11Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `ward-ward-issue-269-claude-edbbfa3f` on host `kais-macbook-pro-2.local` is carrying this issue (reserved 2026-06-25T08:44:11Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Owner

WARD-OUTCOME: blocked - decide the cross-repo path: either re-dispatch this as a multi-repo run that grants cli-guard (ward agent <ref> --repo coilyco-flight-deck/cli-guard) so one container can author the new cli-guard packages and do the ward-side deletions together, OR split into a cli-guard-first issue (land pkg/scan, pkg/attribution, pkg/flock, pkg/version, the cli/hook registry, plus an exported ParseIssueRef, then tag a release) with a ward follow-up that bumps the pin and removes the copies.

Why I stopped here

I read the whole thread, including both earlier pre-flight NO-GO reads, then checked the ground truth rather than taking their word for it. They were right, and the container shape confirms it: /workspace granted only ward. cli-guard is a read-only /substrate reference, and pushing from there is out of bounds the same way touching any ungranted repo is.

The substance of the issue is sound, but the destination is almost entirely cli-guard:

  • Six bullets (junk-scan, settings-installer, hook tables, attribution, flock, semver) land in new cli-guard packages. I confirmed cli-guard/pkg/ has no scan, attribution, flock, or version today. They have to be authored and tagged upstream before ward can consume them.
  • owner-trust: ward's primaryOrgs/ownerAllowed is the brew-tap scope allowlist, a different concern from dispatch.Config.AllowedOwners (which owner an issue ref may come from), and dispatch's ownerAllowed is unexported. Not a drop-in - it needs a shared-abstraction decision.
  • issue-ref: dispatch.ParseIssueRef exists on cli-guard HEAD but not in ward's pinned v0.48.0, and ward's agentIssueRef (Forgejo-only, bare #N resolution, repoSlug/url/String, threaded through dozens of call sites) is a broad migration, not the "low-risk self-contained" piece described.

How it felt

Honestly, anticlimactic but clean. I came in ready to burn down eight independent extractions and instead spent the time proving a negative. The one part that surprised me was finding AllowedOwners and ParseIssueRef already exported on cli-guard HEAD with a TestParseIssueRef_Exported - for a moment it looked like bullets 7-8 might be a free ward-only win, but the pinned version gap and the semantic mismatch closed that door. I deliberately left main untouched rather than fabricate a half-change that wouldn't compile or that quietly did only the ward-side deletions. Confidence that this is genuinely blocked-not-lazy: high. The cleanest unblock is the multi-repo grant - everything here really is pure and independent once both repos are in reach.

  • Claude (she/her), via ward agent
WARD-OUTCOME: blocked - decide the cross-repo path: either re-dispatch this as a multi-repo run that grants cli-guard (`ward agent <ref> --repo coilyco-flight-deck/cli-guard`) so one container can author the new cli-guard packages and do the ward-side deletions together, OR split into a cli-guard-first issue (land `pkg/scan`, `pkg/attribution`, `pkg/flock`, `pkg/version`, the `cli/hook` registry, plus an exported `ParseIssueRef`, then tag a release) with a ward follow-up that bumps the pin and removes the copies. ### Why I stopped here I read the whole thread, including both earlier pre-flight NO-GO reads, then checked the ground truth rather than taking their word for it. They were right, and the container shape confirms it: `/workspace` granted only `ward`. cli-guard is a read-only `/substrate` reference, and pushing from there is out of bounds the same way touching any ungranted repo is. The substance of the issue is sound, but the destination is almost entirely cli-guard: - Six bullets (junk-scan, settings-installer, hook tables, attribution, flock, semver) land in **new** cli-guard packages. I confirmed `cli-guard/pkg/` has no `scan`, `attribution`, `flock`, or `version` today. They have to be authored and tagged upstream before ward can consume them. - **owner-trust**: ward's `primaryOrgs`/`ownerAllowed` is the brew-tap scope allowlist, a different concern from `dispatch.Config.AllowedOwners` (which owner an issue ref may come from), and dispatch's `ownerAllowed` is unexported. Not a drop-in - it needs a shared-abstraction decision. - **issue-ref**: `dispatch.ParseIssueRef` exists on cli-guard HEAD but not in ward's pinned `v0.48.0`, and ward's `agentIssueRef` (Forgejo-only, bare `#N` resolution, `repoSlug`/`url`/`String`, threaded through dozens of call sites) is a broad migration, not the "low-risk self-contained" piece described. ### How it felt Honestly, anticlimactic but clean. I came in ready to burn down eight independent extractions and instead spent the time proving a negative. The one part that surprised me was finding `AllowedOwners` and `ParseIssueRef` already exported on cli-guard HEAD with a `TestParseIssueRef_Exported` - for a moment it looked like bullets 7-8 might be a free ward-only win, but the pinned version gap and the semantic mismatch closed that door. I deliberately left `main` untouched rather than fabricate a half-change that wouldn't compile or that quietly did only the ward-side deletions. Confidence that this is genuinely blocked-not-lazy: high. The cleanest unblock is the multi-repo grant - everything here really is pure and independent once both repos are in reach. <!-- ward-agent-signature --> - Claude (she/her), via `ward agent`
Author
Member

Unblock decision: path B (cli-guard-first split). Matches the ward-pushes-down-into-cli-guard model.

The cli-guard-first half is filed as coilyco-flight-deck/cli-guard#166 - it lands the packages (pkg/scan, pkg/attribution, pkg/flock, pkg/version, the cli/hook registry + settings-installer, owner-trust, exported ParseIssueRef) and tags a cli-guard release.

This issue (ward#269) becomes the follow-up: once cli-guard#166 lands + releases, bump the cli-guard pin here and delete the ward-side copies. Staying blocked (depends on cli-guard#166), not re-queued.

Also gated on the headless-container dispatch fix (ward#311 / #321 / #322): cli-guard headless dispatch is currently broken (cli-guard#79 died on it), so cli-guard#166 likely needs the fix or a hand-run before either side can proceed headless.

**Unblock decision: path B (cli-guard-first split).** Matches the ward-pushes-down-into-cli-guard model. The cli-guard-first half is filed as **coilyco-flight-deck/cli-guard#166** - it lands the packages (pkg/scan, pkg/attribution, pkg/flock, pkg/version, the cli/hook registry + settings-installer, owner-trust, exported ParseIssueRef) and tags a cli-guard release. **This issue (ward#269) becomes the follow-up**: once cli-guard#166 lands + releases, bump the cli-guard pin here and delete the ward-side copies. Staying blocked (depends on cli-guard#166), not re-queued. Also gated on the headless-container dispatch fix (ward#311 / #321 / #322): cli-guard headless dispatch is currently broken (cli-guard#79 died on it), so cli-guard#166 likely needs the fix or a hand-run before either side can proceed headless.
Author
Member

🔒 Reserved by ward agent --driver claude — container ward-ward-issue-269-claude-52d078db on host kais-macbook-pro-2.local is carrying this issue (reserved 2026-06-25T10:50:50Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `ward-ward-issue-269-claude-52d078db` on host `kais-macbook-pro-2.local` is carrying this issue (reserved 2026-06-25T10:50:50Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Member

Dependency satisfied - path B ward-side follow-up is now unblocked. cli-guard#166 landed the extracted packages and cli-guard cut releases v0.58.0 and v0.59.0. cli-guard#79 also retired cli/lockdown at ba21df3.

Carry the ward side now: pin the cli-guard dependency to v0.59.0 or latest, import the moved packages from cli-guard instead of the local copies, delete the ward-side copies, and run the suite.

**Dependency satisfied - path B ward-side follow-up is now unblocked.** cli-guard#166 landed the extracted packages and cli-guard cut releases v0.58.0 and v0.59.0. cli-guard#79 also retired cli/lockdown at ba21df3. Carry the ward side now: pin the cli-guard dependency to v0.59.0 or latest, import the moved packages from cli-guard instead of the local copies, delete the ward-side copies, and run the suite.
Owner

WARD-OUTCOME: done - bumped the cli-guard pin to v0.59.0, repointed all eight helpers at their upstream packages, deleted ward's copies, and pushed to main (77188ae). Issue auto-closed via the trailer.

How it felt

Anticlimactic in the good way. Once cli-guard#166 had actually landed the packages, six of the eight were genuinely the "low-risk self-contained" consumes the triage promised - scan, install-hooks, attribution, flock, version each came out to an import swap plus a delete, net about -540 lines. The two the earlier blocked read flagged as not-drop-ins held up: I kept ward's agentIssueRef domain type and the task-verb steer and only delegated the parse to pkg/issueref, and ownerAllowed now consumes pkg/ownertrust while brew's separate primaryOrgs scope stays put. The hook-table one was the only real refactor (folding detectGuard/routesFor/guardIntegrityRules into a single wardGuardRegistry over cli-guard's hook.Registry), but every hook test drives the public runPreToolUse, so behavior stayed pinned the whole way.

Two things fought back, neither about the substance. There's a pre-existing red test on main (TestAgentLaunchSilencesDockerNoiseWhenHeadless) - it fails identically with my changes stashed, so I refused to "fix" it by rewriting an assertion I couldn't fully explain, and filed ward#335 instead. And trufflehog's binary ships via the agentic-os Brewfile and isn't in this container, so I skipped that one hook (not --no-verify - every other catalog content hook ran green).

Confidence: high. Build green, all eight extractions' tests pass, clean rebase onto main with no conflicts. The one rough edge worth a glance is whether pkg/version's zero-padded compare and pkg/issueref's error wording match ward's old behavior exactly - the tests say yes, and I read both sides, but those are the spots a subtle drift would hide.

— Claude (she/her), via ward agent

WARD-OUTCOME: done - bumped the cli-guard pin to v0.59.0, repointed all eight helpers at their upstream packages, deleted ward's copies, and pushed to main (77188ae). Issue auto-closed via the trailer. ### How it felt Anticlimactic in the good way. Once cli-guard#166 had actually landed the packages, six of the eight were genuinely the "low-risk self-contained" consumes the triage promised - scan, install-hooks, attribution, flock, version each came out to an import swap plus a delete, net about -540 lines. The two the earlier blocked read flagged as not-drop-ins held up: I kept ward's `agentIssueRef` domain type and the task-verb steer and only delegated the *parse* to pkg/issueref, and `ownerAllowed` now consumes pkg/ownertrust while brew's separate `primaryOrgs` scope stays put. The hook-table one was the only real refactor (folding `detectGuard`/`routesFor`/`guardIntegrityRules` into a single `wardGuardRegistry` over cli-guard's `hook.Registry`), but every hook test drives the public `runPreToolUse`, so behavior stayed pinned the whole way. Two things fought back, neither about the substance. There's a pre-existing red test on main (`TestAgentLaunchSilencesDockerNoiseWhenHeadless`) - it fails identically with my changes stashed, so I refused to "fix" it by rewriting an assertion I couldn't fully explain, and filed ward#335 instead. And trufflehog's binary ships via the agentic-os Brewfile and isn't in this container, so I skipped that one hook (not --no-verify - every other catalog content hook ran green). Confidence: high. Build green, all eight extractions' tests pass, clean rebase onto main with no conflicts. The one rough edge worth a glance is whether pkg/version's zero-padded compare and pkg/issueref's error wording match ward's old behavior exactly - the tests say yes, and I read both sides, but those are the spots a subtle drift would hide. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#269
No description provided.