opencode-swarm 7.109.1 → 7.109.3

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/.opencode/skills/ci-failure-batching/SKILL.md +39 -0
  2. package/.opencode/skills/engineering-conventions/SKILL.md +45 -0
  3. package/.opencode/skills/gate-attribution/SKILL.md +31 -0
  4. package/.opencode/skills/merge-queue-readiness/SKILL.md +37 -0
  5. package/.opencode/skills/skill-edit-validation/SKILL.md +29 -0
  6. package/.opencode/skills/swarm-pr-feedback/SKILL.md +47 -0
  7. package/.opencode/skills/worktree-retry-cleanup/SKILL.md +24 -0
  8. package/dist/cli/{curator-q4febs18.js → curator-9q3m25va.js} +6 -6
  9. package/dist/cli/{curator-llm-factory-gtfhwnbr.js → curator-llm-factory-78dyv010.js} +6 -6
  10. package/dist/cli/{guardrail-explain-r2d8ftkv.js → guardrail-explain-csnawe0d.js} +7 -7
  11. package/dist/cli/{hive-promoter-mfd5p9f5.js → hive-promoter-xnx734y3.js} +6 -6
  12. package/dist/cli/{index-1capawwy.js → index-3nd7bz90.js} +7 -7
  13. package/dist/cli/{index-fz1jgbvw.js → index-41fgssqr.js} +22 -2
  14. package/dist/cli/{index-wg0665ft.js → index-8f10r7ay.js} +2 -2
  15. package/dist/cli/{index-9qxntjtx.js → index-b15qbvph.js} +190 -41
  16. package/dist/cli/{index-5gnp8fyw.js → index-mtzjbaaa.js} +3 -3
  17. package/dist/cli/{index-wsg3vkss.js → index-r9dbs4zr.js} +1 -1
  18. package/dist/cli/{index-nq9h2t3x.js → index-xyz8epk6.js} +643 -548
  19. package/dist/cli/{index-mmny81g1.js → index-y5z2qdvk.js} +1 -1
  20. package/dist/cli/index.js +6 -6
  21. package/dist/cli/{knowledge-escalator-6v7sjprx.js → knowledge-escalator-9ksrgq7h.js} +3 -3
  22. package/dist/cli/{knowledge-events-6n3x3he2.js → knowledge-events-ymysgtrr.js} +1 -1
  23. package/dist/cli/{knowledge-store-exkw6yb1.js → knowledge-store-562fefjy.js} +1 -1
  24. package/dist/cli/{knowledge-validator-exymfcb9.js → knowledge-validator-b9nvmzjc.js} +4 -2
  25. package/dist/cli/{skill-generator-mx9br4ty.js → skill-generator-mjfqvnn0.js} +15 -5
  26. package/dist/config/bundled-skills.d.ts +1 -1
  27. package/dist/config/qa-gate-pipeline.d.ts +67 -0
  28. package/dist/hooks/knowledge-types.d.ts +6 -0
  29. package/dist/hooks/knowledge-validator.d.ts +5 -0
  30. package/dist/hooks/skill-invalidator.d.ts +48 -0
  31. package/dist/index.js +215 -214
  32. package/dist/services/skill-generator.d.ts +47 -2
  33. package/dist/tools/knowledge-remove.d.ts +3 -8
  34. package/package.json +6 -1
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: ci-failure-batching
3
+ description: Batch collection and fix protocol for CI failures. Triggered when any CI check fails on a PR. Prevents serial diagnose-fix-push cycles by collecting all failures before fixing.
4
+ ---
5
+
6
+ # CI Failure Batching
7
+
8
+ ## Trigger
9
+ When ANY CI check fails on the PR (pr-monitor surfaces `pr.ci.failed`).
10
+
11
+ ## Protocol
12
+ 1. **DO NOT immediately fix the first failure.** Check if other jobs are still running:
13
+ ```
14
+ gh pr checks <PR> --repo <repo>
15
+ ```
16
+ 2. **If jobs are still running:** Note the failure, WAIT for the run to complete
17
+ 3. **Once the run completes, collect ALL failures:**
18
+ - Identify every check with `fail` status
19
+ - For each: `gh run view <run-id> --log-failed`
20
+ - Build a complete failure ledger
21
+ 4. **Fix ALL failures in one changeset:** Cluster by root cause, fix each cluster, verify locally
22
+ 5. **Push the fixes in one cycle.** Amend the commit and push. NOTE: `git push --force` / `--force-with-lease` is deny-pattern-blocked by the guardrail in guarded sessions (no orchestrator exemption). If force-push is blocked, push a normal new fix commit instead — the batching goal is ONE push cycle (collect all → fix all → push once), not literally one commit. A single new commit containing all batched fixes satisfies the goal.
23
+ 6. **Only re-push if NEW failures surface** that were not in the original batch.
24
+
25
+ ## Why this matters
26
+ Without batching, N failures produce N push cycles. With batching, N failures produce 1 push cycle.
27
+
28
+ Example from session #1685:
29
+ - Without batching: 6 pushes (format → stale-assertion-1 → stale-assertion-2 → integration → merge-group → clean)
30
+ - With batching: 2 pushes (collect all → fix all → push once → clean)
31
+
32
+ ## Pr-monitor workaround
33
+ The pr-monitor fires `pr.ci.failed` per-check. When the first event arrives:
34
+ 1. Check `gh pr checks` — are other jobs still running?
35
+ 2. If yes: WAIT for completion
36
+ 3. If no: the single failure IS the only failure — proceed normally
37
+
38
+ ## Root cause
39
+ The pr-monitor should batch-fire after the CI run completes (issue #1746 item 7). This playbook is the manual protocol.
@@ -127,3 +127,48 @@ When a sandbox executor (`src/sandbox/{linux,macos,win32}/*.ts`) interpolates en
127
127
  - Scope-materialization for lane-scoped resources.
128
128
 
129
129
  A divergence between primary and fallback that is not exercised by a parity test is a regression. The existing per-OS test files `tests/unit/sandbox/{linux,macos,win32}.test.ts` must continue to cover both the primary and fallback paths after every env-affecting change — extend these tests rather than relying on dedicated sandbox-envoverride test files that may or may not exist in your branch.
130
+
131
+ ## SAST baseline capturing (differential scanning)
132
+
133
+ The `sast_scan` tool supports `capture_baseline: true` with a `phase` parameter
134
+ to snapshot pre-existing findings. Subsequent scans with the same `phase` value
135
+ perform differential checking — they only fail on **new** findings, not
136
+ pre-existing ones.
137
+
138
+ ### When to capture a baseline
139
+
140
+ - **Before Phase 1 code changes.** The baseline must reflect the state of the
141
+ codebase *before* any new work is done. This ensures the differential scan
142
+ catches findings introduced by the current session's changes.
143
+
144
+ ### Critical safety guard
145
+
146
+ **NEVER capture a baseline after code changes have been made in a phase.**
147
+ A baseline captured post-edit silently encodes the very bugs the scan is meant
148
+ to catch as "pre-existing," suppressing them indefinitely. This turns the SAST
149
+ gate into theater.
150
+
151
+ ### How to use it
152
+
153
+ 1. Identify the files to scan. In a phase, use the union of declared task-scope
154
+ files plus files the coder is expected to touch. Derive the list from
155
+ `declare_scope` outputs, `git diff --name-only`, or the phase's task specs.
156
+ 2. Before any coder delegation in Phase 1, capture the baseline:
157
+ ```
158
+ sast_scan(directory, changed_files=[...], capture_baseline=true, phase=1)
159
+ ```
160
+ 3. After coder work, scan the same file set:
161
+ ```
162
+ sast_scan(directory, changed_files=[...], phase=1)
163
+ ```
164
+ This returns only NEW findings (absent from the baseline).
165
+ 4. If a pre-existing finding is legitimately fixed, the baseline can be
166
+ re-captured at the start of the next phase with the updated file list.
167
+
168
+ ### Why this matters
169
+
170
+ During PR #1704 review, SAST flagged `RegExp.prototype.exec()` as
171
+ "command injection via child_process.exec()" — a false positive that blocked
172
+ the gate. With a baseline captured before the phase, this pre-existing false
173
+ positive would have been suppressed, and only genuinely new findings would
174
+ surface.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: gate-attribution
3
+ description: Per-task gate dispatch protocol. Documents the single-taskId attribution rule and parallel-lane optimization for reviewer/test_engineer gates.
4
+ ---
5
+
6
+ # Gate Attribution
7
+
8
+ ## The rule
9
+ The gate tracker attributes reviewer/test_engineer dispatches PER TASK (single taskId in the prompt). Set-dispatches covering multiple tasks do NOT count per-task, even with per-task verdicts.
10
+
11
+ ## Protocol
12
+ 1. **For each task requiring a gate:** Dispatch a separate reviewer and/or test_engineer with exactly ONE taskId
13
+ 2. **Minimize overhead via parallel dispatch:**
14
+ ```
15
+ dispatch_lanes_async with:
16
+ - common_prompt: shared verification context
17
+ - lanes: one lane per task, each with a single taskId
18
+ - max_concurrent: up to 3
19
+ ```
20
+ 3. **Collect + attribute:** Each lane result auto-attributes to its taskId
21
+ 4. **Do NOT batch:** Even for identical reviews, dispatch separately
22
+
23
+ ## Optimization for trivial tasks
24
+ For pure ceremony gates (1-line doc fix):
25
+ ```
26
+ TASK: Verify task X.Y. Run skill-mirrors.test.ts. PASS/FAIL.
27
+ taskId: X.Y
28
+ ```
29
+
30
+ ## Why this exists
31
+ The gate tracker (`src/hooks/delegation-gate.ts`) keys delegation chains by `sessionID`, and task attribution resolves exactly ONE taskId per dispatch (`args.task_id ?? args.taskId`). Ambiguous multi-task prompts fail closed (resolve to null) rather than attributing to any task — so a set-dispatch covering multiple tasks does not count per-task even with per-task verdicts. Tracked in issue #1746 item 6.
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: merge-queue-readiness
3
+ description: Pre-queue merge-group CI simulation. Triggered before adding a PR to a GitHub merge queue. Prevents merge-queue kick-outs from integration test failures.
4
+ ---
5
+
6
+ # Merge Queue Readiness
7
+
8
+ ## Trigger
9
+ Before adding the PR to the merge queue (or before the final push if the repo uses a merge queue).
10
+
11
+ ## Protocol
12
+ 1. **Fetch latest main:** `git fetch origin main`
13
+ 2. **Create a temporary simulation worktree (do NOT mutate the PR branch).** Use a project-relative path UNDER the swarm worktree base so the path is portable across OSes and its later removal is permitted by the worktree guardrail (paths outside `.swarm-worktrees/` are blocked). Do NOT hardcode `/tmp` — it does not exist on Windows.
14
+ ```
15
+ git worktree add .swarm-worktrees/merge-sim origin/main
16
+ cd .swarm-worktrees/merge-sim
17
+ git merge <pr-branch> --no-edit
18
+ ```
19
+ 3. **Run integration + unit tests against the merged result:**
20
+ ```
21
+ bun test tests/integration --timeout 120000
22
+ bun test tests/unit --timeout 120000
23
+ ```
24
+ (Use per-file loops for hot modules per AGENTS.md invariant 6)
25
+ 4. **If failures:** Fix on the PR branch, re-push, re-simulate. Always run the cleanup step (5) before re-simulating or on any exit path — do not leave the simulation worktree behind.
26
+ 5. **Cleanup (run on EVERY exit path, including failure):** `git worktree remove --force .swarm-worktrees/merge-sim`. If the remove is guardrail-blocked or fails, delete the directory directly and run `git worktree prune`.
27
+ 6. **Only after simulation passes,** add PR to the merge queue.
28
+
29
+ ## Why this matters
30
+ PR-branch CI and merge-group CI test DIFFERENT things:
31
+ - PR-branch: tests the PR head commit in isolation
32
+ - Merge-group: tests a temporary merge of PR head + latest main
33
+
34
+ Integration tests that pass on the PR branch may fail in merge-group context due to test interactions exposed by the merged result.
35
+
36
+ ## Root cause
37
+ A `swarm ci-simulate` command would automate this (issue #1746 item 5). This playbook is the manual protocol.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: skill-edit-validation
3
+ description: Content-assertion sweep after editing SKILL.md files. Triggered when a task changes skill or prompt content that tests assert against. Prevents stale-assertion CI failures.
4
+ ---
5
+
6
+ # Skill Edit Validation
7
+
8
+ ## Trigger
9
+ After editing ANY `.md` file under `.opencode/skills/`, `.claude/skills/`, or `.agents/skills/` that changes content wording (not just whitespace/formatting).
10
+
11
+ ## Protocol
12
+ 1. **Extract changed phrases:** Identify old wording vs new wording (e.g., "spec.md does NOT exist" changed to "NO effective spec exists")
13
+ 2. **Targeted sweep:** For each OLD phrase, grep test files:
14
+ ```
15
+ rg "<old-phrase>" tests/ src/ --type ts -l
16
+ ```
17
+ Focus on: `*-audit*`, `*-security*`, `*-spec-gate*`, `*skill-mirror*`, `*soft-spec*`, `*prompt*`, `*workflow*`
18
+ 3. **For each match:** Read the assertion context (surrounding 10 lines). Verify:
19
+ - Does the assertion still hold against the new content?
20
+ - Is it checking a substring containing the old phrase?
21
+ - Is it checking for the ABSENCE of a word the new wording introduces? (e.g., `not.toContain('skip')` catches "this check is skipped")
22
+ 4. **Update stale assertions in the same changeset.** Do NOT defer to CI.
23
+ 5. **Preserve behavioral intent:** When updating, preserve what the assertion TESTS (e.g., "the plan skill has a spec-absent branch"), not just the string match.
24
+
25
+ ## Constraint
26
+ Do NOT rubber-stamp brittle assertions. If an assertion tests implementation detail rather than behavioral intent, flag it for refactoring to a semantic check.
27
+
28
+ ## Root cause
29
+ A skill-content test registry would auto-adjust (issue #1746 item 3). This playbook is the manual safety net.
@@ -102,6 +102,53 @@ current branch before editing:
102
102
  - **Cache/state claims:** Test both relevant state orders when the behavior
103
103
  depends on cache priming, singleton state, or prior calls.
104
104
 
105
+ ### Automated Security Finding Verification
106
+
107
+ Automated security bots (e.g., hermes-pr-review, CodeRabbit, Gemini) frequently
108
+ produce findings rated CRITICAL or HIGH that are false positives. In a recent
109
+ PR review cycle, 7/7 bot security findings were false positives upon source
110
+ verification. Before acting on any bot security finding, perform these
111
+ source-level checks:
112
+
113
+ 1. **`child_process.exec` vs `RegExp.exec`**: SAST rules pattern-match on
114
+ `.exec(` and cannot distinguish `child_process.exec(userInput)` (real
115
+ injection risk) from `/^pattern$/.exec(str)` (safe regex test). Read the
116
+ actual line to determine which `.exec` is called.
117
+
118
+ 2. **Schema validation already present**: Bots may flag "missing type
119
+ validation" without checking the Zod schema. Search for the field name in
120
+ `src/config/schema.ts` — `z.number().int()`, `z.string().min()`, etc. are
121
+ runtime validators that run before the code path the bot reviewed.
122
+
123
+ 3. **`Object.assign` mutation claims**: Bots may claim `Object.assign` mutates
124
+ the source object. Check whether the call is `Object.assign(target, source)`
125
+ (mutates target) vs `Object.assign({}, source)` or a manual copy loop into a
126
+ new `{}` (creates a new object, source is safe). Read the actual assignment.
127
+
128
+ 4. **Path containment for system-generated paths**: Bots may flag "path
129
+ traversal" on file paths. Check whether the path is user-controlled (real
130
+ risk) or system-generated from `provisionWorktree`, `mkdtempSync`, or
131
+ similar (no user input reaches the path). Trace the variable's origin.
132
+
133
+ 5. **Value validation vs key validation**: Bots may suggest validating env var
134
+ *values* for shell injection characters. Check whether the value is passed
135
+ through a sandbox executor that escapes arguments (e.g., `wrapCommand`
136
+ which returns a shell-quoted / `psStringEscape`-escaped string for the
137
+ `bunSpawn` array-form argv to consume). Value validation would break
138
+ legitimate env vars (PATH with `;`, URLs with `$`); escaping is the
139
+ sandbox's job — see `engineering-conventions` § "Sandbox env overrides"
140
+ for the full escape contract.
141
+
142
+ 6. **Deduplication for independent resources**: Bots may suggest deduplicating
143
+ cache redirects or env var entries. Check whether the entries map to
144
+ independent keys (different env var names) — independent keys cannot
145
+ "collide" and deduplication is nonsensical.
146
+
147
+ **Rule:** For any bot finding rated CRITICAL or HIGH, read the actual source
148
+ line AND its surrounding context (parent function, schema definition, type
149
+ annotations) before accepting the finding. If the finding is disproved, record
150
+ it in the closure ledger with the specific source evidence that disproves it.
151
+
105
152
  ## Operating Stance
106
153
 
107
154
  Treat every review comment, CI failure, bot summary, PR body claim, and pasted note
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: worktree-retry-cleanup
3
+ description: Protocol for cleaning parallel-coder worktree lanes before retry. Triggered before re-dispatching any task that already has a lane (completed, denied, cancelled, or failed).
4
+ ---
5
+
6
+ # Worktree Retry Cleanup
7
+
8
+ ## Trigger
9
+ Before re-dispatching a coder for a task that already has a lane (any prior dispatch status).
10
+
11
+ ## Protocol
12
+ 1. **Ownership check — do this FIRST, before any deletion.** Confirm the lane is not owned by another ACTIVE session: read `.swarm/session/state.json` and verify no other session's `delegationChains` reference `<session>/<task>`. If another active session owns it, STOP — surface the conflict and do not delete.
13
+ 2. **Check for existing lane branch:** `git branch --list "swarm/lane/<session>/<task>"`
14
+ 3. **If branch exists:**
15
+ - Verify 0-commits-ahead: `git log --oneline HEAD..swarm/lane/<session>/<task>` — empty = safe
16
+ - Delete: `git branch -d swarm/lane/<session>/<task>` (use `-D` only if `-d` fails AND the commits are confirmed unneeded)
17
+ - Under full-auto, `-D` is deny-pattern-blocked — use `-d`
18
+ 4. **Remove the per-lane worktree directory.** Target the SPECIFIC lane `.swarm-worktrees/<session>/<task>`, NOT the session parent (the parent holds sibling lanes). Prefer `git worktree remove .swarm-worktrees/<session>/<task>` — this is permitted because the path is under the `.swarm-worktrees/` base. A bare `rm -rf` / `Remove-Item -Recurse -Force` on `.swarm-worktrees/` is deny-pattern-blocked by the guardrail, so do not use it here.
19
+ 5. **Prune:** `git worktree prune`
20
+ 6. **Verify:** `git branch --list "swarm/lane/<session>/<task>"` returns empty
21
+ 7. Only after cleanup, proceed to `declare_scope` + coder dispatch
22
+
23
+ ## Root cause
24
+ The provisioning code should auto-clean after coder completion/denial/cancellation (tracked in issue #1746 item 1). This playbook is the temporary protocol.
@@ -11,9 +11,9 @@ import {
11
11
  runCuratorInit,
12
12
  runCuratorPhase,
13
13
  writeCuratorSummary
14
- } from "./index-nq9h2t3x.js";
14
+ } from "./index-xyz8epk6.js";
15
15
  import"./index-wj4jeavn.js";
16
- import"./index-5gnp8fyw.js";
16
+ import"./index-mtzjbaaa.js";
17
17
  import"./index-c8s9a3zh.js";
18
18
  import"./index-fm7xz1ne.js";
19
19
  import"./index-j2v3w1ds.js";
@@ -22,10 +22,10 @@ import"./index-yw8qpf51.js";
22
22
  import"./index-85bacexr.js";
23
23
  import"./index-09xpycan.js";
24
24
  import"./index-h4c4rrwx.js";
25
- import"./index-9qxntjtx.js";
26
- import"./index-mmny81g1.js";
27
- import"./index-fz1jgbvw.js";
28
- import"./index-wg0665ft.js";
25
+ import"./index-b15qbvph.js";
26
+ import"./index-y5z2qdvk.js";
27
+ import"./index-41fgssqr.js";
28
+ import"./index-8f10r7ay.js";
29
29
  import"./index-2nt4mq9n.js";
30
30
  import"./index-bfwt3abw.js";
31
31
  import"./index-wvrj16f0.js";
@@ -1,9 +1,9 @@
1
1
  // @bun
2
2
  import {
3
3
  createCuratorLLMDelegate
4
- } from "./index-nq9h2t3x.js";
4
+ } from "./index-xyz8epk6.js";
5
5
  import"./index-wj4jeavn.js";
6
- import"./index-5gnp8fyw.js";
6
+ import"./index-mtzjbaaa.js";
7
7
  import"./index-c8s9a3zh.js";
8
8
  import"./index-fm7xz1ne.js";
9
9
  import"./index-j2v3w1ds.js";
@@ -12,10 +12,10 @@ import"./index-yw8qpf51.js";
12
12
  import"./index-85bacexr.js";
13
13
  import"./index-09xpycan.js";
14
14
  import"./index-h4c4rrwx.js";
15
- import"./index-9qxntjtx.js";
16
- import"./index-mmny81g1.js";
17
- import"./index-fz1jgbvw.js";
18
- import"./index-wg0665ft.js";
15
+ import"./index-b15qbvph.js";
16
+ import"./index-y5z2qdvk.js";
17
+ import"./index-41fgssqr.js";
18
+ import"./index-8f10r7ay.js";
19
19
  import"./index-2nt4mq9n.js";
20
20
  import"./index-bfwt3abw.js";
21
21
  import"./index-wvrj16f0.js";
@@ -1,10 +1,10 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-wsg3vkss.js";
5
- import"./index-nq9h2t3x.js";
4
+ } from "./index-r9dbs4zr.js";
5
+ import"./index-xyz8epk6.js";
6
6
  import"./index-wj4jeavn.js";
