From e15581a7540ca62885f9544503a1121ff1cd8168 Mon Sep 17 00:00:00 2001 From: "clagentic-builder[bot]" <290147524+clagentic-builder[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 15:32:52 -0400 Subject: [PATCH 1/2] fix(docs): remove leaked deployment values from sidecar worked example (lr-f1e995) The worked example in SIDECAR-READ-CONTRACT.md (added by lr-61cc4a) embedded local/retired deployment values in a public doc: file_prefix: crew-agent-spawn- (retired pre-lr-6fd8f4; the live prefix is subagent-) and session_id_env: CREW_SPAWN_AGENT_ID (a local harness var). Rewrite the spawn-scoped entry to neutral placeholders matching the style already used in docs/SETUP.md, and reword the surrounding prose so it no longer frames the example as "Gatekeeper's own deployed configuration cited as a concrete instance" -- the spec defect was the instruction to copy local config into a public doc. Public docs carry generalized shapes only; local implementations live in deployed config, not here. Cross-ref: lr-61cc4a (PR #21 introduced the defect). --- docs/SIDECAR-READ-CONTRACT.md | 46 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/docs/SIDECAR-READ-CONTRACT.md b/docs/SIDECAR-READ-CONTRACT.md index 29c71f4..f5159d1 100644 --- a/docs/SIDECAR-READ-CONTRACT.md +++ b/docs/SIDECAR-READ-CONTRACT.md @@ -16,9 +16,8 @@ harness exists. **No tool names are normative here.** Directory paths, filename prefixes, and environment variable names below are illustrative placeholders. Section -"Worked example" cites one deployed configuration and one reference -implementation to make the shapes concrete — it documents an example, not a -required naming scheme. +"Worked example" cites one reference implementation to make the shapes +concrete — it documents an example, not a required naming scheme. ## Convention, not coupling @@ -172,14 +171,17 @@ it. ## Worked example (illustrative — not normative naming) -Clagentic: Gatekeeper's own deployed configuration and Go reference -implementation are cited here as one concrete instance of the shapes above. -Nothing in this section is a required name, path, or environment variable -for any other consumer. +Clagentic: Gatekeeper's Go reference implementation is cited here to show +one way the shapes above can be implemented. The config snippet below uses +the same field names as `config.example.yaml`'s `attestation.sidecars`, +but the directory, prefix, and env-var values are illustrative +placeholders only — not any deployment's actual configuration. Nothing in +this section is a required name, path, or environment variable for any +other consumer; per section 6, those values always come from each +consumer's own config. **Config shape** (same fields as `config.example.yaml`'s -`attestation.sidecars`, reordered here to lead with spawn-first per -section 2 — see the note below on Gatekeeper's currently deployed order): +`attestation.sidecars`, ordered spawn-first per section 2): ```yaml attestation: @@ -187,30 +189,26 @@ attestation: # Spawn-scoped namespace — checked first, per section 2's spawn-first # resolution order. Short-lived subagent invocations, one file per # concurrent spawn. - - dir: /tmp - file_prefix: crew-agent-spawn- - session_id_env: CREW_SPAWN_AGENT_ID + - dir: + file_prefix: + session_id_env: # Session-scoped namespace — checked second. A lead/interactive - # process. Owned by LORE; prefix is not renamed (see section 7 above). - - dir: /tmp - file_prefix: lore-agent-name- - session_id_env: CLAUDE_CODE_SESSION_ID + # process. If pointed at LORE's session sidecar, its prefix is not + # renamed (see section 7 above). + - dir: + file_prefix: + session_id_env: ``` Both `dir`, `file_prefix`, and the id-env-var name are ordinary config -values (section 6) — nothing about `/tmp`, `lore-agent-name-`, or -`CLAUDE_CODE_SESSION_ID` is hardcoded in Gatekeeper's Go source. +values (section 6) — a consumer's Go (or other language) source never +hardcodes them. The order above follows section 2's spawn-first resolution recommendation. A local deployment MAY choose a different order as its own config decision — the list order is read straight from `config.yaml` and Gatekeeper's chain does not enforce spawn-before-session itself (see -"Reference read implementation" below). Gatekeeper's own currently -deployed `config.example.yaml` lists the session-scoped entry first; that -is a config ordering value to reconcile locally against section 2 (a -separate, non-doc change), and does not change the contract itself. This -worked example leads with spawn-first so it illustrates the contract's own -recommendation rather than appearing to contradict it. +"Reference read implementation" below). **Reference read implementation** ([`internal/attestation/sidecar.go`](../internal/attestation/sidecar.go)): From c892595cfe2b3010a150f7a9a7202b580b5dbe10 Mon Sep 17 00:00:00 2001 From: "clagentic-builder[bot]" <290147524+clagentic-builder[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 15:39:09 -0400 Subject: [PATCH 2/2] fix(config): remove remaining retired spawn-prefix references (lr-f1e995) Scope amendment on lr-f1e995 (comment #1, operator directive) widened this task from the docs-only fix to remove ALL remaining crew-agent-spawn-/CREW_SPAWN_AGENT_ID references repo-wide. - config.example.yaml: replace the retired file_prefix and local session_id_env in the illustrative dual-namespace sidecar block with neutral/fictional placeholder values (spawn- / MY_HARNESS_SPAWN_ID), and update the explanatory comment to match. - internal/attestation/chain_test.go, internal/config/config_test.go, cmd/gatekeeper/main_test.go: rename the fixture prefix/env-var consistently across path literals, FilePrefix fields, session_id_env values, and assertions. make check (go vet + go test ./...) is green. --- cmd/gatekeeper/main_test.go | 4 ++-- config.example.yaml | 12 +++++++----- internal/attestation/chain_test.go | 10 +++++----- internal/config/config_test.go | 8 ++++---- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/cmd/gatekeeper/main_test.go b/cmd/gatekeeper/main_test.go index 5c591fa..27a15d1 100644 --- a/cmd/gatekeeper/main_test.go +++ b/cmd/gatekeeper/main_test.go @@ -320,7 +320,7 @@ func TestRunMint_MultipleSidecarsConfig_SecondResolves(t *testing.T) { const spawnEnv = "GATEKEEPER_TEST_MAIN_SPAWN_LR86779F" t.Setenv(spawnEnv, "spawn-main-1") - spawnPath := filepath.Join(spawnDir, "crew-agent-spawn-spawn-main-1") + spawnPath := filepath.Join(spawnDir, "spawn-spawn-main-1") if err := os.WriteFile(spawnPath, []byte("peaches"), 0o600); err != nil { t.Fatalf("setup: write spawn sidecar file: %v", err) } @@ -346,7 +346,7 @@ attestation: file_prefix: lore-agent-name- session_id_env: GATEKEEPER_TEST_MAIN_SESSION_LR86779F_UNSET - dir: `+spawnDir+` - file_prefix: crew-agent-spawn- + file_prefix: spawn- session_id_env: `+spawnEnv+` `) diff --git a/config.example.yaml b/config.example.yaml index 670824a..b8ec96d 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -51,16 +51,18 @@ attestation: # spawned subagents. The example below shows both — a session-scoped # namespace (crew-manifest's write-agent-sidecar.sh, # /tmp/lore-agent-name-, keyed on CLAUDE_CODE_SESSION_ID) - # and a per-spawn namespace (/tmp/crew-agent-spawn-, keyed on - # CREW_SPAWN_AGENT_ID) — but nothing here hardcodes either plugin as a - # dependency; leave the list empty to disable this layer entirely. + # and a per-spawn namespace (/tmp/spawn-, keyed on + # MY_HARNESS_SPAWN_ID — a fictional example var; substitute your own + # harness's per-spawn env var name) — but nothing here hardcodes either + # plugin as a dependency; leave the list empty to disable this layer + # entirely. sidecars: - dir: /tmp file_prefix: lore-agent-name- session_id_env: CLAUDE_CODE_SESSION_ID - dir: /tmp - file_prefix: crew-agent-spawn- - session_id_env: CREW_SPAWN_AGENT_ID + file_prefix: spawn- + session_id_env: MY_HARNESS_SPAWN_ID # Deprecated: the legacy singular `sidecar:` block (dir/file_prefix/ # session_id_env) is still accepted for back-compat and, when fully # configured, is tried before the `sidecars:` list above. New diff --git a/internal/attestation/chain_test.go b/internal/attestation/chain_test.go index f0e051b..cfc90d8 100644 --- a/internal/attestation/chain_test.go +++ b/internal/attestation/chain_test.go @@ -103,7 +103,7 @@ func TestNewChain_MultipleSidecars_FirstMatchWins(t *testing.T) { if err := os.WriteFile(sessionPath, []byte("holden"), 0o600); err != nil { t.Fatalf("setup: write session sidecar file: %v", err) } - spawnPath := filepath.Join(spawnDir, "crew-agent-spawn-spawn-9") + spawnPath := filepath.Join(spawnDir, "spawn-spawn-9") if err := os.WriteFile(spawnPath, []byte("peaches"), 0o600); err != nil { t.Fatalf("setup: write spawn sidecar file: %v", err) } @@ -117,7 +117,7 @@ func TestNewChain_MultipleSidecars_FirstMatchWins(t *testing.T) { }, { Dir: spawnDir, - FilePrefix: "crew-agent-spawn-", + FilePrefix: "spawn-", SessionIDEnv: spawnEnv, }, }, @@ -150,7 +150,7 @@ func TestNewChain_MultipleSidecars_FirstDeclinesSecondResolves(t *testing.T) { os.Unsetenv(sessionEnv) t.Setenv(spawnEnv, "spawn-10") - spawnPath := filepath.Join(spawnDir, "crew-agent-spawn-spawn-10") + spawnPath := filepath.Join(spawnDir, "spawn-spawn-10") if err := os.WriteFile(spawnPath, []byte("bobbie"), 0o600); err != nil { t.Fatalf("setup: write spawn sidecar file: %v", err) } @@ -164,7 +164,7 @@ func TestNewChain_MultipleSidecars_FirstDeclinesSecondResolves(t *testing.T) { }, { Dir: spawnDir, - FilePrefix: "crew-agent-spawn-", + FilePrefix: "spawn-", SessionIDEnv: spawnEnv, }, }, @@ -204,7 +204,7 @@ func TestNewChain_MultipleSidecars_BothAbsent_BuiltinFallback(t *testing.T) { }, { Dir: spawnDir, - FilePrefix: "crew-agent-spawn-", + FilePrefix: "spawn-", SessionIDEnv: spawnEnv, }, }, diff --git a/internal/config/config_test.go b/internal/config/config_test.go index e7fb823..2d6955e 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -201,8 +201,8 @@ attestation: file_prefix: lore-agent-name- session_id_env: CLAUDE_CODE_SESSION_ID - dir: /tmp - file_prefix: crew-agent-spawn- - session_id_env: CREW_SPAWN_AGENT_ID + file_prefix: spawn- + session_id_env: MY_HARNESS_SPAWN_ID `) cfg, err := Load(path) @@ -216,8 +216,8 @@ attestation: if cfg.Attestation.Sidecars[0].FilePrefix != "lore-agent-name-" { t.Errorf("Sidecars[0].FilePrefix = %q, want %q", cfg.Attestation.Sidecars[0].FilePrefix, "lore-agent-name-") } - if cfg.Attestation.Sidecars[1].FilePrefix != "crew-agent-spawn-" { - t.Errorf("Sidecars[1].FilePrefix = %q, want %q", cfg.Attestation.Sidecars[1].FilePrefix, "crew-agent-spawn-") + if cfg.Attestation.Sidecars[1].FilePrefix != "spawn-" { + t.Errorf("Sidecars[1].FilePrefix = %q, want %q", cfg.Attestation.Sidecars[1].FilePrefix, "spawn-") } resolved := cfg.Attestation.ResolveSidecars()