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.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +27 -0
- package/dist/agents/prompt-dialects.d.ts +3 -0
- package/dist/{chunk-3WNTCPVK.js → chunk-JBG7XMIG.js} +1291 -290
- package/dist/{chunk-F2K4CS5J.js → chunk-M2WF46BP.js} +186 -128
- package/dist/{chunk-6GQYMWWT.js → chunk-TKIDBRM3.js} +1 -1
- package/dist/cli/commands.d.ts +1 -0
- package/dist/cli/config-io.d.ts +2 -1
- package/dist/cli/index.js +126 -428
- package/dist/cli/install-completion.d.ts +34 -0
- package/dist/cli/install-ledger.d.ts +44 -0
- package/dist/cli/install.d.ts +9 -1
- package/dist/cli/operations/claude-code.d.ts +12 -1
- package/dist/cli/operations/codex.d.ts +16 -0
- package/dist/cli/operations/opencode.d.ts +20 -3
- package/dist/cli/operations/types.d.ts +13 -0
- package/dist/cli/package-version.d.ts +19 -0
- package/dist/cli/tui/index.js +63 -24
- package/dist/harness/core/sdd.d.ts +1 -1
- package/dist/hooks/auto-update-checker/checker.d.ts +0 -5
- package/dist/hooks/auto-update-checker/index.d.ts +1 -2
- package/dist/hooks/auto-update-checker/types.d.ts +0 -1
- package/dist/index.js +98 -251
- package/package.json +1 -1
- package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/agents/orchestrator.md +17 -17
- package/plugin/skills/thoth-archive/SKILL.md +7 -0
- package/plugin/skills/thoth-archive/scripts/archive.mjs +28 -74
- package/plugin/skills/thoth-sdd/references/phases/specify.md +12 -1
- package/plugin/skills/thoth-sdd/scripts/durable-deltas.mjs +158 -0
- package/plugin/skills/thoth-sdd/scripts/validate.mjs +67 -28
- package/plugin/skills/thoth-sdd/templates/spec.md +9 -1
- package/skills/thoth-archive/SKILL.md +7 -0
- package/skills/thoth-archive/scripts/archive.mjs +28 -74
- package/skills/thoth-sdd/references/phases/specify.md +12 -1
- package/skills/thoth-sdd/scripts/durable-deltas.mjs +158 -0
- package/skills/thoth-sdd/scripts/validate.mjs +67 -28
- package/skills/thoth-sdd/templates/spec.md +9 -1
- 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
|
|
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 :
|
|
21
|
-
return
|
|
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 [
|
|
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
|
|
160
|
+
return join3(getConfigDir(), "thoth-agents.json");
|
|
46
161
|
}
|
|
47
162
|
function getLiteConfigJsonc() {
|
|
48
|
-
return
|
|
163
|
+
return join3(getConfigDir(), "thoth-agents.jsonc");
|
|
49
164
|
}
|
|
50
165
|
function getOpenCodeManagedModelStatePath() {
|
|
51
|
-
return
|
|
166
|
+
return join3(getConfigDir(), ".thoth-agents-managed-models.json");
|
|
52
167
|
}
|
|
53
168
|
function getExistingLiteConfigPath() {
|
|
54
169
|
const jsonPath = getLiteConfig();
|
|
55
|
-
if (
|
|
170
|
+
if (existsSync2(jsonPath)) return jsonPath;
|
|
56
171
|
const jsoncPath = getLiteConfigJsonc();
|
|
57
|
-
if (
|
|
172
|
+
if (existsSync2(jsoncPath)) return jsoncPath;
|
|
58
173
|
return jsonPath;
|
|
59
174
|
}
|
|
60
175
|
function getExistingConfigPath() {
|
|
61
176
|
const jsonPath = getConfigJson();
|
|
62
|
-
if (
|
|
177
|
+
if (existsSync2(jsonPath)) return jsonPath;
|
|
63
178
|
const jsoncPath = getConfigJsonc();
|
|
64
|
-
if (
|
|
179
|
+
if (existsSync2(jsoncPath)) return jsoncPath;
|
|
65
180
|
return jsonPath;
|
|
66
181
|
}
|
|
67
182
|
function ensureConfigDir() {
|
|
68
183
|
const configDir = getConfigDir();
|
|
69
|
-
if (!
|
|
184
|
+
if (!existsSync2(configDir)) {
|
|
70
185
|
mkdirSync(configDir, { recursive: true });
|
|
71
186
|
}
|
|
72
187
|
}
|
|
73
188
|
function ensureOpenCodeConfigDir() {
|
|
74
|
-
const configDir =
|
|
75
|
-
if (!
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
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}
|
|
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 (
|
|
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
|
|
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
|
|
1424
|
-
- Follow the skill at verified compaction
|
|
1425
|
-
- \`openspec/\` remains canonical; do not mirror SDD phase artifacts
|
|
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
|
-
-
|
|
1430
|
-
-
|
|
1431
|
-
-
|
|
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
|
-
-
|
|
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,
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -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>;
|
package/dist/cli/config-io.d.ts
CHANGED
|
@@ -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;
|