7
- import"./index-5gnp8fyw.js";
7
+ import"./index-mtzjbaaa.js";
8
8
  import"./index-c8s9a3zh.js";
9
9
  import"./index-fm7xz1ne.js";
10
10
  import"./index-j2v3w1ds.js";
@@ -13,10 +13,10 @@ import"./index-yw8qpf51.js";
13
13
  import"./index-85bacexr.js";
14
14
  import"./index-09xpycan.js";
15
15
  import"./index-h4c4rrwx.js";
16
- import"./index-9qxntjtx.js";
17
- import"./index-mmny81g1.js";
18
- import"./index-fz1jgbvw.js";
19
- import"./index-wg0665ft.js";
16
+ import"./index-b15qbvph.js";
17
+ import"./index-y5z2qdvk.js";
18
+ import"./index-41fgssqr.js";
19
+ import"./index-8f10r7ay.js";
20
20
  import"./index-2nt4mq9n.js";
21
21
  import"./index-bfwt3abw.js";
22
22
  import"./index-wvrj16f0.js";
@@ -5,9 +5,9 @@ import {
5
5
  isHiveEligible,
6
6
  promoteFromSwarm,
7
7
  promoteToHive
8
- } from "./index-nq9h2t3x.js";
8
+ } from "./index-xyz8epk6.js";
9
9
  import"./index-wj4jeavn.js";
