thoth-agents 0.3.8 → 0.3.10

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 (41) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +27 -0
  3. package/dist/agents/prompt-dialects.d.ts +3 -0
  4. package/dist/{chunk-3WNTCPVK.js → chunk-JBG7XMIG.js} +1291 -290
  5. package/dist/{chunk-F2K4CS5J.js → chunk-M2WF46BP.js} +186 -128
  6. package/dist/{chunk-6GQYMWWT.js → chunk-TKIDBRM3.js} +1 -1
  7. package/dist/cli/commands.d.ts +1 -0
  8. package/dist/cli/config-io.d.ts +2 -1
  9. package/dist/cli/index.js +126 -428
  10. package/dist/cli/install-completion.d.ts +34 -0
  11. package/dist/cli/install-ledger.d.ts +44 -0
  12. package/dist/cli/install.d.ts +9 -1
  13. package/dist/cli/operations/claude-code.d.ts +12 -1
  14. package/dist/cli/operations/codex.d.ts +16 -0
  15. package/dist/cli/operations/opencode.d.ts +20 -3
  16. package/dist/cli/operations/types.d.ts +13 -0
  17. package/dist/cli/package-version.d.ts +19 -0
  18. package/dist/cli/tui/index.js +63 -24
  19. package/dist/harness/core/sdd.d.ts +1 -1
  20. package/dist/hooks/auto-update-checker/checker.d.ts +0 -5
  21. package/dist/hooks/auto-update-checker/index.d.ts +1 -2
  22. package/dist/hooks/auto-update-checker/types.d.ts +0 -1
  23. package/dist/index.js +98 -251
  24. package/package.json +1 -1
  25. package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +1 -1
  26. package/plugin/.claude-plugin/plugin.json +1 -1
  27. package/plugin/.codex-plugin/plugin.json +1 -1
  28. package/plugin/agents/orchestrator.md +17 -17
  29. package/plugin/skills/thoth-archive/SKILL.md +7 -0
  30. package/plugin/skills/thoth-archive/scripts/archive.mjs +28 -74
  31. package/plugin/skills/thoth-sdd/references/phases/specify.md +12 -1
  32. package/plugin/skills/thoth-sdd/scripts/durable-deltas.mjs +158 -0
  33. package/plugin/skills/thoth-sdd/scripts/validate.mjs +67 -28
  34. package/plugin/skills/thoth-sdd/templates/spec.md +9 -1
  35. package/skills/thoth-archive/SKILL.md +7 -0
  36. package/skills/thoth-archive/scripts/archive.mjs +28 -74
  37. package/skills/thoth-sdd/references/phases/specify.md +12 -1
  38. package/skills/thoth-sdd/scripts/durable-deltas.mjs +158 -0
  39. package/skills/thoth-sdd/scripts/validate.mjs +67 -28
  40. package/skills/thoth-sdd/templates/spec.md +9 -1
  41. package/dist/hooks/auto-update-checker/cache.d.ts +0 -7
@@ -5,20 +5,135 @@ import * as path from "path";
5
5
  // src/cli/config-io.ts
6
6
  import {
7
7
  copyFileSync,
8
- existsSync as existsSync2,
9
- readFileSync,
8
+ existsSync as existsSync3,
9
+ readFileSync as readFileSync2,
10
10
  renameSync,
11
11
  statSync,
12
12
  writeFileSync
13
13
  } from "fs";
14
14
 
