@hegemonart/get-design-done 1.26.0 → 1.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +74 -0
  4. package/README.md +10 -8
  5. package/SKILL.md +3 -0
  6. package/agents/README.md +29 -0
  7. package/package.json +2 -2
  8. package/reference/peer-cli-capabilities.md +151 -0
  9. package/reference/peer-protocols.md +266 -0
  10. package/reference/registry.json +14 -0
  11. package/reference/runtime-models.md +3 -3
  12. package/scripts/install.cjs +100 -1
  13. package/scripts/lib/bandit-router.cjs +214 -7
  14. package/scripts/lib/budget-enforcer.cjs +69 -1
  15. package/scripts/lib/event-stream/index.ts +14 -1
  16. package/scripts/lib/event-stream/types.ts +125 -1
  17. package/scripts/lib/install/runtimes.cjs +58 -0
  18. package/scripts/lib/peer-cli/acp-client.cjs +375 -0
  19. package/scripts/lib/peer-cli/adapters/codex.cjs +101 -0
  20. package/scripts/lib/peer-cli/adapters/copilot.cjs +79 -0
  21. package/scripts/lib/peer-cli/adapters/cursor.cjs +78 -0
  22. package/scripts/lib/peer-cli/adapters/gemini.cjs +81 -0
  23. package/scripts/lib/peer-cli/adapters/qwen.cjs +72 -0
  24. package/scripts/lib/peer-cli/asp-client.cjs +587 -0
  25. package/scripts/lib/peer-cli/broker-lifecycle.cjs +406 -0
  26. package/scripts/lib/peer-cli/registry.cjs +434 -0
  27. package/scripts/lib/peer-cli/spawn-cmd.cjs +149 -0
  28. package/scripts/lib/runtime-detect.cjs +1 -1
  29. package/scripts/lib/session-runner/index.ts +362 -0
  30. package/scripts/lib/session-runner/types.ts +60 -0
  31. package/scripts/validate-frontmatter.ts +159 -1
  32. package/skills/peer-cli-add/SKILL.md +170 -0
  33. package/skills/peer-cli-customize/SKILL.md +110 -0
  34. package/skills/peers/SKILL.md +101 -0
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: peer-cli-add
3
+ description: "Guided ladder for adding a brand-new peer (a peer not in the v1.27 capability matrix) to the gdd peer-CLI delegation layer. Verification ladder + adapter scaffolding + capability-matrix update + Windows quirks documented. Run when you discover a new peer CLI you want gdd to delegate to."
4
+ argument-hint: "<new-peer-id> <peer-binary> <protocol: acp|asp>"
5
+ tools: Read, Edit, Write, Bash, Grep
6
+ ---
7
+
8
+ <!-- Procedural pattern adapted from greenpolo/cc-multi-cli's `multi-cli-anything` skill (Apache 2.0). See NOTICE for full attribution. -->
9
+
10
+ # peer-cli-add
11
+
12
+ ## Role
13
+
14
+ You add a brand-new peer-CLI to gdd's delegation layer. v1.27.0 ships 5 peers (codex, gemini, cursor, copilot, qwen). When the user wants a 6th — a peer that exists in the wild but isn't in our capability matrix yet — they run this skill. It walks them through a verification ladder (does the peer actually speak ACP or ASP?) and produces the 3-file footprint that integrates the peer cleanly.
15
+
16
+ ## Invocation Contract
17
+
18
+ - **Required input**: `<new-peer-id>` (lowercase identifier, e.g., `aider`), `<peer-binary>` (the executable name, e.g., `aider` or `aider.cmd`), `<protocol>` (`acp` or `asp`).
19
+ - **Output**: a 3-file diff + a verification report.
20
+
21
+ ## Procedure
22
+
23
+ ### Step 1 — Verification ladder (no edits yet)
24
+
25
+ Before touching any code, confirm the peer actually speaks the protocol it claims.
26
+
27
+ #### 1a. Binary on PATH
28
+
29
+ `which <peer-binary>` (POSIX) or `where <peer-binary>` (Windows). If exit non-zero, stop and ask user to install the peer first.
30
+
31
+ #### 1b. Handshake test
32
+
33
+ Spawn the peer with the appropriate protocol entry point:
34
+ - ACP peers: `<peer-binary> acp` (or whatever the peer documents as its ACP entry — Gemini uses `gemini acp`; some peers use a flag).
35
+ - ASP peers: `<peer-binary> app-server` (Codex's convention; other ASP peers may differ).
36
+
37
+ Send an `initialize` JSON-RPC message over stdin with `protocolVersion: '2025-06-18'` (ACP) or `service_name: 'gdd_peer_delegation'` (ASP).
38
+
39
+ Capture the reply on stdout. If the reply is a valid JSON-RPC response with `result.protocolVersion` (ACP) or `result.threadId` (ASP), the peer speaks the protocol.
40
+
41
+ If no valid reply within 5 seconds, the peer either doesn't speak this protocol or uses a non-standard entry point. Stop and ask the user for the correct invocation.
42
+
43
+ #### 1c. Model-ID `-preview`-suffix trap
44
+
45
+ Many peers expose preview models with a `-preview` suffix (e.g., `gpt-5-preview` vs `gpt-5`). The suffix drifts: today's preview is tomorrow's GA. Capture the peer's current model list (most peers expose `<peer-binary> models` or similar). Note any model that has `-preview` in its name and document the parent name in the new entry's `provider_model_id` field — so the runtime-models.md entry can survive the suffix flipping.
46
+
47
+ #### 1d. Windows quirks
48
+
49
+ If the peer-binary ends in `.cmd` and the user is on Windows, confirm the spawn-cmd shell-escape logic from `scripts/lib/peer-cli/spawn-cmd.cjs` will pick it up (it should — that module already handles `.cmd` detection per Plan 27-03 / D-04). Document any other Windows-specific quirks in the new adapter's leading comment.
50
+
51
+ ### Step 2 — Generate the adapter scaffold
52
+
53
+ Use the existing 5 adapters at `scripts/lib/peer-cli/adapters/{codex,gemini,cursor,copilot,qwen}.cjs` as templates. Pick the closest match to your new peer's protocol (ASP if `<protocol> = asp`, otherwise ACP).
54
+
55
+ Use the `Write` tool to create `scripts/lib/peer-cli/adapters/<new-peer-id>.cjs`:
56
+
57
+ ```js
58
+ 'use strict';
59
+
60
+ const { createAcpClient } = require('../acp-client.cjs');
61
+ // OR for ASP peers: const { createAspClient } = require('../asp-client.cjs');
62
+
63
+ const ROLES_CLAIMED = ['<role-1>', '<role-2>']; // ASK USER which roles this peer claims
64
+ const ROLE_PREFIX = {
65
+ '<role-1>': '<prompt prefix or empty string>',
66
+ '<role-2>': '<prompt prefix or empty string>',
67
+ };
68
+
69
+ function claims(role) { return ROLES_CLAIMED.includes(role); }
70
+
71
+ async function dispatch({ command, args, cwd, env }, role, text, opts) {
72
+ if (!claims(role)) {
73
+ throw new Error(`<new-peer-id> does not claim role: ${role}`);
74
+ }
75
+ const client = createAcpClient({ command, args, cwd, env });
76
+ try {
77
+ await client.initialize({ protocolVersion: '2025-06-18' });
78
+ const prompt = (ROLE_PREFIX[role] || '') + text;
79
+ return await client.prompt(prompt, { onNotification: opts?.onNotification });
80
+ } finally {
81
+ await client.close();
82
+ }
83
+ }
84
+
85
+ module.exports = { claims, dispatch, ROLES_CLAIMED, ROLE_PREFIX, name: '<new-peer-id>', protocol: '<protocol>' };
86
+ ```
87
+
88
+ Replace placeholders with the user's input from Step 1's verification.
89
+
90
+ ### Step 3 — Add `peerBinary` to runtimes.cjs
91
+
92
+ Edit `scripts/lib/install/runtimes.cjs` to add an entry for the new peer. Mirror the shape of the 5 existing peer entries. Add the `peerBinary` field with platform-aware resolution:
93
+
94
+ ```js
95
+ {
96
+ id: '<new-peer-id>',
97
+ // ... existing fields per Phase 24 runtime matrix shape ...
98
+ peerBinary: process.platform === 'win32' ? '<peer-binary>.cmd' : '<peer-binary>',
99
+ }
100
+ ```
101
+
102
+ ### Step 4 — Add the capability-matrix entry
103
+
104
+ Edit `reference/peer-cli-capabilities.md`. Add a new row to the top capability matrix table AND a new per-peer section. Follow the existing format. Cite the verification evidence from Step 1.
105
+
106
+ ### Step 5 — Update the registry capability matrix
107
+
108
+ Edit `scripts/lib/peer-cli/registry.cjs`. Add the new peer to the `CAPABILITY_MATRIX` constant (and `KNOWN_PEERS` if that's a separate list). Mirror the shape of the 5 existing entries.
109
+
110
+ ### Step 6 — Verify the integration
111
+
112
+ Run, in this order, until each passes:
113
+
114
+ 1. `npx tsc --noEmit` — clean.
115
+ 2. `node --test tests/peer-cli-registry.test.cjs tests/peer-cli-adapters.test.cjs` — no regression on existing tests.
116
+ 3. `node --test tests/reference-registry.test.cjs` — capability-matrix doc is in registry.json (if you added it).
117
+ 4. `npm run validate:frontmatter` — no agent's `delegate_to:` field is broken by the new entry.
118
+
119
+ If any step fails, surface the error and offer to revert the changes.
120
+
121
+ ### Step 7 — Surface a 3-file footprint summary
122
+
123
+ ```
124
+ ## peer-cli-add summary
125
+
126
+ Added peer: <new-peer-id> (protocol: <protocol>)
127
+ Roles claimed: <role-1>, <role-2>
128
+
129
+ Files modified:
130
+ ✓ scripts/lib/peer-cli/adapters/<new-peer-id>.cjs (new)
131
+ ✓ scripts/lib/install/runtimes.cjs (added peerBinary entry)
132
+ ✓ reference/peer-cli-capabilities.md (added matrix row + per-peer section)
133
+ ✓ scripts/lib/peer-cli/registry.cjs (added to CAPABILITY_MATRIX)
134
+
135
+ Verification:
136
+ ✓ tsc clean
137
+ ✓ existing peer-cli tests pass
138
+ ✓ reference-registry round-trip valid
139
+ ✓ frontmatter validator: 0 violations
140
+
141
+ Next steps:
142
+ - Run /gdd:peers to confirm the new peer shows up in the capability matrix.
143
+ - Run skills/peer-cli-customize/SKILL.md to wire delegate_to: <new-peer-id>-<role> on specific agents.
144
+ - Phase 23.5 bandit will need ~5 cycles of data before the posterior surfaces a recommendation for this peer.
145
+ ```
146
+
147
+ ## Edge cases
148
+
149
+ - **Peer speaks neither ACP nor ASP** — gdd v1.27 ships only those two protocols. Stop and document the gap in `.design/RESEARCH.md` for a future phase to consider adding a new protocol layer.
150
+ - **Peer claims a role no existing peer claims** (e.g., `translate`) — fine, capability matrix is open. But document the role in `reference/peer-cli-capabilities.md` so future peers can compete on it.
151
+ - **Peer claims ALL roles** (e.g., a generalist peer) — accept, but flag in the per-peer section. Generalist peers are usually weaker than specialist peers; the bandit will sort it out via measurement.
152
+ - **Peer name conflicts with an existing peer-id** — fail. Peer-IDs must be globally unique. Suggest a disambiguating suffix.
153
+ - **User wants to add a peer for testing only** — same flow, but suggest committing under a separate branch and not adding to the install-time detection nudge until the peer is production-ready.
154
+
155
+ ## Cross-references
156
+
157
+ - `scripts/lib/peer-cli/registry.cjs` (Plan 27-05) — capability matrix data.
158
+ - `scripts/lib/peer-cli/adapters/*.cjs` (Plan 27-04) — adapter template.
159
+ - `scripts/lib/peer-cli/spawn-cmd.cjs` (Plan 27-03) — Windows .cmd handling.
160
+ - `reference/peer-cli-capabilities.md` (Plan 27-05) — capability-matrix doc.
161
+ - `skills/peer-cli-customize/SKILL.md` — once new peer is added, use customize to wire it on specific agents.
162
+ - `.planning/phases/27-peer-cli-delegation/CONTEXT.md` D-02, D-05 — decision lineage.
163
+
164
+ ## Record
165
+
166
+ After execution, append one JSONL line to `.design/skill-records.jsonl`:
167
+
168
+ ```json
169
+ {"skill": "peer-cli-add", "ts": "<ISO timestamp>", "new_peer": "<new-peer-id>", "protocol": "<protocol>", "roles_claimed": ["<role-1>"], "verification_passed": true}
170
+ ```
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: peer-cli-customize
3
+ description: "Rewire role→peer mappings on a per-agent basis. File-edit-driven (touches frontmatter delegate_to: per agent), no runtime config layer. Run when you want a specific agent to delegate to a different peer than the default capability-matrix mapping suggests."
4
+ argument-hint: "[<agent-name>] [<new-delegate-target>]"
5
+ tools: Read, Edit, Bash, Grep
6
+ ---
7
+
8
+ <!-- Procedural pattern adapted from greenpolo/cc-multi-cli's `customize` skill (Apache 2.0). See NOTICE for full attribution. -->
9
+
10
+ # peer-cli-customize
11
+
12
+ ## Role
13
+
14
+ You help the user rewire which peer-CLI delegate handles which agent's calls. The mechanism is direct file-edits to agent frontmatter (`delegate_to:` field added in Plan 27-06) — there is no runtime config layer. Your job is to make this safe and validatable.
15
+
16
+ ## Invocation Contract
17
+
18
+ - **Optional input**: agent-name + new delegate target. If absent, the skill runs in interactive discovery mode.
19
+ - **Output**: a diff summary listing each `agents/*.md` file modified, the old vs new `delegate_to:` value, and the validation result.
20
+
21
+ ## Procedure
22
+
23
+ ### Step 1 — Show current state
24
+
25
+ Read the capability matrix from `scripts/lib/peer-cli/registry.cjs#describeCapabilities()`. Surface the 5 peers and their claimed roles to the user.
26
+
27
+ Then scan `agents/*.md` and grep for `delegate_to:` frontmatter values. Render a table:
28
+
29
+ ```
30
+ | Agent | delegate_to (current) |
31
+ |----------------------------|------------------------|
32
+ | design-reflector | none |
33
+ | design-context-checker | (unset) |
34
+ | design-verifier | gemini-research |
35
+ | ... | ... |
36
+ ```
37
+
38
+ ### Step 2 — Confirm rewire intent
39
+
40
+ Either accept the user's explicit `<agent-name> <new-delegate-target>` arguments OR ask: "Which agent do you want to rewire? What should `delegate_to:` become?"
41
+
42
+ Valid `<new-delegate-target>` values:
43
+ - `<peer>-<role>` from the capability matrix (e.g., `gemini-research`, `codex-execute`, `cursor-debug`, `cursor-plan`, `copilot-review`, `copilot-research`, `qwen-write`).
44
+ - `none` (explicit opt-out).
45
+ - Empty / `(unset)` to remove the field entirely (revert to default behavior).
46
+
47
+ ### Step 3 — Validate the proposed rewire
48
+
49
+ Cross-check the new value against the capability matrix:
50
+ 1. The peer must exist in the matrix.
51
+ 2. The role must be in the peer's `claims` list.
52
+ 3. The peer must (eventually, at runtime) be in `.design/config.json#peer_cli.enabled_peers` for dispatch to fire — but that's a runtime concern, not a frontmatter validation concern.
53
+
54
+ If validation fails, surface the error and stop. Do not edit the file.
55
+
56
+ ### Step 4 — Apply the edit
57
+
58
+ Use the `Edit` tool to modify the agent's frontmatter. Three cases:
59
+
60
+ **Case A: Field is absent, user wants to add it.**
61
+ Insert `delegate_to: <new-target>` into the frontmatter block (between the existing `default-tier:` and the next field, or at the end of frontmatter). Preserve YAML formatting.
62
+
63
+ **Case B: Field is present, user wants to change the value.**
64
+ Replace the existing value. If the existing value is `none` and the new value is `<peer>-<role>`, just swap. Mirror the existing indentation.
65
+
66
+ **Case C: Field is present, user wants to remove it.**
67
+ Delete the entire `delegate_to:` line. The field is optional — absence === default behavior.
68
+
69
+ ### Step 5 — Re-validate via the frontmatter validator
70
+
71
+ Run `npm run validate:frontmatter` (or whatever the project's frontmatter check is). Confirm the modified agent passes. If validation fails, surface the error and offer to revert.
72
+
73
+ ### Step 6 — Surface a diff summary
74
+
75
+ Report back:
76
+
77
+ ```
78
+ ## Rewire summary
79
+
80
+ ✓ design-verifier: delegate_to: gemini-research → cursor-debug
81
+ ✓ design-reflector: delegate_to (unset) → codex-execute
82
+
83
+ frontmatter validator: 0 violations (40 files checked)
84
+ next time these agents are spawned, session-runner will dispatch through the new peer.
85
+
86
+ To verify: /gdd:peers (shows updated allowlist + capability matrix).
87
+ ```
88
+
89
+ ## Edge cases
90
+
91
+ - **User asks to rewire to a peer not in the capability matrix** (e.g., a peer they want to add later): direct them to `skills/peer-cli-add/SKILL.md` first; do not allow the frontmatter edit until the peer exists in the matrix.
92
+ - **User asks to rewire to a role the peer doesn't claim** (e.g., `codex-debug` — codex only claims `execute`): refuse with a helpful message listing what the peer DOES claim. Suggest a closer match if obvious.
93
+ - **User asks to rewire ALL agents to a peer at once** (bulk operation): support but require explicit confirmation. Show the diff of all proposed edits before applying.
94
+ - **Validator fails after edit**: revert the edit (re-run `Edit` with the inverse old/new strings). Surface the original error.
95
+
96
+ ## Cross-references
97
+
98
+ - `scripts/validate-frontmatter.ts` (Plan 27-06) — `delegate_to` field validation.
99
+ - `scripts/lib/peer-cli/registry.cjs` (Plan 27-05) — capability matrix.
100
+ - `agents/README.md#peer-cli-delegation-delegate_to` — field documentation.
101
+ - `skills/peer-cli-add/SKILL.md` — for adding a NEW peer (this skill is for rewiring among existing peers).
102
+ - `.planning/phases/27-peer-cli-delegation/CONTEXT.md` D-06 — decision lineage.
103
+
104
+ ## Record
105
+
106
+ After execution, append one JSONL line to `.design/skill-records.jsonl`:
107
+
108
+ ```json
109
+ {"skill": "peer-cli-customize", "ts": "<ISO timestamp>", "agents_rewired": ["design-verifier", "design-reflector"], "validator_passed": true}
110
+ ```
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: gdd-peers
3
+ description: "Discover peer-CLI capability matrix — which of {codex, gemini, cursor, copilot, qwen} are installed, allowlisted in .design/config.json, and (if Phase 23.5 has data) their cost/quality delta vs local. Single command, no flags. Read by users investigating delegation setup."
4
+ argument-hint: ""
5
+ tools: Read, Bash
6
+ ---
7
+
8
+ # gdd-peers
9
+
10
+ ## Role
11
+
12
+ You are a deterministic discovery skill. You do not spawn agents and do not delegate to peers. You read `scripts/lib/install/runtimes.cjs`, `scripts/lib/peer-cli/registry.cjs`, `.design/config.json`, and (optionally) `.design/intel/bandit-posterior.json`, then emit a single Markdown table summarizing peer-CLI status.
13
+
14
+ ## Invocation Contract
15
+
16
+ - **Input**: none. The skill takes no arguments.
17
+ - **Output**: a Markdown capability-matrix table to stdout. No JSON wrapper. The table is the entire output.
18
+
19
+ ## Procedure
20
+
21
+ ### 1. Load runtime matrix
22
+
23
+ Read `scripts/lib/install/runtimes.cjs` and extract the 14 runtime entries. The 5 peer-capable entries (`codex`, `gemini`, `cursor`, `copilot`, `qwen`) carry a `peerBinary?` field (added in Plan 27-11). Collect their IDs and binary paths.
24
+
25
+ ### 2. Load capability matrix
26
+
27
+ Read `scripts/lib/peer-cli/registry.cjs`. The exported `describeCapabilities()` returns the per-peer claimed-roles map. The capability matrix is the source of truth for which roles each peer can take.
28
+
29
+ Use the canonical declared matrix:
30
+
31
+ | Peer | Roles claimed | Protocol |
32
+ |---------|--------------------------|----------|
33
+ | codex | execute | ASP |
34
+ | gemini | research, exploration | ACP |
35
+ | cursor | debug, plan | ACP |
36
+ | copilot | review, research | ACP |
37
+ | qwen | write | ACP |
38
+
39
+ ### 3. Detect installation
40
+
41
+ For each peer, run `which <peerBinary>` (POSIX) or `where <peerBinary>` (Windows). If exit 0 → installed. If exit non-zero → not installed.
42
+
43
+ ### 4. Read allowlist
44
+
45
+ Read `.design/config.json`. The path is `peer_cli.enabled_peers` — an array of peer-IDs. Default: `[]` (empty, opt-in required). If the file or path is missing, treat as empty.
46
+
47
+ ### 5. (Optional) Read posterior win-rate
48
+
49
+ If `.design/intel/bandit-posterior.json` exists, look up the per-peer last-N-cycle delta (cost or correctness, whichever is the bandit's primary signal). For each peer, compute the average reward delta vs the `delegate=none` arm. Render as `-12% cost (last 5 cycles)` or `(no data yet)` when fewer than 3 cycles of evidence exist.
50
+
51
+ If the posterior file does not exist, surface "(no data yet)" for every peer.
52
+
53
+ ### 6. Render the table
54
+
55
+ Emit the table in this exact shape:
56
+
57
+ ```
58
+ ## Peer-CLI Capability Matrix
59
+
60
+ | Peer | Installed | Allowlisted | Claimed roles | Posterior delta vs local |
61
+ |---------|-----------|-------------|--------------------------|--------------------------|
62
+ | codex | ✓ | ✓ | execute | -12% cost (last 5 cycles)|
63
+ | gemini | ✓ | ✓ | research, exploration | -8% |
64
+ | cursor | ✗ | ✗ | debug, plan | (not installed) |
65
+ | copilot | ✓ | ✗ | review, research | (opt-in disabled) |
66
+ | qwen | ✓ | ✓ | write | (no data yet) |
67
+
68
+ > Tip: Enable peers via `.design/config.json#peer_cli.enabled_peers`.
69
+ > See `reference/peer-cli-capabilities.md` for the full capability matrix.
70
+ > See `skills/peer-cli-customize/SKILL.md` to rewire role→peer mappings per agent.
71
+ ```
72
+
73
+ Rules for the third column ("Posterior delta vs local"):
74
+ - If `Installed = ✗` → `(not installed)`.
75
+ - Else if `Allowlisted = ✗` → `(opt-in disabled)`.
76
+ - Else if posterior data has fewer than 3 cycles → `(no data yet)`.
77
+ - Else compute and render the delta.
78
+
79
+ ### 7. Done
80
+
81
+ The table IS the output. No follow-up prose. Users can act on the data:
82
+ - See "(opt-in disabled)" → enable in `.design/config.json`.
83
+ - See "(not installed)" → install the peer CLI.
84
+ - See concrete deltas → trust the bandit's recommendation, or override per-agent via `skills/peer-cli-customize`.
85
+
86
+ ## Cross-references
87
+
88
+ - `scripts/lib/peer-cli/registry.cjs` (Plan 27-05) — capability matrix data source.
89
+ - `scripts/lib/install/runtimes.cjs` (Plan 27-11) — `peerBinary` field per runtime.
90
+ - `reference/peer-cli-capabilities.md` (Plan 27-05) — full capability matrix doc.
91
+ - `skills/peer-cli-customize/SKILL.md` (Plan 27-10) — rewire role→peer mappings.
92
+ - `skills/peer-cli-add/SKILL.md` (Plan 27-10) — add a brand-new peer.
93
+ - `.planning/phases/27-peer-cli-delegation/CONTEXT.md` D-10 — decision lineage.
94
+
95
+ ## Record
96
+
97
+ After execution, append one JSONL line to `.design/skill-records.jsonl`:
98
+
99
+ ```json
100
+ {"skill": "gdd-peers", "ts": "<ISO timestamp>", "peers_detected": ["codex", "gemini"], "peers_allowlisted": ["codex"], "had_posterior": false}
101
+ ```