10
- import"./index-5gnp8fyw.js";
10
+ import"./index-mtzjbaaa.js";
11
11
  import"./index-c8s9a3zh.js";
12
12
  import"./index-fm7xz1ne.js";
13
13
  import"./index-j2v3w1ds.js";
@@ -16,10 +16,10 @@ import"./index-yw8qpf51.js";
16
16
  import"./index-85bacexr.js";
17
17
  import"./index-09xpycan.js";
18
18
  import"./index-h4c4rrwx.js";
19
- import"./index-9qxntjtx.js";
20
- import"./index-mmny81g1.js";
21
- import"./index-fz1jgbvw.js";
22
- import"./index-wg0665ft.js";
19
+ import"./index-b15qbvph.js";
20
+ import"./index-y5z2qdvk.js";
21
+ import"./index-41fgssqr.js";
22
+ import"./index-8f10r7ay.js";
23
23
  import"./index-2nt4mq9n.js";
24
24
  import"./index-bfwt3abw.js";
25
25
  import"./index-wvrj16f0.js";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-wsg3vkss.js";
4
+ } from "./index-r9dbs4zr.js";
5
5
  import {
6
6
  handleGuardrailLog
7
7
  } from "./index-vx76tcxe.js";
@@ -80,9 +80,9 @@ import {
80
80
  handleWriteRetroCommand,
81
81
  normalizeSwarmCommandInput,
82
82
  resolveCommand
83
- } from "./index-nq9h2t3x.js";
83
+ } from "./index-xyz8epk6.js";
84
84
  import"./index-wj4jeavn.js";