15
+ // src/cli/package-version.ts
16
+ import { readFileSync } from "fs";
17
+ import { dirname as dirname2, join as join2 } from "path";
18
+ import { fileURLToPath } from "url";
19
+
20
+ // src/cli/package-root.ts
21
+ import { existsSync } from "fs";
22
+ import { dirname, join, parse } from "path";
23
+ function findPackageRoot(startDir) {
24
+ let currentDir = startDir;
25
+ const filesystemRoot = parse(startDir).root;
26
+ while (true) {
27
+ if (existsSync(join(currentDir, "package.json"))) {
28
+ return currentDir;
29
+ }
30
+ if (currentDir === filesystemRoot) {
31
+ return null;
32
+ }
33
+ const parentDir = dirname(currentDir);
34
+ if (parentDir === currentDir) {
35
+ return null;
36
+ }
37
+ currentDir = parentDir;
38
+ }
39
+ }
40
+
41
+ // src/cli/package-version.ts
42
+ var EXPECTED_PACKAGE_NAME = "thoth-agents";
43
+ var SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
44
+ function isValidPackageVersion(version) {
45
+ return typeof version === "string" && SEMVER_PATTERN.test(version);
46
+ }
47
+ function resolveExecutingPackageVersion(options = {}) {
48
+ const moduleUrl = options.moduleUrl ?? import.meta.url;
49
+ const packageRoot = findPackageRoot(dirname2(fileURLToPath(moduleUrl)));
50
+ if (!packageRoot) {
51
+ return {
52
+ ok: false,
53
+ error: {
54
+ code: "package-root-not-found",
55
+ message: "Could not locate the executing thoth-agents package root."
56
+ }
57
+ };
58
+ }
59
+ const packageJsonPath = join2(packageRoot, "package.json");
60
+ let serializedMetadata;
61
+ try {
62
+ serializedMetadata = readFileSync(packageJsonPath, "utf8");
63
+ } catch (error) {
64
+ return {
65
+ ok: false,
66
+ error: {
67
+ code: "package-metadata-unreadable",
68
+ message: `Could not read executing package metadata: ${error}`,
69
+ packageJsonPath
70
+ }
71
+ };
72
+ }
73
+ let metadata;
74
+ try {
75
+ metadata = JSON.parse(serializedMetadata);
76
+ } catch (error) {
77
+ return {
78
+ ok: false,
79
+ error: {
80
+ code: "package-metadata-malformed",
81
+ message: `Could not parse executing package metadata: ${error}`,
82
+ packageJsonPath
83
+ }
84
+ };
85
+ }
86
+ if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
87
+ return {
88
+ ok: false,
89
+ error: {
90
+ code: "package-metadata-malformed",
91
+ message: "Executing package metadata must be a JSON object.",
92
+ packageJsonPath
93
+ }
94
+ };
95
+ }
96
+ const { name, version } = metadata;
97
+ if (typeof name !== "string" || name.length === 0) {
98
+ return {
99
+ ok: false,
100
+ error: {
101
+ code: "package-metadata-malformed",
102
+ message: "Executing package metadata has no valid package name.",
103
+ packageJsonPath
104
+ }
105
+ };
106
+ }
107
+ if (name !== EXPECTED_PACKAGE_NAME) {
108
+ return {
109
+ ok: false,
110
+ error: {
111
+ code: "package-name-mismatch",
112
+ message: `Expected package ${EXPECTED_PACKAGE_NAME}, received ${name}.`,
113
+ packageJsonPath
114
+ }
115
+ };
116
+ }
117
+ if (!isValidPackageVersion(version)) {
118
+ return {
119
+ ok: false,
120
+ error: {
121
+ code: "package-version-invalid",
122
+ message: "Executing package metadata has no valid semantic version.",
123
+ packageJsonPath
124
+ }
125
+ };
126
+ }
127
+ return { ok: true, version, packageRoot };
128
+ }
129
+
15
130
  // src/cli/paths.ts
16
- import { existsSync, mkdirSync } from "fs";
131
+ import { existsSync as existsSync2, mkdirSync } from "fs";
17
132
  import { homedir } from "os";
18
- import { dirname, join } from "path";
133
+ import { dirname as dirname3, join as join3 } from "path";
19
134
  function getDefaultOpenCodeConfigDir() {
20
- const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config");
21
- return join(userConfigDir, "opencode");
135
+ const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join3(homedir(), ".config");
136
+ return join3(userConfigDir, "opencode");
22
137
  }
