opencode-swarm 7.121.1 → 7.121.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.
Files changed (31) hide show
  1. package/dist/cli/{curation-policy-re2kaysb.js → curation-policy-10wnhpwn.js} +2 -2
  2. package/dist/cli/{curator-llm-factory-jkbachdb.js → curator-llm-factory-vcyvbny0.js} +10 -10
  3. package/dist/cli/{curator-tesgq6ye.js → curator-mwvrryf3.js} +10 -10
  4. package/dist/cli/{evidence-summary-service-jtx5q3r6.js → evidence-summary-service-k14ykm03.js} +2 -2
  5. package/dist/cli/{guardrail-explain-hqz48re6.js → guardrail-explain-tgkk87z5.js} +11 -11
  6. package/dist/cli/{hive-promoter-4vfe1rcs.js → hive-promoter-z4tw1gfv.js} +10 -10
  7. package/dist/cli/{index-rywkdacj.js → index-0f800qg7.js} +3 -3
  8. package/dist/cli/{index-8cp19x15.js → index-1y03193n.js} +1 -1
  9. package/dist/cli/{index-k7gvykn4.js → index-2ygp3qq4.js} +11 -11
  10. package/dist/cli/{index-nhgw7de8.js → index-35xyj7gn.js} +1 -1
  11. package/dist/cli/{index-69ms9ny1.js → index-5a3xsnzg.js} +1 -1
  12. package/dist/cli/{index-3366gs26.js → index-db82jxt7.js} +2 -2
  13. package/dist/cli/{index-j5xv8zbp.js → index-emkb0bbe.js} +1 -1
  14. package/dist/cli/{index-0k4r8111.js → index-ft6jw816.js} +4 -4
  15. package/dist/cli/{index-0e1v02hq.js → index-j8349ac0.js} +1 -1
  16. package/dist/cli/{index-0mbmfmt0.js → index-qt2yaghg.js} +2 -1
  17. package/dist/cli/{index-fndvr7fr.js → index-rbfq77sz.js} +1 -1
  18. package/dist/cli/{index-78b192v7.js → index-x4fwtd59.js} +3 -3
  19. package/dist/cli/{index-e7yqazk3.js → index-y0qa3xf0.js} +38 -31
  20. package/dist/cli/index.js +10 -10
  21. package/dist/cli/{knowledge-escalator-0ejqs8c9.js → knowledge-escalator-8ajq1fhb.js} +3 -3
  22. package/dist/cli/{knowledge-events-wx9e37ba.js → knowledge-events-2sjy3aa7.js} +1 -1
  23. package/dist/cli/{knowledge-store-rnajx33a.js → knowledge-store-27cesthc.js} +1 -1
  24. package/dist/cli/{knowledge-validator-1f4mkzmc.js → knowledge-validator-9keh3p8j.js} +4 -4
  25. package/dist/cli/{scan-cursor-qapm0sxj.js → scan-cursor-qmsmmg1b.js} +2 -2
  26. package/dist/cli/{skill-generator-tkv7s12g.js → skill-generator-hkyxdc3j.js} +5 -5
  27. package/dist/config/plan-schema.d.ts +3 -0
  28. package/dist/hooks/delegation-gate.d.ts +115 -0
  29. package/dist/index.js +20 -10
  30. package/dist/tools/save-plan.d.ts +2 -0
  31. package/package.json +1 -1
@@ -65,7 +65,7 @@ import {
65
65
  saveTaskSetSnapshot,
66
66
  transientBackoff,
67
67
  validateProjectRoot
68
- } from "./index-j5xv8zbp.js";
68
+ } from "./index-emkb0bbe.js";
69
69
  import {
70
70
  withTimeout
71
71
  } from "./index-4905hd2m.js";
@@ -95,15 +95,15 @@ import {
95
95
  retireSkill,
96
96
  selectCandidateEntries,
97
97
  syncBundledProjectSkillsIfMissingAsync
98
- } from "./index-78b192v7.js";
98
+ } from "./index-x4fwtd59.js";
99
99
  import {
100
100
  readRecentEscalations
101
- } from "./index-0k4r8111.js";
101
+ } from "./index-ft6jw816.js";
102
102
  import {
103
103
  alreadyCuratedThisGeneration,
104
104
  claimNextScanBatch,
105
105
  resolveCohortId
106
- } from "./index-0e1v02hq.js";
106
+ } from "./index-j8349ac0.js";
107
107
  import {
108
108
  CURATOR_INIT_PROMPT,
109
109
  CURATOR_PHASE_PROMPT,
@@ -136,11 +136,11 @@ import {
136
136
  validateActionability,
137
137
  validateActionableFields,
138
138
  validateLesson
139
- } from "./index-3366gs26.js";
139
+ } from "./index-db82jxt7.js";
140
140
  import {
141
141
  authorizeCuration,
142
142
  buildConfigFingerprintInput
143
- } from "./index-69ms9ny1.js";
143
+ } from "./index-5a3xsnzg.js";
144
144
  import {
145
145
  cohortConfigFingerprint
146
146
  } from "./index-rtry5xyf.js";
