opencode-swarm 7.113.1 → 7.113.2
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.
- package/.opencode/skills/engineering-conventions/SKILL.md +5 -0
- package/.opencode/skills/gate-attribution/SKILL.md +2 -0
- package/dist/background/pending-delegations.d.ts +8 -0
- package/dist/background/workspace-snapshot.d.ts +7 -0
- package/dist/cli/{curator-nm2c9y1p.js → curator-9s04amtf.js} +4 -3
- package/dist/cli/{curator-llm-factory-nmhzc774.js → curator-llm-factory-dwvk7rh0.js} +4 -3
- package/dist/cli/{evidence-summary-service-j6fnsfeq.js → evidence-summary-service-w1er1ea2.js} +2 -2
- package/dist/cli/{gate-evidence-mk0ss1re.js → gate-evidence-9hdwj6tt.js} +1 -1
- package/dist/cli/{guardrail-explain-q1np1xaw.js → guardrail-explain-2k271yh4.js} +5 -4
- package/dist/cli/{hive-promoter-z4dezw62.js → hive-promoter-0y4pnft4.js} +4 -3
- package/dist/cli/{index-npd9rypp.js → index-54dgk0bv.js} +10 -10
- package/dist/cli/{index-d0w40jm3.js → index-afgh75zg.js} +1 -1
- package/dist/cli/{workspace-snapshot-w58jr2ga.js → index-dqh3zhhc.js} +53 -10
- package/dist/cli/{index-ky8eb4q6.js → index-n7rd2rkj.js} +1 -1
- package/dist/cli/{index-rqpm9cwe.js → index-w51xz4dr.js} +5 -4
- package/dist/cli/{index-pm992z24.js → index-x5g7et24.js} +10 -7
- package/dist/cli/index.js +4 -3
- package/dist/cli/{pending-delegations-gc3a2hfx.js → pending-delegations-t047f4a7.js} +7 -0
- package/dist/cli/workspace-snapshot-eyf6gd0d.js +22 -0
- package/dist/config/skill-mirrors.d.ts +3 -1
- package/dist/gate-evidence-classification.d.ts +5 -0
- package/dist/gate-evidence.d.ts +14 -3
- package/dist/index.js +272 -272
- package/dist/memory/schema.d.ts +4 -4
- package/dist/tools/phase-complete.d.ts +8 -0
- package/dist/tools/sast-scan.d.ts +2 -0
- package/package.json +1 -1
|
@@ -149,6 +149,11 @@ A baseline captured post-edit silently encodes the very bugs the scan is meant
|
|
|
149
149
|
to catch as "pre-existing," suppressing them indefinitely. This turns the SAST
|
|
150
150
|
gate into theater.
|
|
151
151
|
|
|
152
|
+
Baseline capture also requires at least one supported, existing file to be
|
|
153
|
+
successfully scanned. Omitted, empty, or entirely unscannable `changed_files`
|
|
154
|
+
returns `capture_baseline requires changed_files to produce a non-empty baseline`
|
|
155
|
+
instead of reporting a successful no-op capture.
|
|
156
|
+
|
|
152
157
|
### How to use it
|
|
153
158
|
|
|
154
159
|
1. Identify the files to scan. In a phase, use the union of declared task-scope
|
|
@@ -35,6 +35,8 @@ no reviewed rows are parseable, attribution falls back to the single-task rule.
|
|
|
35
35
|
4. **Collect + attribute:** Single-task lanes auto-attribute to their taskId; set-dispatch rows auto-attribute per parsed row.
|
|
36
36
|
5. **Do NOT rely on prose summaries:** A batched dispatch without parseable rows is ambiguous and does not count per-task.
|
|
37
37
|
|
|
38
|
+
Gate evidence is persisted independently as `.swarm/evidence/{taskId}.json` for each task. Passing set-dispatch rows cause the hook to write one task-scoped file per task; a single multi-task evidence file cannot satisfy any task.
|
|
39
|
+
|
|
38
40
|
## Optimization for trivial tasks
|
|
39
41
|
For pure ceremony gates (1-line doc fix):
|
|
40
42
|
```
|
|
@@ -56,6 +56,8 @@ export interface BackgroundDelegationRecord {
|
|
|
56
56
|
promptHash?: string;
|
|
57
57
|
/** Project/root provenance captured at dispatch time. */
|
|
58
58
|
workspace?: BackgroundWorkspaceSnapshot;
|
|
59
|
+
/** Immutable pre-coder provenance for doc-only gate classification. */
|
|
60
|
+
taskChangeContext?: BackgroundTaskChangeContext;
|
|
59
61
|
prompt?: BackgroundPromptSnapshot;
|
|
60
62
|
generation?: number;
|
|
61
63
|
result?: BackgroundDelegationResult;
|
|
@@ -65,9 +67,14 @@ export interface BackgroundWorkspaceSnapshot {
|
|
|
65
67
|
directory: string;
|
|
66
68
|
gitHead: string | null;
|
|
67
69
|
dirtyHash: string | null;
|
|
70
|
+
changedFiles?: string[] | null;
|
|
68
71
|
prHeadSha: string | null;
|
|
69
72
|
scope: string | null;
|
|
70
73
|
}
|
|
74
|
+
export interface BackgroundTaskChangeContext {
|
|
75
|
+
declaredFiles: string[] | null;
|
|
76
|
+
baseline: BackgroundWorkspaceSnapshot;
|
|
77
|
+
}
|
|
71
78
|
export interface BackgroundPromptSnapshot {
|
|
72
79
|
text: string;
|
|
73
80
|
chars: number;
|
|
@@ -114,6 +121,7 @@ export interface RecordPendingInput {
|
|
|
114
121
|
mode?: string;
|
|
115
122
|
promptHash?: string;
|
|
116
123
|
workspace?: BackgroundWorkspaceSnapshot;
|
|
124
|
+
taskChangeContext?: BackgroundTaskChangeContext;
|
|
117
125
|
prompt?: BackgroundPromptSnapshot;
|
|
118
126
|
generation?: number;
|
|
119
127
|
}
|
|
@@ -11,7 +11,14 @@ interface CaptureWorkspaceSnapshotOptions {
|
|
|
11
11
|
*/
|
|
12
12
|
resolveCurrentPrHeadSha?: boolean;
|
|
13
13
|
}
|
|
14
|
+
/** Parse `git status --porcelain=v1 -z`, including both sides of renames. */
|
|
15
|
+
export declare function parsePorcelainPaths(output: string): string[] | null;
|
|
14
16
|
export declare function captureWorkspaceSnapshot(directory: string, optionsOrScope?: string | null | CaptureWorkspaceSnapshotOptions, prHeadShaArg?: string | null): BackgroundWorkspaceSnapshot;
|
|
17
|
+
/**
|
|
18
|
+
* Conservatively derive final paths changed since a pre-task snapshot.
|
|
19
|
+
* Git or parsing failures return null so gate classification fails closed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function changedFilesSinceSnapshot(directory: string, baseline: BackgroundWorkspaceSnapshot | undefined): string[] | null;
|
|
15
22
|
export declare function workspaceSnapshotMatches(expected: BackgroundWorkspaceSnapshot | undefined, current: BackgroundWorkspaceSnapshot): {
|
|
16
23
|
ok: true;
|
|
17
24
|
} | {
|
|
@@ -12,12 +12,12 @@ import {
|
|
|
12
12
|
runCuratorInit,
|
|
13
13
|
runCuratorPhase,
|
|
14
14
|
writeCuratorSummary
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-54dgk0bv.js";
|
|
16
16
|
import"./index-8f256d7t.js";
|
|
17
17
|
import"./index-c8s9a3zh.js";
|
|
18
18
|
import"./index-0gf6de8b.js";
|
|
19
19
|
import"./index-1ey3dxq7.js";
|
|
20
|
-
import"./index-
|
|
20
|
+
import"./index-afgh75zg.js";
|
|
21
21
|
import"./index-scww5b77.js";
|
|
22
22
|
import"./index-9fxs0rm1.js";
|
|
23
23
|
import"./index-q1jaeynn.js";
|
|
@@ -38,7 +38,8 @@ import"./index-jtqkh8jf.js";
|
|
|
38
38
|
import"./index-5e4e2hvv.js";
|
|
39
39
|
import"./index-p0arc26j.js";
|
|
40
40
|
import"./index-zgwm4ryv.js";
|
|
41
|
-
import"./index-
|
|
41
|
+
import"./index-dqh3zhhc.js";
|
|
42
|
+
import"./index-x5g7et24.js";
|
|
42
43
|
import"./index-0dab9w37.js";
|
|
43
44
|
import"./index-293f68mj.js";
|
|
44
45
|
import"./index-5mkc2f9z.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
createCuratorLLMDelegate
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-54dgk0bv.js";
|
|
5
5
|
import"./index-8f256d7t.js";
|
|
6
6
|
import"./index-c8s9a3zh.js";
|
|
7
7
|
import"./index-0gf6de8b.js";
|
|
8
8
|
import"./index-1ey3dxq7.js";
|
|
9
|
-
import"./index-
|
|
9
|
+
import"./index-afgh75zg.js";
|
|
10
10
|
import"./index-scww5b77.js";
|
|
11
11
|
import"./index-9fxs0rm1.js";
|
|
12
12
|
import"./index-q1jaeynn.js";
|
|
@@ -27,7 +27,8 @@ import"./index-jtqkh8jf.js";
|
|
|
27
27
|
import"./index-5e4e2hvv.js";
|
|
28
28
|
import"./index-p0arc26j.js";
|
|
29
29
|
import"./index-zgwm4ryv.js";
|
|
30
|
-
import"./index-
|
|
30
|
+
import"./index-dqh3zhhc.js";
|
|
31
|
+
import"./index-x5g7et24.js";
|
|
31
32
|
import"./index-0dab9w37.js";
|
|
32
33
|
import"./index-293f68mj.js";
|
|
33
34
|
import"./index-5mkc2f9z.js";
|
package/dist/cli/{evidence-summary-service-j6fnsfeq.js → evidence-summary-service-w1er1ea2.js}
RENAMED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
loadPlanJsonOnly,
|
|
7
7
|
mergeDurableGateEntriesFromEvidence,
|
|
8
8
|
readDurableGateEvidence
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-afgh75zg.js";
|
|
10
10
|
import"./index-scww5b77.js";
|
|
11
11
|
import"./index-q1exe2b3.js";
|
|
12
12
|
import"./index-1rga1vvb.js";
|
|
@@ -16,7 +16,7 @@ import"./index-p0arc26j.js";
|
|
|
16
16
|
import {
|
|
17
17
|
log
|
|
18
18
|
} from "./index-zgwm4ryv.js";
|
|
19
|
-
import"./index-
|
|
19
|
+
import"./index-x5g7et24.js";
|
|
20
20
|
import"./index-0dab9w37.js";
|
|
21
21
|
import"./index-293f68mj.js";
|
|
22
22
|
import"./index-5mkc2f9z.js";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
handleGuardrailExplain
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
4
|
+
} from "./index-n7rd2rkj.js";
|
|
5
|
+
import"./index-54dgk0bv.js";
|
|
6
6
|
import"./index-8f256d7t.js";
|
|
7
7
|
import"./index-c8s9a3zh.js";
|
|
8
8
|
import"./index-0gf6de8b.js";
|
|
9
9
|
import"./index-1ey3dxq7.js";
|
|
10
|
-
import"./index-
|
|
10
|
+
import"./index-afgh75zg.js";
|
|
11
11
|
import"./index-scww5b77.js";
|
|
12
12
|
import"./index-9fxs0rm1.js";
|
|
13
13
|
import"./index-q1jaeynn.js";
|
|
@@ -28,7 +28,8 @@ import"./index-jtqkh8jf.js";
|
|
|
28
28
|
import"./index-5e4e2hvv.js";
|
|
29
29
|
import"./index-p0arc26j.js";
|
|
30
30
|
import"./index-zgwm4ryv.js";
|
|
31
|
-
import"./index-
|
|
31
|
+
import"./index-dqh3zhhc.js";
|
|
32
|
+
import"./index-x5g7et24.js";
|
|
32
33
|
import"./index-0dab9w37.js";
|
|
33
34
|
import"./index-293f68mj.js";
|
|
34
35
|
import"./index-5mkc2f9z.js";
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
isHiveEligible,
|
|
6
6
|
promoteFromSwarm,
|
|
7
7
|
promoteToHive
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-54dgk0bv.js";
|
|
9
9
|
import"./index-8f256d7t.js";
|
|
10
10
|
import"./index-c8s9a3zh.js";
|
|
11
11
|
import"./index-0gf6de8b.js";
|
|
12
12
|
import"./index-1ey3dxq7.js";
|
|
13
|
-
import"./index-
|
|
13
|
+
import"./index-afgh75zg.js";
|
|
14
14
|
import"./index-scww5b77.js";
|
|
15
15
|
import"./index-9fxs0rm1.js";
|
|
16
16
|
import"./index-q1jaeynn.js";
|
|
@@ -31,7 +31,8 @@ import"./index-jtqkh8jf.js";
|
|
|
31
31
|
import"./index-5e4e2hvv.js";
|
|
32
32
|
import"./index-p0arc26j.js";
|
|
33
33
|
import"./index-zgwm4ryv.js";
|
|
34
|
-
import"./index-
|
|
34
|
+
import"./index-dqh3zhhc.js";
|
|
35
|
+
import"./index-x5g7et24.js";
|
|
35
36
|
import"./index-0dab9w37.js";
|
|
36
37
|
import"./index-293f68mj.js";
|
|
37
38
|
import"./index-5mkc2f9z.js";
|
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
savePlan,
|
|
69
69
|
transientBackoff,
|
|
70
70
|
validateProjectRoot
|
|
71
|
-
} from "./index-
|
|
71
|
+
} from "./index-afgh75zg.js";
|
|
72
72
|
import {
|
|
73
73
|
buildOpenSpecProjectionSync,
|
|
74
74
|
detectSpeckit,
|
|
@@ -10218,11 +10218,11 @@ var _internals12 = {
|
|
|
10218
10218
|
return KnowledgeConfigSchema2.parse({});
|
|
10219
10219
|
},
|
|
10220
10220
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
|
|
10221
|
-
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-
|
|
10221
|
+
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-9s04amtf.js");
|
|
10222
10222
|
return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig);
|
|
10223
10223
|
},
|
|
10224
10224
|
checkHivePromotions: async (entries, knowledgeConfig) => {
|
|
10225
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
10225
|
+
const { checkHivePromotions } = await import("./hive-promoter-0y4pnft4.js");
|
|
10226
10226
|
return checkHivePromotions(entries, knowledgeConfig);
|
|
10227
10227
|
},
|
|
10228
10228
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -17280,8 +17280,8 @@ var _internals23 = {
|
|
|
17280
17280
|
loadCuratorDeps: async () => {
|
|
17281
17281
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
17282
17282
|
import("./schema-qb313fyy.js"),
|
|
17283
|
-
import("./curator-
|
|
17284
|
-
import("./curator-llm-factory-
|
|
17283
|
+
import("./curator-9s04amtf.js"),
|
|
17284
|
+
import("./curator-llm-factory-dwvk7rh0.js")
|
|
17285
17285
|
]);
|
|
17286
17286
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
17287
17287
|
}
|
|
@@ -17777,7 +17777,7 @@ import { fileURLToPath } from "url";
|
|
|
17777
17777
|
// package.json
|
|
17778
17778
|
var package_default = {
|
|
17779
17779
|
name: "opencode-swarm",
|
|
17780
|
-
version: "7.113.
|
|
17780
|
+
version: "7.113.2",
|
|
17781
17781
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
17782
17782
|
main: "dist/index.js",
|
|
17783
17783
|
types: "dist/index.d.ts",
|
|
@@ -20050,7 +20050,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
20050
20050
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
20051
20051
|
}
|
|
20052
20052
|
async function handleEvidenceSummaryCommand(directory) {
|
|
20053
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
20053
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-w1er1ea2.js");
|
|
20054
20054
|
const artifact = await buildEvidenceSummary(directory);
|
|
20055
20055
|
if (!artifact) {
|
|
20056
20056
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -32618,7 +32618,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
32618
32618
|
async function handleHelpCommand(ctx) {
|
|
32619
32619
|
const targetCommand = ctx.args.join(" ");
|
|
32620
32620
|
if (!targetCommand) {
|
|
32621
|
-
const { buildHelpText } = await import("./index-
|
|
32621
|
+
const { buildHelpText } = await import("./index-w51xz4dr.js");
|
|
32622
32622
|
return buildHelpText();
|
|
32623
32623
|
}
|
|
32624
32624
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -32627,7 +32627,7 @@ async function handleHelpCommand(ctx) {
|
|
|
32627
32627
|
return _internals48.buildDetailedHelp(resolved.key, resolved.entry);
|
|
32628
32628
|
}
|
|
32629
32629
|
const similar = _internals48.findSimilarCommands(targetCommand);
|
|
32630
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
32630
|
+
const { buildHelpText: fullHelp } = await import("./index-w51xz4dr.js");
|
|
32631
32631
|
if (similar.length > 0) {
|
|
32632
32632
|
return `Command '/swarm ${targetCommand}' not found.
|
|
32633
32633
|
|
|
@@ -32760,7 +32760,7 @@ var COMMAND_REGISTRY = {
|
|
|
32760
32760
|
},
|
|
32761
32761
|
"guardrail explain": {
|
|
32762
32762
|
handler: async (ctx) => {
|
|
32763
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
32763
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-2k271yh4.js");
|
|
32764
32764
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
32765
32765
|
},
|
|
32766
32766
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import"./index-a76rekgs.js";
|
|
3
|
-
|
|
4
2
|
// src/background/workspace-snapshot.ts
|
|
5
3
|
import * as child_process from "child_process";
|
|
6
4
|
import { createHash } from "crypto";
|
|
@@ -19,6 +17,30 @@ function runGit(directory, args) {
|
|
|
19
17
|
return null;
|
|
20
18
|
return typeof result.stdout === "string" ? result.stdout.trimEnd() : null;
|
|
21
19
|
}
|
|
20
|
+
function parseNulPaths(output) {
|
|
21
|
+
return output.split("\x00").filter((entry) => entry.length > 0);
|
|
22
|
+
}
|
|
23
|
+
function parsePorcelainPaths(output) {
|
|
24
|
+
const entries = parseNulPaths(output);
|
|
25
|
+
const paths = [];
|
|
26
|
+
for (let index = 0;index < entries.length; index++) {
|
|
27
|
+
const entry = entries[index];
|
|
28
|
+
if (entry.length < 4 || entry[2] !== " ")
|
|
29
|
+
return null;
|
|
30
|
+
const status = entry.slice(0, 2);
|
|
31
|
+
const changedPath = entry.slice(3);
|
|
32
|
+
if (!changedPath)
|
|
33
|
+
return null;
|
|
34
|
+
paths.push(changedPath);
|
|
35
|
+
if (status.includes("R") || status.includes("C")) {
|
|
36
|
+
const originalPath = entries[++index];
|
|
37
|
+
if (!originalPath)
|
|
38
|
+
return null;
|
|
39
|
+
paths.push(originalPath);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return [...new Set(paths)];
|
|
43
|
+
}
|
|
22
44
|
function captureWorkspaceSnapshot(directory, optionsOrScope = null, prHeadShaArg = null) {
|
|
23
45
|
const scope = typeof optionsOrScope === "object" && optionsOrScope !== null ? optionsOrScope.scope ?? null : optionsOrScope;
|
|
24
46
|
const prHeadSha = (() => {
|
|
@@ -34,16 +56,43 @@ function captureWorkspaceSnapshot(directory, optionsOrScope = null, prHeadShaArg
|
|
|
34
56
|
const porcelain = runGit(directory, [
|
|
35
57
|
"status",
|
|
36
58
|
"--porcelain=v1",
|
|
59
|
+
"-z",
|
|
37
60
|
"--untracked-files=all"
|
|
38
61
|
]);
|
|
62
|
+
const changedFiles = porcelain === null ? null : parsePorcelainPaths(porcelain);
|
|
39
63
|
return {
|
|
40
64
|
directory: path.resolve(directory),
|
|
41
65
|
gitHead,
|
|
42
66
|
dirtyHash: porcelain === null ? null : digest(porcelain),
|
|
67
|
+
changedFiles,
|
|
43
68
|
prHeadSha,
|
|
44
69
|
scope
|
|
45
70
|
};
|
|
46
71
|
}
|
|
72
|
+
function changedFilesSinceSnapshot(directory, baseline) {
|
|
73
|
+
if (!baseline?.gitHead || baseline.changedFiles == null)
|
|
74
|
+
return null;
|
|
75
|
+
if (baseline.changedFiles.length > 0)
|
|
76
|
+
return null;
|
|
77
|
+
const current = captureWorkspaceSnapshot(directory);
|
|
78
|
+
if (!current.gitHead || current.changedFiles == null)
|
|
79
|
+
return null;
|
|
80
|
+
const changed = new Set(current.changedFiles);
|
|
81
|
+
if (baseline.gitHead !== current.gitHead) {
|
|
82
|
+
const committed = runGit(directory, [
|
|
83
|
+
"diff",
|
|
84
|
+
"--name-only",
|
|
85
|
+
"-z",
|
|
86
|
+
baseline.gitHead,
|
|
87
|
+
current.gitHead
|
|
88
|
+
]);
|
|
89
|
+
if (committed === null)
|
|
90
|
+
return null;
|
|
91
|
+
for (const changedPath of parseNulPaths(committed))
|
|
92
|
+
changed.add(changedPath);
|
|
93
|
+
}
|
|
94
|
+
return [...changed];
|
|
95
|
+
}
|
|
47
96
|
function workspaceSnapshotMatches(expected, current) {
|
|
48
97
|
if (!expected)
|
|
49
98
|
return { ok: true };
|
|
@@ -80,11 +129,5 @@ function digest(text) {
|
|
|
80
129
|
var _internals = {
|
|
81
130
|
spawnSync: child_process.spawnSync
|
|
82
131
|
};
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
digest,
|
|
86
|
-
compareWorkspaceSnapshots,
|
|
87
|
-
compareWorkspaceSnapshot,
|
|
88
|
-
captureWorkspaceSnapshot,
|
|
89
|
-
_internals
|
|
90
|
-
};
|
|
132
|
+
|
|
133
|
+
export { parsePorcelainPaths, captureWorkspaceSnapshot, changedFilesSinceSnapshot, workspaceSnapshotMatches, compareWorkspaceSnapshot, compareWorkspaceSnapshots, digest, _internals };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
handleGuardrailExplain
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-n7rd2rkj.js";
|
|
5
5
|
import {
|
|
6
6
|
handleGuardrailLog
|
|
7
7
|
} from "./index-r9fjzr3k.js";
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
handleWriteRetroCommand,
|
|
82
82
|
normalizeSwarmCommandInput,
|
|
83
83
|
resolveCommand
|
|
84
|
-
} from "./index-
|
|
84
|
+
} from "./index-54dgk0bv.js";
|
|
85
85
|
import"./index-8f256d7t.js";
|
|
86
86
|
import"./index-c8s9a3zh.js";
|
|
87
87
|
import"./index-0gf6de8b.js";
|
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
ORCHESTRATOR_NAME,
|
|
91
91
|
stripKnownSwarmPrefix
|
|
92
92
|
} from "./index-1ey3dxq7.js";
|
|
93
|
-
import"./index-
|
|
93
|
+
import"./index-afgh75zg.js";
|
|
94
94
|
import"./index-scww5b77.js";
|
|
95
95
|
import"./index-9fxs0rm1.js";
|
|
96
96
|
import"./index-q1jaeynn.js";
|
|
@@ -111,7 +111,8 @@ import"./index-jtqkh8jf.js";
|
|
|
111
111
|
import"./index-5e4e2hvv.js";
|
|
112
112
|
import"./index-p0arc26j.js";
|
|
113
113
|
import"./index-zgwm4ryv.js";
|
|
114
|
-
import"./index-
|
|
114
|
+
import"./index-dqh3zhhc.js";
|
|
115
|
+
import"./index-x5g7et24.js";
|
|
115
116
|
import"./index-0dab9w37.js";
|
|
116
117
|
import"./index-293f68mj.js";
|
|
117
118
|
import"./index-5mkc2f9z.js";
|
|
@@ -71,7 +71,8 @@ var TaskEvidenceSchema = exports_external.object({
|
|
|
71
71
|
taskId: exports_external.string(),
|
|
72
72
|
required_gates: exports_external.array(exports_external.string()).default([]),
|
|
73
73
|
gates: exports_external.record(exports_external.string(), GateEvidenceSchema),
|
|
74
|
-
turbo: exports_external.boolean().optional()
|
|
74
|
+
turbo: exports_external.boolean().optional(),
|
|
75
|
+
test_engineer_exempt: exports_external.boolean().optional()
|
|
75
76
|
});
|
|
76
77
|
var DEFAULT_REQUIRED_GATES = ["reviewer", "test_engineer"];
|
|
77
78
|
function isValidTaskId(taskId) {
|
|
@@ -80,10 +81,10 @@ function isValidTaskId(taskId) {
|
|
|
80
81
|
function assertValidTaskId(taskId) {
|
|
81
82
|
assertStrictTaskId(taskId);
|
|
82
83
|
}
|
|
83
|
-
function deriveRequiredGates(agentType) {
|
|
84
|
+
function deriveRequiredGates(agentType, context = {}) {
|
|
84
85
|
switch (agentType) {
|
|
85
86
|
case "coder":
|
|
86
|
-
return ["reviewer", "test_engineer"];
|
|
87
|
+
return context.testEngineerExempt === true ? ["reviewer"] : ["reviewer", "test_engineer"];
|
|
87
88
|
case "docs":
|
|
88
89
|
return ["docs"];
|
|
89
90
|
case "designer":
|
|
@@ -110,8 +111,8 @@ function deriveRequiredGates(agentType) {
|
|
|
110
111
|
return ["reviewer", "test_engineer"];
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
|
-
function expandRequiredGates(existingGates, newAgentType) {
|
|
114
|
-
const newGates = deriveRequiredGates(newAgentType);
|
|
114
|
+
function expandRequiredGates(existingGates, newAgentType, context = {}) {
|
|
115
|
+
const newGates = deriveRequiredGates(newAgentType, context);
|
|
115
116
|
const combined = [...new Set([...existingGates ?? [], ...newGates])];
|
|
116
117
|
return combined.sort();
|
|
117
118
|
}
|
|
@@ -166,6 +167,7 @@ async function recordGateEvidence(directory, taskId, gate, sessionId, turbo) {
|
|
|
166
167
|
taskId,
|
|
167
168
|
required_gates: requiredGates,
|
|
168
169
|
turbo: turbo === true ? true : existing?.turbo,
|
|
170
|
+
test_engineer_exempt: existing?.test_engineer_exempt,
|
|
169
171
|
gates: {
|
|
170
172
|
...existing?.gates ?? {},
|
|
171
173
|
[gate]: {
|
|
@@ -179,7 +181,7 @@ async function recordGateEvidence(directory, taskId, gate, sessionId, turbo) {
|
|
|
179
181
|
});
|
|
180
182
|
telemetry.gatePassed(sessionId, gate, taskId);
|
|
181
183
|
}
|
|
182
|
-
async function recordAgentDispatch(directory, taskId, agentType, turbo) {
|
|
184
|
+
async function recordAgentDispatch(directory, taskId, agentType, turbo, context = {}) {
|
|
183
185
|
assertValidTaskId(taskId);
|
|
184
186
|
await withTaskEvidenceLock(directory, taskId, agentType, async () => {
|
|
185
187
|
const resolvedEvidenceDir = getEvidenceDir(directory);
|
|
@@ -191,11 +193,12 @@ async function recordAgentDispatch(directory, taskId, agentType, turbo) {
|
|
|
191
193
|
telemetry.gateParseError(taskId, error);
|
|
192
194
|
throw error;
|
|
193
195
|
}
|
|
194
|
-
const requiredGates = existing ? expandRequiredGates(existing.required_gates, agentType) : deriveRequiredGates(agentType);
|
|
196
|
+
const requiredGates = existing ? expandRequiredGates(existing.required_gates, agentType, context) : deriveRequiredGates(agentType, context);
|
|
195
197
|
const updated = {
|
|
196
198
|
taskId,
|
|
197
199
|
required_gates: requiredGates,
|
|
198
200
|
turbo: turbo === true ? true : existing?.turbo,
|
|
201
|
+
test_engineer_exempt: agentType === "coder" ? context.testEngineerExempt === true && !requiredGates.includes("test_engineer") : existing?.test_engineer_exempt,
|
|
199
202
|
gates: existing?.gates ?? {}
|
|
200
203
|
};
|
|
201
204
|
await atomicWriteFile(evidencePath, JSON.stringify(updated, null, 2));
|
package/dist/cli/index.js
CHANGED
|
@@ -7,14 +7,14 @@ import {
|
|
|
7
7
|
getPluginLockFilePaths,
|
|
8
8
|
package_default,
|
|
9
9
|
resolveCommand
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-54dgk0bv.js";
|
|
11
11
|
import"./index-8f256d7t.js";
|
|
12
12
|
import"./index-c8s9a3zh.js";
|
|
13
13
|
import"./index-0gf6de8b.js";
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_AGENT_CONFIGS
|
|
16
16
|
} from "./index-1ey3dxq7.js";
|
|
17
|
-
import"./index-
|
|
17
|
+
import"./index-afgh75zg.js";
|
|
18
18
|
import"./index-scww5b77.js";
|
|
19
19
|
import"./index-9fxs0rm1.js";
|
|
20
20
|
import"./index-q1jaeynn.js";
|
|
@@ -35,7 +35,8 @@ import"./index-jtqkh8jf.js";
|
|
|
35
35
|
import"./index-5e4e2hvv.js";
|
|
36
36
|
import"./index-p0arc26j.js";
|
|
37
37
|
import"./index-zgwm4ryv.js";
|
|
38
|
-
import"./index-
|
|
38
|
+
import"./index-dqh3zhhc.js";
|
|
39
|
+
import"./index-x5g7et24.js";
|
|
39
40
|
import"./index-0dab9w37.js";
|
|
40
41
|
import"./index-293f68mj.js";
|
|
41
42
|
import"./index-5mkc2f9z.js";
|
|
@@ -45,9 +45,14 @@ var WorkspaceSchema = exports_external.object({
|
|
|
45
45
|
directory: exports_external.string(),
|
|
46
46
|
gitHead: exports_external.string().nullable(),
|
|
47
47
|
dirtyHash: exports_external.string().nullable(),
|
|
48
|
+
changedFiles: exports_external.array(exports_external.string()).nullable().optional(),
|
|
48
49
|
prHeadSha: exports_external.string().nullable(),
|
|
49
50
|
scope: exports_external.string().nullable()
|
|
50
51
|
}).strict();
|
|
52
|
+
var TaskChangeContextSchema = exports_external.object({
|
|
53
|
+
declaredFiles: exports_external.array(exports_external.string()).nullable(),
|
|
54
|
+
baseline: WorkspaceSchema
|
|
55
|
+
}).strict();
|
|
51
56
|
var PromptSchema = exports_external.object({
|
|
52
57
|
text: exports_external.string(),
|
|
53
58
|
chars: exports_external.number(),
|
|
@@ -82,6 +87,7 @@ var RecordSchema = exports_external.object({
|
|
|
82
87
|
mode: exports_external.string().optional(),
|
|
83
88
|
promptHash: exports_external.string().optional(),
|
|
84
89
|
workspace: WorkspaceSchema.optional(),
|
|
90
|
+
taskChangeContext: TaskChangeContextSchema.optional(),
|
|
85
91
|
prompt: PromptSchema.optional(),
|
|
86
92
|
generation: exports_external.number().optional(),
|
|
87
93
|
result: ResultSchema.optional(),
|
|
@@ -157,6 +163,7 @@ async function recordPendingDelegation(directory, input, options = {}) {
|
|
|
157
163
|
...input.mode ? { mode: input.mode } : {},
|
|
158
164
|
...input.promptHash ? { promptHash: input.promptHash } : {},
|
|
159
165
|
...input.workspace ? { workspace: input.workspace } : {},
|
|
166
|
+
...input.taskChangeContext ? { taskChangeContext: input.taskChangeContext } : {},
|
|
160
167
|
...input.prompt ? { prompt: input.prompt } : {},
|
|
161
168
|
...input.generation !== undefined ? { generation: input.generation } : {}
|
|
162
169
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
_internals,
|
|
4
|
+
captureWorkspaceSnapshot,
|
|
5
|
+
changedFilesSinceSnapshot,
|
|
6
|
+
compareWorkspaceSnapshot,
|
|
7
|
+
compareWorkspaceSnapshots,
|
|
8
|
+
digest,
|
|
9
|
+
parsePorcelainPaths,
|
|
10
|
+
workspaceSnapshotMatches
|
|
11
|
+
} from "./index-dqh3zhhc.js";
|
|
12
|
+
import"./index-a76rekgs.js";
|
|
13
|
+
export {
|
|
14
|
+
workspaceSnapshotMatches,
|
|
15
|
+
parsePorcelainPaths,
|
|
16
|
+
digest,
|
|
17
|
+
compareWorkspaceSnapshots,
|
|
18
|
+
compareWorkspaceSnapshot,
|
|
19
|
+
changedFilesSinceSnapshot,
|
|
20
|
+
captureWorkspaceSnapshot,
|
|
21
|
+
_internals
|
|
22
|
+
};
|
|
@@ -68,7 +68,8 @@ export declare const OPENCODE_ONLY_ARCHITECT_MODE_SKILLS: Array<{
|
|
|
68
68
|
* `kind`:
|
|
69
69
|
* - `identical`: `.opencode` and `.claude` SKILL.md must be byte-identical.
|
|
70
70
|
* `canonical` records which side wins when they drift (fix direction only;
|
|
71
|
-
* detection is symmetric).
|
|
71
|
+
* detection is symmetric). `extraIdenticalPaths` narrowly extends the same
|
|
72
|
+
* byte-identity contract to additional runtime mirrors when present.
|
|
72
73
|
* - `divergent`: both must exist; content intentionally differs per runtime.
|
|
73
74
|
* - `opencode-only`: `.opencode` exists; no `.claude` mirror expected.
|
|
74
75
|
*/
|
|
@@ -76,6 +77,7 @@ export declare const ADDITIONAL_SKILL_MIRROR_CONTRACTS: Array<{
|
|
|
76
77
|
slug: string;
|
|
77
78
|
kind: 'identical' | 'divergent' | 'opencode-only';
|
|
78
79
|
canonical?: '.claude' | '.opencode';
|
|
80
|
+
extraIdenticalPaths?: string[];
|
|
79
81
|
reason: string;
|
|
80
82
|
}>;
|
|
81
83
|
/**
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function isExactMarkdownPath(value: unknown): boolean;
|
|
2
|
+
/** Cheap pre-classification used to avoid Git snapshots for ineligible tasks. */
|
|
3
|
+
export declare function isMarkdownOnlyDeclaredScope(value: unknown): value is string[];
|
|
4
|
+
/** Require independent non-empty declared and observed exact-.md proof. */
|
|
5
|
+
export declare function isMarkdownOnlyTaskChange(declaredFiles: unknown, observedFiles: unknown): boolean;
|
package/dist/gate-evidence.d.ts
CHANGED
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
* Evidence files survive session restarts (unlike in-memory state).
|
|
10
10
|
* Agents never write these files directly — only the hook does.
|
|
11
11
|
* Gates are append-only: required_gates can only grow, never shrink.
|
|
12
|
+
*
|
|
13
|
+
* Threat boundary: this store provides atomic, path-contained durability and
|
|
14
|
+
* auditability for cooperative same-user agents. It is not tamper-proof
|
|
15
|
+
* authorization against a process with arbitrary same-user workspace access;
|
|
16
|
+
* that requires a protected trust root outside the project workspace.
|
|
12
17
|
*/
|
|
13
18
|
export interface GateEvidence {
|
|
14
19
|
sessionId: string;
|
|
@@ -20,8 +25,14 @@ export interface TaskEvidence {
|
|
|
20
25
|
required_gates: string[];
|
|
21
26
|
gates: Record<string, GateEvidence>;
|
|
22
27
|
turbo?: boolean;
|
|
28
|
+
/** Durable proof that the coder dispatch was classified as exact Markdown-only. */
|
|
29
|
+
test_engineer_exempt?: boolean;
|
|
23
30
|
}
|
|
24
31
|
export declare const DEFAULT_REQUIRED_GATES: string[];
|
|
32
|
+
export interface GateDerivationContext {
|
|
33
|
+
/** Trusted pre/post workspace classification; false/absent fails closed. */
|
|
34
|
+
testEngineerExempt?: boolean;
|
|
35
|
+
}
|
|
25
36
|
/**
|
|
26
37
|
* Canonical task-id validation helper.
|
|
27
38
|
* Delegates to the shared strict validator (#452 item 2).
|
|
@@ -32,12 +43,12 @@ export declare function isValidTaskId(taskId: string): boolean;
|
|
|
32
43
|
* Maps the first-dispatched agent type to the initial required_gates array.
|
|
33
44
|
* Unknown agent types fall back to the safe default ["reviewer", "test_engineer"].
|
|
34
45
|
*/
|
|
35
|
-
export declare function deriveRequiredGates(agentType: string): string[];
|
|
46
|
+
export declare function deriveRequiredGates(agentType: string, context?: GateDerivationContext): string[];
|
|
36
47
|
/**
|
|
37
48
|
* Returns the union of existingGates and deriveRequiredGates(newAgentType).
|
|
38
49
|
* Sorted, deduplicated. Gates can only grow, never shrink.
|
|
39
50
|
*/
|
|
40
|
-
export declare function expandRequiredGates(existingGates: string[], newAgentType: string): string[];
|
|
51
|
+
export declare function expandRequiredGates(existingGates: string[], newAgentType: string, context?: GateDerivationContext): string[];
|
|
41
52
|
/**
|
|
42
53
|
* Creates or updates .swarm/evidence/{taskId}.json with a gate pass entry.
|
|
43
54
|
* If file doesn't exist: creates with required_gates from deriveRequiredGates(gate).
|
|
@@ -50,7 +61,7 @@ export declare function recordGateEvidence(directory: string, taskId: string, ga
|
|
|
50
61
|
* Used when non-gate agents are dispatched (coder, explorer, sme, etc.).
|
|
51
62
|
* Creates evidence file if it doesn't exist yet.
|
|
52
63
|
*/
|
|
53
|
-
export declare function recordAgentDispatch(directory: string, taskId: string, agentType: string, turbo?: boolean): Promise<void>;
|
|
64
|
+
export declare function recordAgentDispatch(directory: string, taskId: string, agentType: string, turbo?: boolean, context?: GateDerivationContext): Promise<void>;
|
|
54
65
|
/**
|
|
55
66
|
* Returns the TaskEvidence for a task, or null if file missing or parse error.
|
|
56
67
|
* Never throws.
|