23
138
  function getCustomOpenCodeConfigDir() {
24
139
  const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
@@ -33,7 +148,7 @@ function getConfigDir() {
33
148
  }
34
149
  function getOpenCodeConfigPaths() {
35
150
  const configDir = getDefaultOpenCodeConfigDir();
36
- return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
151
+ return [join3(configDir, "opencode.json"), join3(configDir, "opencode.jsonc")];
37
152
  }
38
153
  function getConfigJson() {
39
154
  return getOpenCodeConfigPaths()[0];
@@ -42,37 +157,37 @@ function getConfigJsonc() {
42
157
  return getOpenCodeConfigPaths()[1];
43
158
  }
44
159
  function getLiteConfig() {
45
- return join(getConfigDir(), "thoth-agents.json");
160
+ return join3(getConfigDir(), "thoth-agents.json");
46
161
  }
47
162
  function getLiteConfigJsonc() {
48
- return join(getConfigDir(), "thoth-agents.jsonc");
163
+ return join3(getConfigDir(), "thoth-agents.jsonc");
49
164
  }
50
165
  function getOpenCodeManagedModelStatePath() {
51
- return join(getConfigDir(), ".thoth-agents-managed-models.json");
166
+ return join3(getConfigDir(), ".thoth-agents-managed-models.json");
52
167
  }
53
168
  function getExistingLiteConfigPath() {
54
169
  const jsonPath = getLiteConfig();
55
- if (existsSync(jsonPath)) return jsonPath;
170
+ if (existsSync2(jsonPath)) return jsonPath;
56
171
  const jsoncPath = getLiteConfigJsonc();
57
- if (existsSync(jsoncPath)) return jsoncPath;
172
+ if (existsSync2(jsoncPath)) return jsoncPath;
58
173
  return jsonPath;
59
174
  }
60
175
  function getExistingConfigPath() {
61
176
  const jsonPath = getConfigJson();
62
- if (existsSync(jsonPath)) return jsonPath;
177
+ if (existsSync2(jsonPath)) return jsonPath;
63
178
  const jsoncPath = getConfigJsonc();
64
- if (existsSync(jsoncPath)) return jsoncPath;
179
+ if (existsSync2(jsoncPath)) return jsoncPath;
65
180
  return jsonPath;
66
181
  }
67
182
  function ensureConfigDir() {
68
183
  const configDir = getConfigDir();
69
- if (!existsSync(configDir)) {
184
+ if (!existsSync2(configDir)) {
70
185
  mkdirSync(configDir, { recursive: true });
71
186
  }
72
187
  }
73
188
  function ensureOpenCodeConfigDir() {
74
- const configDir = dirname(getConfigJson());
75
- if (!existsSync(configDir)) {
189
+ const configDir = dirname3(getConfigJson());
190
+ if (!existsSync2(configDir)) {
76
191
  mkdirSync(configDir, { recursive: true });
77
192
  }
78
193
  }
@@ -349,10 +464,10 @@ function stripJsonComments(json) {
349
464
  }
350
465
  function parseConfigFile(path2) {
351
466
  try {
352
- if (!existsSync2(path2)) return { config: null };
467
+ if (!existsSync3(path2)) return { config: null };
353
468
  const stat = statSync(path2);
354
469
  if (stat.size === 0) return { config: null };
355
- const content = readFileSync(path2, "utf-8");
470
+ const content = readFileSync2(path2, "utf-8");
356
471
  if (content.trim().length === 0) return { config: null };
357
472
  return { config: JSON.parse(stripJsonComments(content)) };
358
473
  } catch (err) {
@@ -378,7 +493,7 @@ function writeConfig(configPath, config) {
378
493
  const bakPath = `${configPath}.bak`;
379
494
  const content = `${JSON.stringify(config, null, 2)}
380
495
  `;
381
- if (existsSync2(configPath)) {
496
+ if (existsSync3(configPath)) {
382
497
  copyFileSync(configPath, bakPath);
383
498
  }
384
499
  writeFileSync(tmpPath, content);
@@ -391,7 +506,7 @@ function mergeOpenCodeMainConfig(config, update) {
391
506
  ...plugins.filter(
392
507
  (plugin) => plugin !== PACKAGE_NAME && !plugin.startsWith(`${PACKAGE_NAME}@`)
393
508
  ),
394
- `${PACKAGE_NAME}@latest`
509
+ `${PACKAGE_NAME}@${update.pluginVersion}`
395
510
  ];
396
511
  }
397
512
  if (update.disableDefaults) {
@@ -406,6 +521,13 @@ function mergeOpenCodeMainConfig(config, update) {
406
521
  }
407
522
  function updateOpenCodeMainConfig(update) {
408
523
  const configPath = getExistingConfigPath();
524
+ if (update.ensurePlugin && !isValidPackageVersion(update.pluginVersion)) {
525
+ return {
526
+ success: false,
527
+ configPath,
528
+ error: "An approved plugin version is required."
529
+ };
530
+ }
409
531
  try {
410
532
  ensureOpenCodeConfigDir();
411
533
  } catch (err) {
@@ -446,7 +568,7 @@ function writeLiteConfig(installConfig, targetPath) {
446
568
  const bakPath = `${configPath}.bak`;
447
569
  const content = `${JSON.stringify(config, null, 2)}
448
570
  `;
449
- if (existsSync2(configPath)) {
571
+ if (existsSync3(configPath)) {
450
572
  copyFileSync(configPath, bakPath);
451
573
  }
452
574
  writeFileSync(tmpPath, content);
@@ -680,6 +802,9 @@ var OPENCODE_PROMPT_DIALECT = {
680
802
  progressTool: "todowrite",
681
803
  hostStatusSurface: "task_status",
682
804
  lifecycle: {
805
+ freshDelegation: "`task` without `task_id`",
806
+ sameAssignmentContinuation: "`task` with the prior `task_id`",
807
+ independentContext: "omitting `task_id` creates an isolated child session",
683
808
  statusAction: "wait, poll, and collect",
684
809
  terminalState: "terminal task_status result",
685
810
  nonterminalState: "nonterminal task_status result",
@@ -713,6 +838,9 @@ var CODEX_PROMPT_DIALECT = {
713
838
  progressTool: "functions.update_plan",
714
839
  hostStatusSurface: "collaboration.list_agents",
715
840
  lifecycle: {
841
+ freshDelegation: '`collaboration.spawn_agent` with `fork_turns="none"`',
842
+ sameAssignmentContinuation: "`collaboration.followup_task` for the existing agent",
843
+ independentContext: '`fork_turns="none"` prevents parent-history inheritance',
716
844
  statusAction: "wait and inspect status",
717
845
  terminalState: "terminal mailbox completion or failure update",
718
846
  nonterminalState: "collaboration.wait_agent timeout or silence",
@@ -753,6 +881,9 @@ var CLAUDE_CODE_PROMPT_DIALECT = {
753
881
  progressTool: "TodoWrite",
754
882
  hostStatusSurface: "TodoWrite",
755
883
  lifecycle: {
884
+ freshDelegation: "a normal `Agent` invocation",
885
+ sameAssignmentContinuation: "`SendMessage` to the prior agent ID",
886
+ independentContext: "do not use `fork` for independent work",
756
887
  statusAction: "wait, inspect, and collect",
757
888
  terminalState: "terminal TaskOutput result",
758
889
  nonterminalState: "nonterminal TaskOutput result",
@@ -891,6 +1022,10 @@ var ORCHESTRATION_POLICY = {
891
1022
  "Delegate only when specialization, context isolation, or independent parallel work creates a net gain.",
892
1023
  "Prefer child agents for read-heavy exploration, research, analysis, and verification.",
893
1024
  "Use one writer for each mutable surface and never parallelize overlapping writes.",
1025
+ "A fresh subagent instance is the default when the objective, SDD phase, mutable surface, or independent judgment changes.",
1026
+ "Continue an existing subagent only to steer, complete, or clarify the same bounded assignment; completed agents are not a reusable role pool.",
1027
+ "Every Oracle plan review, verification round, and approval or PASS judgment uses a fresh Oracle instance; reuse is limited to clarifying current findings.",
1028
+ "Wait and status operations collect only the active nonterminal assignment and do not authorize later reuse.",
894
1029
  "Child agents return distilled evidence instead of raw logs or file dumps."
895
1030
  ]
896
1031
  };
@@ -1079,85 +1214,6 @@ var SDD_PHASES = [
1079
1214
  reason: "Transactionally sync declared durable deltas and close verified work with a dated audit trail."
1080
1215
  }
1081
1216
  ];
1082
- var SDD_ARTIFACT_GRAPH = [
1083
- {
1084
- id: "spec",
1085
- path: "spec.md",
1086
- producedBy: "specify",
1087
- consumes: [],
1088
- requiredFor: ["accelerated", "full"]
1089
- },
1090
- {
1091
- id: "plan",
1092
- path: "plan.md",
1093
- producedBy: "plan",
1094
- consumes: ["spec"],
1095
- requiredFor: ["accelerated", "full"]
1096
- },
1097
- {
1098
- id: "tasks",
1099
- path: "tasks.md",
1100
- producedBy: "tasks",
1101
- consumes: ["spec", "plan"],
1102
- requiredFor: ["accelerated", "full"]
1103
- },
1104
- {
1105
- id: "requirements-checklist",
1106
- path: "checklists/requirements.md",
1107
- producedBy: "checklist",
1108
- consumes: ["spec"],
1109
- requiredFor: []
1110
- },
1111
- {
1112
- id: "research",
1113
- path: "research.md",
1114
- producedBy: "plan",
1115
- consumes: ["spec"],
1116
- requiredFor: []
1117
- },
1118
- {
1119
- id: "data-model",
1120
- path: "data-model.md",
1121
- producedBy: "plan",
1122
- consumes: ["spec"],
1123
- requiredFor: []
1124
- },
1125
- {
1126
- id: "contracts",
1127
- path: "contracts/",
1128
- producedBy: "plan",
1129
- consumes: ["spec"],
1130
- requiredFor: []
1131
- },
1132
- {
1133
- id: "quickstart",
1134
- path: "quickstart.md",
1135
- producedBy: "plan",
1136
- consumes: ["spec", "plan"],
1137
- requiredFor: []
1138
- },
1139
- {
1140
- id: "plan-review",
1141
- path: "plan-review.md",
1142
- producedBy: "plan-review",
1143
- consumes: ["spec", "plan", "tasks"],
1144
- requiredFor: []
1145
- },
1146
- {
1147
- id: "verify-report",
1148
- path: "verify-report.md",
1149
- producedBy: "verify",
1150
- consumes: ["spec", "plan", "tasks"],
1151
- requiredFor: ["accelerated", "full"]
1152
- },
1153
- {
1154
- id: "archive-report",
1155
- path: "archive-report.md",
1156
- producedBy: "archive",
1157
- consumes: ["spec", "plan", "tasks", "verify-report"],
1158
- requiredFor: ["accelerated", "full"]
1159
- }
1160
- ];
1161
1217
  var SDD_ROUTE_EXECUTION_POLICIES = [
1162
1218
  {
1163
1219
  route: "direct",
@@ -1250,13 +1306,6 @@ function getSddRouteExecutionPolicy(route) {
1250
1306
  validationGates: [...policy.validationGates]
1251
1307
  };
1252
1308
  }
1253
- function getSddArtifactGraph() {
1254
- return SDD_ARTIFACT_GRAPH.map((artifact) => ({
1255
- ...artifact,
1256
- consumes: [...artifact.consumes],
1257
- requiredFor: [...artifact.requiredFor]
1258
- }));
1259
- }
1260
1309
  function getSddPhase(id) {
1261
1310
  const phase = SDD_PHASES.find((candidate) => candidate.id === id);
1262
1311
  if (!phase) {
@@ -1364,9 +1413,6 @@ function renderSddRoute(route) {
1364
1413
  function renderRoleDirectory() {
1365
1414
  return getAgentPackContract().roles.filter((role) => role.name !== "orchestrator").map((role) => `- ${roleTemplate(role.name)}: ${role.responsibility}`).join("\n");
1366
1415
  }
1367
- function renderArtifactSummary() {
1368
- return getSddArtifactGraph().filter((artifact) => artifact.requiredFor.length === 0).map((artifact) => artifact.path).join(", ");
1369
- }
1370
1416
  function createOrchestratorPromptSections() {
1371
1417
  const workflow = getSddWorkflowContract();
1372
1418
  const policy = getAgentPackContract().orchestrationPolicy;
@@ -1382,10 +1428,19 @@ You are the adaptive root for thoth-agents. Keep requirements, decisions, execut
1382
1428
  - Delegate only for net gain from specialization, context isolation, review, or safe parallelism. The maximum delegation depth is ${policy.maxDelegationDepth}; children never delegate.
1383
1429
  - Maintain one writer for each mutable surface. Parallelize only independent work with no overlapping writes.
1384
1430
  - Keep prompts bounded; request distilled evidence, not raw logs or full files.
1431
+ - Preserve unrelated changes; report changed files, evidence, risks, and capability gaps.
1385
1432
  - Use \`{{userQuestionTool}}\` only when a material unresolved choice changes the result. Continue all safe non-blocked work first.
1386
1433
  - Use \`{{progressTool}}\` only when the work genuinely has multiple dependent steps.
1387
1434
  </operating-model>
1388
1435
 
1436
+ <delegation-lifecycle>
1437
+ - A new objective, SDD phase, mutable surface, or independent judgment is a work boundary: start a fresh specialist using {{lifecycleFreshDelegation}}. Never treat completed agents as a reusable role pool.
1438
+ - Independent context: {{lifecycleIndependentContext}}.
1439
+ - Continue with {{lifecycleSameAssignmentContinuation}} only to steer, complete, or clarify the same bounded assignment; never to cross a work boundary.
1440
+ - {{lifecycleSameSessionProbe}} only collects the active nonterminal assignment and does not authorize later reuse.
1441
+ - Every Oracle plan review, verification round, and approval or PASS judgment uses a fresh Oracle instance. An existing Oracle session may only clarify its current findings.
1442
+ </delegation-lifecycle>
1443
+
1389
1444
  <routing>
1390
1445
  ${renderRoleDirectory()}
1391
1446
  </routing>
@@ -1419,29 +1474,20 @@ ${renderRoleDirectory()}
1419
1474
  </external-skills>
1420
1475
 
1421
1476
  <memory>
1422
- - Load the installed \`thoth-mem\` skill for resume or prior work and provider-backed memory; never invent its protocol.
1423
- - Preserve a durable decision, root cause, convention, or discovery only when reusable. Root owns the stable root session ID, project, lifecycle, real-user intent, and authorization; never invent identity or confirmed effects.
1424
- - Follow the skill at verified compaction and a meaningful semantic boundary. Children receive only bounded MEMORY dispatch and never own root lifecycle.
1425
- - \`openspec/\` remains canonical; do not mirror SDD phase artifacts into provider memory. A memory failure degrades memory only and does not block unrelated implementation or verification.
1477
+ - Load the installed \`thoth-mem\` skill for resume or prior work; never invent its protocol.
1478
+ - Preserve a durable decision, root cause, convention, or discovery only when reusable. Root owns the stable root session ID, project, lifecycle, real-user intent, and authorization.
1479
+ - Follow the skill at verified compaction or a meaningful semantic boundary; children receive only bounded MEMORY and never own root lifecycle.
1480
+ - \`openspec/\` remains canonical; do not mirror SDD phase artifacts. A memory failure does not block unrelated work.
1426
1481
  </memory>
1427
1482
 
1428
1483
  <artifacts>
1429
- - Preserve Spec Kit semantics inside ${workflow.artifactRoot}.
1430
- - Accelerated and Full require spec.md, plan.md, tasks.md, verify-report.md, and archive-report.md; optional when useful: ${renderArtifactSummary()}.
1431
- - Root owns openspec/ coordination and thoth-sdd gates; product work has one writer, and root alone moves [~] -> [x] after evidence.
1432
- - ${roleTemplate("oracle")} returns read-only findings. Root persists verification; after PASS, archive syncs declared durable deltas and moves the change to openspec/changes/archive/YYYY-MM-DD-<feature>/.
1484
+ - In ${workflow.artifactRoot}, Accelerated and Full require spec.md, plan.md, tasks.md, verify-report.md, and archive-report.md.
1485
+ - Root owns openspec/ gates and task state, moves [~] -> [x] after evidence, and keeps one product writer.
1486
+ - ${roleTemplate("oracle")} returns read-only findings; root persists verification and archives declared durable deltas after PASS.
1433
1487
  </artifacts>
1434
1488
 
1435
- <execution>
1436
- - Validate contracts and tests first; use test-first work for behavior. Root or one writer implements; do not delegate merely because an agent exists.
1437
- - ${roleTemplate("oracle")} owns selected plan review and every verification; root and writers never self-approve.
1438
- - Preserve unrelated working-tree changes. Never instruct an agent to discard them.
1439
- - Report changed files, evidence, risks, and capability gaps truthfully.
1440
- </execution>
1441
-
1442
1489
  <delegation>
1443
- - Dispatch through \`{{delegationTool}}\` with this envelope; use the same boundaries for non-SDD work.
1444
- - Parallelize only independent work and await requested results before synthesis.
1490
+ - Use this envelope for all \`{{delegationTool}}\` delegation; parallelize only independent work and await results.
1445
1491
  - Child return fields: conclusion, evidence, verification, risks, openQuestions, nextAction.
1446
1492
 
1447
1493
  ${renderSddPhaseDispatchTemplate()}
@@ -1619,6 +1665,15 @@ function renderRoleText(section, dialect) {
1619
1665
  ).replaceAll("{{userQuestionTool}}", dialect.tools.userQuestionTool).replaceAll("{{progressTool}}", dialect.tools.progressTool).replaceAll(
1620
1666
  "{{lifecycleStatusAction}}",
1621
1667
  dialect.tools.lifecycle.statusAction
1668
+ ).replaceAll(
1669
+ "{{lifecycleFreshDelegation}}",
1670
+ dialect.tools.lifecycle.freshDelegation
1671
+ ).replaceAll(
1672
+ "{{lifecycleIndependentContext}}",
1673
+ dialect.tools.lifecycle.independentContext
1674
+ ).replaceAll(
1675
+ "{{lifecycleSameAssignmentContinuation}}",
1676
+ dialect.tools.lifecycle.sameAssignmentContinuation
1622
1677
  ).replaceAll(
1623
1678
  "{{lifecycleTerminalState}}",
1624
1679
  dialect.tools.lifecycle.terminalState
@@ -1748,6 +1803,9 @@ export {
1748
1803
  getDefaultOpenCodeModel,
1749
1804
  getDefaultOpenCodeVariant,
1750
1805
  POLL_INTERVAL_BACKGROUND_MS,
1806
+ findPackageRoot,
1807
+ isValidPackageVersion,
1808
+ resolveExecutingPackageVersion,
1751
1809
  getOpenCodeConfigPaths,
1752
1810
  getOpenCodeManagedModelStatePath,
1753
1811
  getExistingLiteConfigPath,
@@ -14,7 +14,7 @@ import {
14
14
  getStepBudgetPromptSection,
15
15
  loadAgentPrompt,
16
16
  renderRolePrompt
17
- } from "./chunk-F2K4CS5J.js";
17
+ } from "./chunk-M2WF46BP.js";
18
18
 
19
19
  // src/agents/deep.ts
20
20
  var DEEP_PROMPT = renderRolePrompt(
@@ -14,6 +14,7 @@ export interface CliModelCommandServices {
14
14
  operationContext(): OperationContext;
15
15
  modelRoles(harness: OperationHarnessArg): ModelRoleInput[];
16
16
  modelOptions(harness: OperationHarnessArg): Promise<ModelOption[]>;
17
+ applyOperationPlan?(plan: OperationPlan): OperationApplyResult;
17
18
  }
18
19
  export declare function printHarnessGeneration(args: GenerateArgs): number;
19
20
  export declare function runCliCommand(parsed: CliParseResult, modelServices?: CliModelCommandServices): Promise<number>;
@@ -15,9 +15,10 @@ export declare function parseConfig(path: string): {
15
15
  * Write config to file atomically.
16
16
  */
17
17
  export declare function writeConfig(configPath: string, config: OpenCodeConfig): void;
18
- export declare function addPluginToOpenCodeConfig(): Promise<ConfigMergeResult>;
18
+ export declare function addPluginToOpenCodeConfig(pluginVersion: string): Promise<ConfigMergeResult>;
19
19
  export interface OpenCodeMainConfigUpdate {
20
20
  ensurePlugin?: boolean;
21
+ pluginVersion?: string;
21
22
  disableDefaults?: boolean;
22
23
  }
23
24
  export declare function updateOpenCodeMainConfig(update: OpenCodeMainConfigUpdate): ConfigMergeResult;