@@ -170,7 +170,7 @@ import {
170
170
  transactFile,
171
171
  transactKnowledge,
172
172
  wordBigrams
173
- } from "./index-rywkdacj.js";
173
+ } from "./index-0f800qg7.js";
174
174
  import {
175
175
  MAX_EVENT_LOG_ENTRIES,
176
176
  _internals,
@@ -180,7 +180,7 @@ import {
180
180
  recordHiveKnowledgeEvent,
181
181
  recordKnowledgeEvent,
182
182
  resolveKnowledgeEventsPath
183
- } from "./index-nhgw7de8.js";
183
+ } from "./index-35xyj7gn.js";
184
184
  import {
185
185
  resolveHiveDataDir,
186
186
  resolveHiveEventsPath,
@@ -204,7 +204,7 @@ import {
204
204
  import {
205
205
  PlanSchema,
206
206
  RetrospectiveEvidenceSchema
207
- } from "./index-0mbmfmt0.js";
207
+ } from "./index-qt2yaghg.js";
208
208
  import {
209
209
  AGENT_TOOL_MAP,
210
210
  ALL_SUBAGENT_NAMES,
@@ -9759,7 +9759,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
9759
9759
  }
9760
9760
  if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
9761
9761
  try {
9762
- const skillModule = await import("./skill-generator-tkv7s12g.js");
9762
+ const skillModule = await import("./skill-generator-hkyxdc3j.js");
9763
9763
  for (const cand of skillCandidates) {
9764
9764
  if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
9765
9765
  continue;
@@ -10096,7 +10096,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
10096
10096
  } catch {}
10097
10097
  }
10098
10098
  if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
10099
- const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-0ejqs8c9.js");
10099
+ const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-8ajq1fhb.js");
10100
10100
  for (const { id } of contradictedEntries) {
10101
10101
  try {
10102
10102
  await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
@@ -10894,7 +10894,7 @@ async function runCuratorPostMortem(directory, options = {}) {
10894
10894
  warnings.push("Failed to collect knowledge summary.");
10895
10895
  }
10896
10896
  try {
10897
- const { getScanStatus } = await import("./scan-cursor-qapm0sxj.js");
10897
+ const { getScanStatus } = await import("./scan-cursor-qmsmmg1b.js");
10898
10898
  const scanStatus = await getScanStatus(directory);
10899
10899
  if (scanStatus.remaining_estimate > 0) {
10900
10900
  warnings.push(`Fair scan: reviewed ${knowledgeSummary.length} entries this sweep (generation ${scanStatus.generation}); ${scanStatus.remaining_estimate} more eligible entries will be visited in future curation sweeps.`);
@@ -11068,7 +11068,7 @@ var _internals15 = {
11068
11068
  loadDefaultKnowledgeConfig: async (directory) => {
11069
11069
  const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-vwxpsk6j.js");
11070
11070
  try {
11071
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-fndvr7fr.js");
11071
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-rbfq77sz.js");
11072
11072
  const loaded = loadPluginConfigWithMeta2(directory);
11073
11073
  return KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
11074
11074
  } catch {
@@ -11076,11 +11076,11 @@ var _internals15 = {
11076
11076
  }
11077
11077
  },
11078
11078
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig, generation) => {
11079
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-tesgq6ye.js");
11079
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-mwvrryf3.js");
11080
11080
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig, generation);
11081
11081
  },
11082
11082
  checkHivePromotions: async (entries, knowledgeConfig, directory) => {
11083
- const { checkHivePromotions } = await import("./hive-promoter-4vfe1rcs.js");
11083
+ const { checkHivePromotions } = await import("./hive-promoter-z4tw1gfv.js");
11084
11084
  return checkHivePromotions(entries, knowledgeConfig, directory);
11085
11085
  },
11086
11086
  applyProposalTriage: async (directory, triage) => {
@@ -11089,7 +11089,7 @@ var _internals15 = {
11089
11089
  activateProposal,
11090
11090
  listSkills: listSkills2,
11091
11091
  sanitizeSlug
11092
- } = await import("./skill-generator-tkv7s12g.js");
11092
+ } = await import("./skill-generator-hkyxdc3j.js");
11093
11093
  const result = {
11094
11094
  approved: [],
11095
11095
  rejected: [],
@@ -13557,7 +13557,7 @@ function hashContent(content) {
13557
13557
  async function loadConfigForPolicyCurator(directory) {
13558
13558
  const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-vwxpsk6j.js");
13559
13559
  try {
13560
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-fndvr7fr.js");
13560
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-rbfq77sz.js");
13561
13561
  const { config: loadedConfig } = loadPluginConfigWithMeta2(directory);
13562
13562
  return KnowledgeConfigSchema2.parse(loadedConfig.knowledge ?? {});
13563
13563
  } catch {
@@ -18867,8 +18867,8 @@ var _internals28 = {
18867
18867
  loadCuratorDeps: async () => {
18868
18868
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
18869
18869
  import("./schema-vwxpsk6j.js"),
18870
- import("./curator-tesgq6ye.js"),
18871
- import("./curator-llm-factory-jkbachdb.js")
18870
+ import("./curator-mwvrryf3.js"),
18871
+ import("./curator-llm-factory-vcyvbny0.js")
18872
18872
  ]);
18873
18873
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
18874
18874
  }
@@ -19366,7 +19366,7 @@ import { fileURLToPath } from "url";
19366
19366
  // package.json
19367
19367
  var package_default = {
19368
19368
  name: "opencode-swarm",
19369
- version: "7.121.1",
19369
+ version: "7.121.2",
19370
19370
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
19371
19371
  main: "dist/index.js",
19372
19372
  types: "dist/index.d.ts",
@@ -19806,7 +19806,7 @@ async function computeCurationDiagnostics(directory, entries) {
19806
19806
  let scanCompleted = false;
19807
19807
  let scanRemaining = 0;
19808
19808
  try {
19809
- const { getScanStatus } = await import("./scan-cursor-qapm0sxj.js");
19809
+ const { getScanStatus } = await import("./scan-cursor-qmsmmg1b.js");
19810
19810
  const status = await getScanStatus(directory);
19811
19811
  scanGeneration = status.generation;
19812
19812
  scanCompleted = status.completed;
@@ -19819,14 +19819,14 @@ async function computeCurationDiagnostics(directory, entries) {
19819
19819
  const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-vwxpsk6j.js");
19820
19820
  let config;
19821
19821
  try {
19822
- const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-fndvr7fr.js");
19822
+ const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-rbfq77sz.js");
19823
19823
  const loaded = loadPluginConfigWithMeta2(directory);
19824
19824
  config = KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
19825
19825
  } catch {
19826
19826
  config = KnowledgeConfigSchema2.parse({});
19827
19827
  }
19828
19828
  const { cohortConfigFingerprint: cohortConfigFingerprint2 } = await import("./config-fingerprint-v22xh5a2.js");
19829
- const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-re2kaysb.js");
19829
+ const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-10wnhpwn.js");
19830
19830
  const currentFp = cohortConfigFingerprint2(buildConfigFingerprintInput2(config));
19831
19831
  const cohortFp = await readCohortConfigFingerprint(directory);
19832
19832
  configMatch = cohortFp === null ? null : currentFp === cohortFp;
@@ -21817,7 +21817,7 @@ async function handleEvidenceCommand(directory, args) {
21817
21817
  return formatTaskEvidenceMarkdown(evidenceData);
21818
21818
  }
21819
21819
  async function handleEvidenceSummaryCommand(directory) {
21820
- const { buildEvidenceSummary } = await import("./evidence-summary-service-jtx5q3r6.js");
21820
+ const { buildEvidenceSummary } = await import("./evidence-summary-service-k14ykm03.js");
21821
21821
  const artifact = await buildEvidenceSummary(directory);
21822
21822
  if (!artifact) {
21823
21823
  return "No plan found. Run `/swarm plan` to check plan status.";
@@ -39194,7 +39194,7 @@ function buildDetailedHelp(commandName, entry) {
39194
39194
  async function handleHelpCommand(ctx) {
39195
39195
  const targetCommand = ctx.args.join(" ");
39196
39196
  if (!targetCommand) {
39197
- const { buildHelpText } = await import("./index-k7gvykn4.js");
39197
+ const { buildHelpText } = await import("./index-2ygp3qq4.js");
39198
39198
  return buildHelpText();
39199
39199
  }
39200
39200
  const tokens = targetCommand.split(/\s+/);
@@ -39203,7 +39203,7 @@ async function handleHelpCommand(ctx) {
39203
39203
  return _internals61.buildDetailedHelp(resolved.key, resolved.entry);
39204
39204
  }
39205
39205
  const similar = _internals61.findSimilarCommands(targetCommand);
39206
- const { buildHelpText: fullHelp } = await import("./index-k7gvykn4.js");
39206
+ const { buildHelpText: fullHelp } = await import("./index-2ygp3qq4.js");
39207
39207
  if (similar.length > 0) {
39208
39208
  return `Command '/swarm ${targetCommand}' not found.
39209
39209
 
@@ -39336,7 +39336,7 @@ var COMMAND_REGISTRY = {
39336
39336
  },
39337
39337
  "guardrail explain": {
39338
39338
  handler: async (ctx) => {
39339
- const { handleGuardrailExplain } = await import("./guardrail-explain-hqz48re6.js");
39339
+ const { handleGuardrailExplain } = await import("./guardrail-explain-tgkk87z5.js");
39340
39340
  return handleGuardrailExplain(ctx.directory, ctx.args);
39341
39341
  },
39342
39342
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -39346,7 +39346,7 @@ var COMMAND_REGISTRY = {
39346
39346
  },
39347
39347
  "guardrail-explain": {
39348
39348
  handler: async (ctx) => {
39349
- const { handleGuardrailExplain } = await import("./guardrail-explain-hqz48re6.js");
39349
+ const { handleGuardrailExplain } = await import("./guardrail-explain-tgkk87z5.js");
39350
39350
  return handleGuardrailExplain(ctx.directory, ctx.args);
39351
39351
  },
39352
39352
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -40597,6 +40597,8 @@ DELEGATION ENVELOPE FIELDS \u2014 include these in every delegation for traceabi
40597
40597
 
40598
40598
  Before delegating to {{AGENT_PREFIX}}reviewer: call check_gate_status for the current task_id and include the gate results in the GATES field of the reviewer message. Format: GATES: lint=PASS/FAIL, sast_scan=PASS/FAIL, secretscan=PASS/FAIL (use PASS/FAIL/skipped for each gate). If no gates have been run yet, use GATES: none.
40599
40599
 
40600
+ ACCEPTANCE FIELD RESOLUTION \u2014 before every {{AGENT_PREFIX}}coder (and {{AGENT_PREFIX}}reviewer) delegation, populate that delegation's ACCEPTANCE field like this: (1) read the current task's \`fr_refs\` from the plan; (2) if \`fr_refs\` is non-empty, look up EVERY listed FR-###/SC-### id in the current \`.swarm/spec.md\` and copy each one's full requirement text into ACCEPTANCE VERBATIM \u2014 byte-for-byte, no summarizing or paraphrasing, and concatenate all of them when a task maps to more than one; (3) if \`fr_refs\` is empty or absent, populate ACCEPTANCE with a task-derived one-line restatement of what DONE looks like instead (the same pattern as \`acceptanceCriteria\` above). ACCEPTANCE must never be empty \u2014 lacking a spec mapping is normal and is not a reason to omit it.
40601
+
40600
40602
  <!-- BEHAVIORAL_GUIDANCE_START -->
40601
40603
  PARTIAL GATE RATIONALIZATIONS \u2014 automated gates \u2260 agent review. Running SOME gates is NOT compliance:
40602
40604
  \u2717 "I ran pre_check_batch so the code is verified" \u2192 pre_check_batch does NOT replace {{AGENT_PREFIX}}reviewer or {{AGENT_PREFIX}}test_engineer
@@ -40773,7 +40775,7 @@ FILE: src/auth/login.ts
40773
40775
  INPUT: Validate email format, password >= 8 chars
40774
40776
  OUTPUT: Modified file
40775
40777
  CONSTRAINT: Do not modify other functions
40776
- ACCEPTANCE: Populate from the plan task's acceptance criteria / FR / SC when the task has them (one item per line, or FR-/SC-style references), so the coder can gate its implementation on each. Omit the field entirely when the task has no structured acceptance criteria.
40778
+ ACCEPTANCE: [copied verbatim from spec.md, or a task-derived DONE restatement \u2014 see ACCEPTANCE FIELD RESOLUTION]
40777
40779
  SKILLS: file:.claude/skills/engineering-conventions/SKILL.md
40778
40780
 
40779
40781
  {{AGENT_PREFIX}}reviewer
@@ -40781,8 +40783,9 @@ TASK: Review login validation
40781
40783
  FILE: src/auth/login.ts
40782
40784
  CHECK: [security, correctness, edge-cases]
40783
40785
  GATES: lint=PASS, sast_scan=PASS, secretscan=PASS
40786
+ ACCEPTANCE: [copied verbatim from spec.md, or a task-derived DONE restatement \u2014 see ACCEPTANCE FIELD RESOLUTION; same text as the coder delegation for this task]
40784
40787
  SKILLS_USED_BY_CODER: file:.claude/skills/engineering-conventions/SKILL.md
40785
- OUTPUT: VERDICT + RISK + ISSUES
40788
+ OUTPUT: VERDICT + RISK + ISSUES + ACCEPTANCE_SATISFACTION
40786
40789
  SKILLS: file:.claude/skills/engineering-conventions/SKILL.md
40787
40790
 
40788
40791
  {{AGENT_PREFIX}}test_engineer
@@ -42307,7 +42310,7 @@ AUTOMATIC REJECTION: Any vaporware indicator triggers immediate rejection before
42307
42310
  Emit event: 'reviewer_substance_check' with fields: { function_name: string, issue_type: string }
42308
42311
 
42309
42312
  TIER 1: CORRECTNESS (mandatory, always run)
42310
- Does the code do what the task acceptance criteria require? Check: every acceptance criterion has corresponding implementation. First-error focus: if you find a correctness issue, stop. Report it. Do not continue to style or optimization issues.
42313
+ Does the code do what the task acceptance criteria require? Check: every acceptance criterion has corresponding implementation. When your input includes an ACCEPTANCE field, that field \u2014 not your own impression of "looks correct" \u2014 is the authoritative acceptance criteria: verify the diff satisfies EVERY requirement stated in ACCEPTANCE (including verbatim FR/SC text when the task maps to one or more spec requirements), not merely that the diff is well-formed or plausible in isolation. A diff that is clean, idiomatic, and bug-free but does not satisfy an ACCEPTANCE requirement is a Tier 1 CORRECTNESS failure. First-error focus: if you find a correctness issue, stop. Report it. Do not continue to style or optimization issues.
42311
42314
 
42312
42315
  TIER 2: SAFETY (mandatory for MODERATE+, always for COMPLEX)
42313
42316
  Does the code introduce security vulnerabilities, data loss risks, or breaking changes? Check against: SAST findings, secret scan results, import analysis. Anti-rubber-stamp: "No issues found" requires evidence. State what you checked.
@@ -42345,9 +42348,12 @@ DIFF: [changed files/functions, or "infer from FILE" if omitted]
42345
42348
  AFFECTS: [callers/consumers/dependents to inspect, or "infer from diff"]
42346
42349
  CHECK: [list of dimensions to evaluate]
42347
42350
  GATES: [pre-completed gate results (lint, SAST, secretscan, etc.), or "none" if unavailable]
42351
+ ACCEPTANCE: [verbatim FR/SC requirement text this diff must satisfy, copied byte-for-byte from spec.md when the task maps to one or more FR-###/SC-### items \u2014 never a paraphrase or summary. When the task maps to no spec requirement, this is a task-derived, one-line restatement of what DONE looks like instead. This field is never empty.]
42348
42352
  SKILLS: [optional \u2014 either "none", repo-relative file: references (preferred), or inline skill content pasted by architect]
42349
42353
  SKILLS_USED_BY_CODER: [list of skill paths that were passed to the coder for this task, or "none" if no skills were used]
42350
42354
 
42355
+ ACCEPTANCE HANDLING: ACCEPTANCE is the authoritative definition of "done" for this task \u2014 evaluate the diff against it explicitly and directly, not only against your own general impression of code quality or correctness in isolation. Before writing your verdict, check EACH item in ACCEPTANCE against the diff and be prepared to state whether it is met. If the diff fails to satisfy any item in ACCEPTANCE, that is a Tier 1 CORRECTNESS failure \u2014 REJECT even if the code otherwise looks clean and well-written, and cite the specific unmet ACCEPTANCE item(s) in your FIXES.
42356
+
42351
42357
  SKILLS HANDLING: If SKILLS is present and not "none", read the skill names/descriptions first, then load every referenced skill that applies before beginning your review. If uncertain whether a skill applies, load it.
42352
42358
  - A file entry may include a short description after the path; use the description to decide whether the full skill body is relevant.
42353
42359
  - For \`file:\` entries, use the search tool to read the referenced \`SKILL.md\` file with \`include\` set to that exact repo-relative path, \`mode: regex\`, \`query: .*\`, \`max_results: 1000\`, and \`max_lines: 1000\`.
@@ -42373,6 +42379,7 @@ VERDICT: APPROVED | REJECTED
42373
42379
  REUSE_RE_VERIFICATION: [VERIFIED | DUPLICATION_DETECTED | SKIPPED] \u2014 DUPLICATION_DETECTED is only valid when VERDICT is REJECTED
42374
42380
  RISK: LOW | MEDIUM | HIGH | CRITICAL
42375
42381
  ISSUES: list with line numbers, grouped by CHECK dimension
42382
+ ACCEPTANCE_SATISFACTION: SATISFIED | PARTIAL | NOT_SATISFIED \u2014 one line per item in the input ACCEPTANCE field, stating explicitly whether the diff satisfies it (with evidence: file:line or "no corresponding implementation found"). This is a distinct question from "does the diff look correct" \u2014 assess conformance to ACCEPTANCE even when the diff is otherwise well-written. NOT_SATISFIED on any item forces VERDICT: REJECTED.
42376
42383
  TASK: [task id being reviewed, or "unknown"]
42377
42384
  SKILL_COMPLIANCE: COMPLIANT | PARTIAL | VIOLATED \u2014 [list of violations or "all rules followed"]
42378
42385
  DIRECTIVE_COMPLIANCE: one line per knowledge directive shown during this phase (IDs listed in the DIRECTIVES TO VERIFY block of your prompt, when present). Use exactly one of:
package/dist/cli/index.js CHANGED
@@ -7,28 +7,28 @@ import {
7
7
  getPluginLockFilePaths,
8
8
  package_default,
9
9
  resolveCommand
10
- } from "./index-e7yqazk3.js";
10
+ } from "./index-y0qa3xf0.js";
11
11
  import"./index-kyvg2cmp.js";
12
12
  import"./index-vqcgmy4y.js";
13
- import"./index-j5xv8zbp.js";
13
+ import"./index-emkb0bbe.js";
14
14
  import"./index-4905hd2m.js";
15
15
  import"./index-nprawcc0.js";
16
- import"./index-78b192v7.js";
17
- import"./index-0k4r8111.js";
18
- import"./index-0e1v02hq.js";
16
+ import"./index-x4fwtd59.js";
17
+ import"./index-ft6jw816.js";
18
+ import"./index-j8349ac0.js";
19
19
  import"./index-vxv732ex.js";
20
20
  import"./index-c8s9a3zh.js";
21
21
  import"./index-816rkp4y.js";
22
22
  import"./index-22e127jw.js";
23
- import"./index-3366gs26.js";
24
- import"./index-69ms9ny1.js";
23
+ import"./index-db82jxt7.js";
24
+ import"./index-5a3xsnzg.js";
25
25
  import"./index-rtry5xyf.js";
26
- import"./index-rywkdacj.js";
27
- import"./index-nhgw7de8.js";
26
+ import"./index-0f800qg7.js";
27
+ import"./index-35xyj7gn.js";
28
28
  import"./index-ae75rja9.js";
29
29
  import"./index-3jvqw5hy.js";
30
30
  import"./index-9xpgytj9.js";
31
- import"./index-0mbmfmt0.js";
31
+ import"./index-qt2yaghg.js";
32
32
  import"./index-gnp9x6se.js";
33
33
  import {
34
34
  DEFAULT_AGENT_CONFIGS
@@ -8,9 +8,9 @@ import {
8
8
  maybeEscalateOnViolation,
9
9
  maybeQuarantineOnContradiction,
10
10
  readRecentEscalations
11
- } from "./index-0k4r8111.js";
12
- import"./index-rywkdacj.js";
13
- import"./index-nhgw7de8.js";
11
+ } from "./index-ft6jw816.js";
12
+ import"./index-0f800qg7.js";
13
+ import"./index-35xyj7gn.js";
14
14
  import"./index-ae75rja9.js";
15
15
  import"./index-3jvqw5hy.js";
16
16
  import"./index-4rhcth7a.js";
@@ -25,7 +25,7 @@ import {
25
25
  resolveKnowledgeCounterBaselinePath,
26
26
  resolveKnowledgeEventsPath,
27
27
  resolveLegacyApplicationLogPath
28
- } from "./index-nhgw7de8.js";
28
+ } from "./index-35xyj7gn.js";
29
29
  import"./index-ae75rja9.js";
30
30
  import"./index-3jvqw5hy.js";
31
31
  import"./index-zgwm4ryv.js";
@@ -40,7 +40,7 @@ import {
40
40
  transactKnowledge,
41
41
  transactKnowledgeWithCas,
42
42
  wordBigrams
43
- } from "./index-rywkdacj.js";
43
+ } from "./index-0f800qg7.js";
44
44
  import {
45
45
  resolveHiveDataDir
46
46
  } from "./index-ae75rja9.js";
@@ -23,11 +23,11 @@ import {
23
23
  validateLesson,
24
24
  validateSkillCandidatePath,
25
25
  validateSkillPath
26
- } from "./index-3366gs26.js";
27
- import"./index-69ms9ny1.js";
26
+ } from "./index-db82jxt7.js";
27
+ import"./index-5a3xsnzg.js";
28
28
  import"./index-rtry5xyf.js";
29
- import"./index-rywkdacj.js";
30
- import"./index-nhgw7de8.js";
29
+ import"./index-0f800qg7.js";
30
+ import"./index-35xyj7gn.js";
31
31
  import"./index-ae75rja9.js";
32
32
  import"./index-3jvqw5hy.js";
33
33
  import"./index-4rhcth7a.js";
@@ -4,8 +4,8 @@ import {
4
4
  alreadyCuratedThisGeneration,
5
5
  claimNextScanBatch,
6
6
  getScanStatus
7
- } from "./index-0e1v02hq.js";
8
- import"./index-rywkdacj.js";
7
+ } from "./index-j8349ac0.js";
8
+ import"./index-0f800qg7.js";
9
9
  import"./index-ae75rja9.js";
10
10
  import"./index-3jvqw5hy.js";
11
11
  import"./index-4rhcth7a.js";
@@ -33,12 +33,12 @@ import {
33
33
  sanitizeSlug,
34
34
  selectCandidateEntries,
35
35
  writeEvalStub
36
- } from "./index-78b192v7.js";
37
- import"./index-3366gs26.js";
38
- import"./index-69ms9ny1.js";
36
+ } from "./index-x4fwtd59.js";
37
+ import"./index-db82jxt7.js";
38
+ import"./index-5a3xsnzg.js";
39
39
  import"./index-rtry5xyf.js";
40
- import"./index-rywkdacj.js";
41
- import"./index-nhgw7de8.js";
40
+ import"./index-0f800qg7.js";
41
+ import"./index-35xyj7gn.js";
42
42
  import"./index-ae75rja9.js";
43
43
  import"./index-3jvqw5hy.js";
44
44
  import"./index-4rhcth7a.js";
@@ -69,6 +69,7 @@ export declare const TaskSchema: z.ZodObject<{
69
69
  files_touched: z.ZodDefault<z.ZodArray<z.ZodString>>;
70
70
  evidence_path: z.ZodOptional<z.ZodString>;
71
71
  blocked_reason: z.ZodOptional<z.ZodString>;
72
+ fr_refs: z.ZodOptional<z.ZodArray<z.ZodString>>;
72
73
  }, z.core.$strip>;
73
74
  export type Task = z.infer<typeof TaskSchema>;
74
75
  export declare const PhaseSchema: z.ZodObject<{
@@ -103,6 +104,7 @@ export declare const PhaseSchema: z.ZodObject<{
103
104
  files_touched: z.ZodDefault<z.ZodArray<z.ZodString>>;
104
105
  evidence_path: z.ZodOptional<z.ZodString>;
105
106
  blocked_reason: z.ZodOptional<z.ZodString>;
107
+ fr_refs: z.ZodOptional<z.ZodArray<z.ZodString>>;
106
108
  }, z.core.$strip>>>;
107
109
  type: z.ZodOptional<z.ZodEnum<{
108
110
  code: "code";
@@ -148,6 +150,7 @@ export declare const PlanSchema: z.ZodObject<{
148
150
  files_touched: z.ZodDefault<z.ZodArray<z.ZodString>>;
149
151
  evidence_path: z.ZodOptional<z.ZodString>;
150
152
  blocked_reason: z.ZodOptional<z.ZodString>;
153
+ fr_refs: z.ZodOptional<z.ZodArray<z.ZodString>>;
151
154
  }, z.core.$strip>>>;
152
155
  type: z.ZodOptional<z.ZodEnum<{
153
156
  code: "code";
@@ -66,6 +66,20 @@ interface ValidationContext {
66
66
  /**
67
67
  * Validates a DelegationEnvelope against the current plan and agent list.
68
68
  * Returns { valid: true } on success, or { valid: false; reason: string } on failure.
69
+ *
70
+ * NOTE (#1687, kept SEPARATE from {@link validateCoderReviewerAcceptanceField}):
71
+ * this validator operates on a *structured* `DelegationEnvelope` object recovered
72
+ * from the OLD `KEY:VALUE` envelope format (`taskId:`/`targetAgent:`/`action:`/
73
+ * `commandType:`/`files:`/`acceptanceCriteria:`) and is consumed ADVISORY-ONLY,
74
+ * POST-execution via {@link appendDelegationEnvelopeAdvisory} in `toolAfter` (it
75
+ * never throws). The free-text coder/reviewer format
76
+ * (`TASK:`/`FILE:`/`ACCEPTANCE:`) does NOT parse into this shape
77
+ * (`parseDelegationEnvelope` returns `null`), so this path never fires on a real
78
+ * coder/reviewer dispatch. The pre-dispatch, BLOCKING acceptance-field gate for
79
+ * the free-text format lives in {@link validateCoderReviewerAcceptanceField};
80
+ * the two are intentionally not merged (advisory-vs-blocking, structured-vs-
81
+ * free-text are different contracts). Do not delete this function — it retains a
82
+ * real purpose for the old envelope format and other delegation types.
69
83
  */
70
84
  export declare function validateDelegationEnvelope(envelope: unknown, context: ValidationContext): EnvelopeValidationResult;
71
85
  /**
@@ -87,6 +101,107 @@ export declare function validateDelegationEnvelope(envelope: unknown, context: V
87
101
  * the side effect (advisory push) is the production purpose.
88
102
  */
89
103
  export declare function appendDelegationEnvelopeAdvisory(session: AgentSessionState, promptText: string, context: ValidationContext): EnvelopeValidationResult | null;
104
+ /**
105
+ * FR-003 / SC-003 / SC-004 (issue #1687): pre-dispatch acceptance-criteria
106
+ * enforcement for **coder and reviewer** delegations, operating on the REAL
107
+ * free-text delegation prompt (`TASK:`/`FILE:`/`INPUT:`/`OUTPUT:`/`CONSTRAINT:`/
108
+ * `ACCEPTANCE:`/`SKILLS:`) the architect actually sends via the native Task tool.
109
+ *
110
+ * Deliberately kept SEPARATE from {@link validateDelegationEnvelope} (see the
111
+ * sibling note there), NOT a rename/reuse of it, because the semantics differ on
112
+ * two axes: this function parses the FREE-TEXT `ACCEPTANCE:` line (not a
113
+ * structured envelope object) and is consumed as a BLOCKING, PRE-execution
114
+ * (`toolBefore`) gate (not the advisory, post-execution `toolAfter` path that
115
+ * `validateDelegationEnvelope` feeds via {@link appendDelegationEnvelopeAdvisory}).
116
+ * The two formats never overlap — `parseDelegationEnvelope` returns `null` for
117
+ * the free-text coder/reviewer format — so merging them would conflate
118
+ * advisory-vs-blocking and structured-vs-free-text contracts. M15's advisory
119
+ * mechanism is left fully intact for the old envelope format and other
120
+ * delegation types.
121
+ *
122
+ * A dispatch passes when an `ACCEPTANCE:` line exists AND the field carries
123
+ * non-empty, non-whitespace content — either INLINE on the header line (the
124
+ * architect-instructed same-line format) OR on the lines that FOLLOW a bare
125
+ * `ACCEPTANCE:` header, up to (but excluding) the next INPUT-FORMAT field header
126
+ * (`^[A-Z][A-Z0-9_]*:`, e.g. `SKILLS:`) or end of input. The multi-line form is
127
+ * a plausible way to paste a verbatim FR/SC body that spans lines (PR #1864
128
+ * review feedback), so treating a bare header + following content as EMPTY would
129
+ * false-block a good-faith copy. The next-field-header terminator ensures
130
+ * content belonging to the NEXT field (e.g. `SKILLS: none`) is never miscounted
131
+ * as ACCEPTANCE content — an empty `ACCEPTANCE:` immediately followed by another
132
+ * field is still correctly rejected as empty. Prompts are split on `\r?\n` so a
133
+ * trailing `\r` (CRLF-authored prompts) never leaks into the captured content.
134
+ *
135
+ * Only NON-EMPTINESS is enforced here; verbatim-coverage of the mapped FR/SC
136
+ * bodies is a SEPARATE, later check ({@link checkAcceptanceCoversFrRefs}) that
137
+ * already newline-normalizes the whole prompt, so multi-line ACCEPTANCE content
138
+ * is visible to it regardless.
139
+ *
140
+ * @param promptText the assembled delegation prompt (all text-bearing Task args
141
+ * joined).
142
+ * @returns `{ valid: true }` when the ACCEPTANCE field is present and non-empty;
143
+ * otherwise `{ valid: false, reason }` with a diagnosable reason the caller
144
+ * turns into a blocking, pre-dispatch error.
145
+ */
146
+ export declare function validateCoderReviewerAcceptanceField(promptText: string): {
147
+ valid: boolean;
148
+ reason?: 'acceptance_field_missing' | 'acceptance_field_empty';
149
+ };
150
+ /**
151
+ * FR-001/FR-002/FR-005/SC-001/SC-002/SC-006 (issue #1687): pull the verbatim
152
+ * requirement BODY for a single spec id (`FR-###` / `SC-###`) out of `spec.md`.
153
+ *
154
+ * spec.md requirements are bold-prefixed bullets, one per (possibly wrapped)
155
+ * bullet, e.g.
156
+ * `- **FR-000 — Structured task-to-FR mapping.** The plan task model SHALL ...`
157
+ * `- **SC-000 (FR-000).** Given a plan ..., then ...`
158
+ * The requirement BODY is the text AFTER the FIRST closing `**` of the leading
159
+ * bold span — i.e. everything past the `**...**` id/title prefix. Handles both
160
+ * FR-### and SC-### uniformly (no special-casing) and stitches on any
161
+ * immediately-following continuation lines of a wrapped bullet until the next
162
+ * bullet / next FR-|SC- bullet / a blank line / a markdown heading.
163
+ *
164
+ * @returns the raw (untrimmed) body string, or `null` when the id is not present
165
+ * in the spec (unknown/typo/renamed) — the caller treats null as fail-open skip.
166
+ */
167
+ export declare function extractSpecRequirementBodyById(specText: string, id: string): string | null;
168
+ /**
169
+ * FR-001/FR-002 (issue #1687): symmetric normalization applied identically to
170
+ * BOTH the extracted spec body AND the ACCEPTANCE prompt text before the
171
+ * substring-coverage compare. Asymmetric normalization would false-block, so this
172
+ * is deliberately the single shared normalizer. Strips markdown emphasis/code
173
+ * markers and leading list markers, folds punctuation the architect's LLM copy
174
+ * routinely substitutes (dash-width, curly-vs-straight quotes) so a good-faith
175
+ * verbatim copy is not false-blocked on a `—`→`--` or `'`→`'` swap, collapses
176
+ * ALL whitespace (incl. newlines) to single spaces, trims, and lowercases. Every
177
+ * fold is symmetric (both sides go through this one function), so it can only
178
+ * REDUCE false-blocks — it never opens a bypass, since covered/uncovered still
179
+ * differ by whole words, not punctuation.
180
+ */
181
+ export declare function normalizeAcceptanceText(s: string): string;
182
+ /**
183
+ * FR-001/FR-002/FR-005/SC-001/SC-002/SC-006 (issue #1687): mechanical coverage
184
+ * check that the ACCEPTANCE text CONTAINS the verbatim requirement body for each
185
+ * mapped spec id. Fail-open by construction:
186
+ * - an id not present in spec.md (unknown/typo/renamed) is SKIPPED, never blocked;
187
+ * - an id whose body normalizes to empty is SKIPPED (neither trivially covered
188
+ * nor a miss);
189
+ * - each id is checked INDEPENDENTLY (per-id substring), because the architect
190
+ * concatenates multiple requirement bodies with an UNSPECIFIED separator — a
191
+ * whole-string equality compare would false-block multi-FR tasks.
192
+ *
193
+ * @returns `{ covered: true }` when every id is present-and-covered or skipped;
194
+ * `{ covered: false, missingId }` naming the FIRST id whose body is not a
195
+ * substring of the ACCEPTANCE text.
196
+ */
197
+ export declare function checkAcceptanceCoversFrRefs(params: {
198
+ acceptanceText: string;
199
+ frRefs: string[];
200
+ specText: string;
201
+ }): {
202
+ covered: boolean;
203
+ missingId?: string;
204
+ };
90
205
  interface MessageInfo {
91
206
  role: string;
92
207
  agent?: string;