85
- import"./index-5gnp8fyw.js";
85
+ import"./index-mtzjbaaa.js";
86
86
  import"./index-c8s9a3zh.js";
87
87
  import"./index-fm7xz1ne.js";
88
88
  import"./index-j2v3w1ds.js";
@@ -95,10 +95,10 @@ import {
95
95
  ORCHESTRATOR_NAME,
96
96
  stripKnownSwarmPrefix
97
97
  } from "./index-h4c4rrwx.js";
98
- import"./index-9qxntjtx.js";
99
- import"./index-mmny81g1.js";
100
- import"./index-fz1jgbvw.js";
101
- import"./index-wg0665ft.js";
98
+ import"./index-b15qbvph.js";
99
+ import"./index-y5z2qdvk.js";
100
+ import"./index-41fgssqr.js";
101
+ import"./index-8f10r7ay.js";
102
102
  import"./index-2nt4mq9n.js";
103
103
  import"./index-bfwt3abw.js";
104
104
  import"./index-wvrj16f0.js";
@@ -6,7 +6,7 @@ import {
6
6
  resolveSwarmKnowledgePath,
7
7
  resolveSwarmRejectedPath,
8
8
  transactKnowledge
9
- } from "./index-wg0665ft.js";
9
+ } from "./index-8f10r7ay.js";
10
10
  import {
11
11
  resolveKnowledgeStoreDir
12
12
  } from "./index-2nt4mq9n.js";
@@ -341,6 +341,7 @@ function validateLesson(candidate, existingLessons, meta) {
341
341
  }
342
342
  var ACTIONABLE_STRING_MAX = 200;
343
343
  var ACTIONABLE_LIST_MAX = 20;
344
+ var RETIRED_SKILL_HISTORY_MAX = 50;
344
345
  var NAME_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
345
346
  var SOURCE_REF_FORBIDDEN = /(\.\.\/|\.\.\\|\0|[\x00-\x1f\x7f])/;
346
347
  var ALLOWED_SKILL_PATH_PREFIXES = [
@@ -473,6 +474,25 @@ function validateActionableFields(fields) {
473
474
  if (fields.generated_skill_path !== undefined && !validateSkillPath(fields.generated_skill_path)) {
474
475
  errors.push("generated_skill_path must be repo-local under allowed prefix");
475
476
  }
477
+ if (fields.draft_generated_skill_slug !== undefined) {
478
+ if (typeof fields.draft_generated_skill_slug !== "string" || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(fields.draft_generated_skill_slug)) {
479
+ errors.push("draft_generated_skill_slug must be a kebab-case slug");
480
+ }
481
+ }
482
+ if (fields.draft_generated_skill_path !== undefined && !validateSkillPath(fields.draft_generated_skill_path)) {
483
+ errors.push("draft_generated_skill_path must be repo-local under allowed prefix");
484
+ }
485
+ if (fields.retired_skill_history !== undefined) {
486
+ if (!Array.isArray(fields.retired_skill_history)) {
487
+ errors.push("retired_skill_history must be an array of slugs");
488
+ } else {
489
+ if (fields.retired_skill_history.length > RETIRED_SKILL_HISTORY_MAX) {
490
+ errors.push(`retired_skill_history exceeds ${RETIRED_SKILL_HISTORY_MAX} items`);
491
+ } else if (!fields.retired_skill_history.every((s) => typeof s === "string" && /^[a-z0-9][a-z0-9-]{0,63}$/.test(s))) {
492
+ errors.push("retired_skill_history entries must be kebab-case slugs");
493
+ }
494
+ }
495
+ }
476
496
  return { valid: errors.length === 0, errors };
477
497
  }
478
498
  function hasNonEmptyList(v) {
@@ -738,4 +758,4 @@ var _internals = {
738
758
  hasSignificantOverlap
739
759
  };
740
760
 
741
- export { DANGEROUS_COMMAND_ERROR_PATTERNS, DANGEROUS_COMMAND_WARNING_PATTERNS, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, validateLesson, ACTIONABLE_STRING_MAX, ACTIONABLE_LIST_MAX, ALLOWED_SKILL_PATH_PREFIXES, validateSkillPath, validateSkillCandidatePath, validateActionableFields, validateActionability, resolveUnactionablePath, appendUnactionable, auditEntryHealth, quarantineEntry, restoreEntry, unarchiveEntry, _internals };
761
+ export { DANGEROUS_COMMAND_ERROR_PATTERNS, DANGEROUS_COMMAND_WARNING_PATTERNS, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, validateLesson, ACTIONABLE_STRING_MAX, ACTIONABLE_LIST_MAX, RETIRED_SKILL_HISTORY_MAX, ALLOWED_SKILL_PATH_PREFIXES, validateSkillPath, validateSkillCandidatePath, validateActionableFields, validateActionability, resolveUnactionablePath, appendUnactionable, auditEntryHealth, quarantineEntry, restoreEntry, unarchiveEntry, _internals };
@@ -525,7 +525,7 @@ async function applyConfidenceFloorAction(directory, touched, options) {
525
525
  const recovered = touched.filter((e) => e.confidence > CONFIDENCE_FLOOR + FLOOR_EPSILON && e.confidence_floor_demoted);
526
526
  if (atFloor.length === 0 && recovered.length === 0)
527
527
  return;
528
- const { readKnowledgeCounterRollups, effectiveRetrievalOutcomes } = await import("./knowledge-events-6n3x3he2.js");
528
+ const { readKnowledgeCounterRollups, effectiveRetrievalOutcomes } = await import("./knowledge-events-ymysgtrr.js");
529
529
  const rollups = await readKnowledgeCounterRollups(directory);
530
530
  const flagIds = new Set;
531
531
  for (const e of atFloor) {
@@ -592,7 +592,7 @@ async function applyConfidenceFloorAction(directory, touched, options) {
592
592
  });
593
593
  }
594
594
  if (action === "quarantine" && toQuarantine.length > 0) {
595
- const { quarantineEntry } = await import("./knowledge-validator-exymfcb9.js");
595
+ const { quarantineEntry } = await import("./knowledge-validator-b9nvmzjc.js");
596
596
  for (const { id } of toQuarantine) {
597
597
  await quarantineEntry(directory, id, "confidence_floor_negative_outcome", "auto").catch((err) => {
598
598
  console.warn("[knowledge-store] confidence-floor quarantine failed (best-effort):", err instanceof Error ? err.message : String(err));