thoth-agents 0.3.9 → 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/dist/agents/prompt-dialects.d.ts +3 -0
- package/dist/{chunk-XEEYNMPC.js → chunk-JBG7XMIG.js} +1 -1
- package/dist/{chunk-2TLT6WWY.js → chunk-M2WF46BP.js} +39 -106
- package/dist/{chunk-MY2GIOOH.js → chunk-TKIDBRM3.js} +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/cli/tui/index.js +2 -2
- package/dist/harness/core/sdd.d.ts +1 -1
- package/dist/index.js +2 -2
- 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
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "thoth-agents",
|
|
11
11
|
"description": "Adaptive root orchestration, six specialist subagents, and a runtime-autonomous Spec Kit-compatible SDD bundle.",
|
|
12
|
-
"version": "0.3.
|
|
12
|
+
"version": "0.3.10",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "thoth-agents maintainers"
|
|
15
15
|
},
|
|
@@ -2,6 +2,9 @@ import type { AgentDispatchMethod, AgentRoleName } from '../harness/core/agent-p
|
|
|
2
2
|
import type { HarnessCapabilities, HarnessId } from '../harness/types';
|
|
3
3
|
export type AgentPromptRole = AgentRoleName;
|
|
4
4
|
export interface LifecycleNomenclature {
|
|
5
|
+
freshDelegation: string;
|
|
6
|
+
sameAssignmentContinuation: string;
|
|
7
|
+
independentContext: string;
|
|
5
8
|
statusAction: string;
|
|
6
9
|
terminalState: string;
|
|
7
10
|
nonterminalState: string;
|
|
@@ -802,6 +802,9 @@ var OPENCODE_PROMPT_DIALECT = {
|
|
|
802
802
|
progressTool: "todowrite",
|
|
803
803
|
hostStatusSurface: "task_status",
|
|
804
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",
|
|
805
808
|
statusAction: "wait, poll, and collect",
|
|
806
809
|
terminalState: "terminal task_status result",
|
|
807
810
|
nonterminalState: "nonterminal task_status result",
|
|
@@ -835,6 +838,9 @@ var CODEX_PROMPT_DIALECT = {
|
|
|
835
838
|
progressTool: "functions.update_plan",
|
|
836
839
|
hostStatusSurface: "collaboration.list_agents",
|
|
837
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',
|
|
838
844
|
statusAction: "wait and inspect status",
|
|
839
845
|
terminalState: "terminal mailbox completion or failure update",
|
|
840
846
|
nonterminalState: "collaboration.wait_agent timeout or silence",
|
|
@@ -875,6 +881,9 @@ var CLAUDE_CODE_PROMPT_DIALECT = {
|
|
|
875
881
|
progressTool: "TodoWrite",
|
|
876
882
|
hostStatusSurface: "TodoWrite",
|
|
877
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",
|
|
878
887
|
statusAction: "wait, inspect, and collect",
|
|
879
888
|
terminalState: "terminal TaskOutput result",
|
|
880
889
|
nonterminalState: "nonterminal TaskOutput result",
|
|
@@ -1013,6 +1022,10 @@ var ORCHESTRATION_POLICY = {
|
|
|
1013
1022
|
"Delegate only when specialization, context isolation, or independent parallel work creates a net gain.",
|
|
1014
1023
|
"Prefer child agents for read-heavy exploration, research, analysis, and verification.",
|
|
1015
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.",
|
|
1016
1029
|
"Child agents return distilled evidence instead of raw logs or file dumps."
|
|
1017
1030
|
]
|
|
1018
1031
|
};
|
|
@@ -1201,85 +1214,6 @@ var SDD_PHASES = [
|
|
|
1201
1214
|
reason: "Transactionally sync declared durable deltas and close verified work with a dated audit trail."
|
|
1202
1215
|
}
|
|
1203
1216
|
];
|
|
1204
|
-
var SDD_ARTIFACT_GRAPH = [
|
|
1205
|
-
{
|
|
1206
|
-
id: "spec",
|
|
1207
|
-
path: "spec.md",
|
|
1208
|
-
producedBy: "specify",
|
|
1209
|
-
consumes: [],
|
|
1210
|
-
requiredFor: ["accelerated", "full"]
|
|
1211
|
-
},
|
|
1212
|
-
{
|
|
1213
|
-
id: "plan",
|
|
1214
|
-
path: "plan.md",
|
|
1215
|
-
producedBy: "plan",
|
|
1216
|
-
consumes: ["spec"],
|
|
1217
|
-
requiredFor: ["accelerated", "full"]
|
|
1218
|
-
},
|
|
1219
|
-
{
|
|
1220
|
-
id: "tasks",
|
|
1221
|
-
path: "tasks.md",
|
|
1222
|
-
producedBy: "tasks",
|
|
1223
|
-
consumes: ["spec", "plan"],
|
|
1224
|
-
requiredFor: ["accelerated", "full"]
|
|
1225
|
-
},
|
|
1226
|
-
{
|
|
1227
|
-
id: "requirements-checklist",
|
|
1228
|
-
path: "checklists/requirements.md",
|
|
1229
|
-
producedBy: "checklist",
|
|
1230
|
-
consumes: ["spec"],
|
|
1231
|
-
requiredFor: []
|
|
1232
|
-
},
|
|
1233
|
-
{
|
|
1234
|
-
id: "research",
|
|
1235
|
-
path: "research.md",
|
|
1236
|
-
producedBy: "plan",
|
|
1237
|
-
consumes: ["spec"],
|
|
1238
|
-
requiredFor: []
|
|
1239
|
-
},
|
|
1240
|
-
{
|
|
1241
|
-
id: "data-model",
|
|
1242
|
-
path: "data-model.md",
|
|
1243
|
-
producedBy: "plan",
|
|
1244
|
-
consumes: ["spec"],
|
|
1245
|
-
requiredFor: []
|
|
1246
|
-
},
|
|
1247
|
-
{
|
|
1248
|
-
id: "contracts",
|
|
1249
|
-
path: "contracts/",
|
|
1250
|
-
producedBy: "plan",
|
|
1251
|
-
consumes: ["spec"],
|
|
1252
|
-
requiredFor: []
|
|
1253
|
-
},
|
|
1254
|
-
{
|
|
1255
|
-
id: "quickstart",
|
|
1256
|
-
path: "quickstart.md",
|
|
1257
|
-
producedBy: "plan",
|
|
1258
|
-
consumes: ["spec", "plan"],
|
|
1259
|
-
requiredFor: []
|
|
1260
|
-
},
|
|
1261
|
-
{
|
|
1262
|
-
id: "plan-review",
|
|
1263
|
-
path: "plan-review.md",
|
|
1264
|
-
producedBy: "plan-review",
|
|
1265
|
-
consumes: ["spec", "plan", "tasks"],
|
|
1266
|
-
requiredFor: []
|
|
1267
|
-
},
|
|
1268
|
-
{
|
|
1269
|
-
id: "verify-report",
|
|
1270
|
-
path: "verify-report.md",
|
|
1271
|
-
producedBy: "verify",
|
|
1272
|
-
consumes: ["spec", "plan", "tasks"],
|
|
1273
|
-
requiredFor: ["accelerated", "full"]
|
|
1274
|
-
},
|
|
1275
|
-
{
|
|
1276
|
-
id: "archive-report",
|
|
1277
|
-
path: "archive-report.md",
|
|
1278
|
-
producedBy: "archive",
|
|
1279
|
-
consumes: ["spec", "plan", "tasks", "verify-report"],
|
|
1280
|
-
requiredFor: ["accelerated", "full"]
|
|
1281
|
-
}
|
|
1282
|
-
];
|
|
1283
1217
|
var SDD_ROUTE_EXECUTION_POLICIES = [
|
|
1284
1218
|
{
|
|
1285
1219
|
route: "direct",
|
|
@@ -1372,13 +1306,6 @@ function getSddRouteExecutionPolicy(route) {
|
|
|
1372
1306
|
validationGates: [...policy.validationGates]
|
|
1373
1307
|
};
|
|
1374
1308
|
}
|
|
1375
|
-
function getSddArtifactGraph() {
|
|
1376
|
-
return SDD_ARTIFACT_GRAPH.map((artifact) => ({
|
|
1377
|
-
...artifact,
|
|
1378
|
-
consumes: [...artifact.consumes],
|
|
1379
|
-
requiredFor: [...artifact.requiredFor]
|
|
1380
|
-
}));
|
|
1381
|
-
}
|
|
1382
1309
|
function getSddPhase(id) {
|
|
1383
1310
|
const phase = SDD_PHASES.find((candidate) => candidate.id === id);
|
|
1384
1311
|
if (!phase) {
|
|
@@ -1486,9 +1413,6 @@ function renderSddRoute(route) {
|
|
|
1486
1413
|
function renderRoleDirectory() {
|
|
1487
1414
|
return getAgentPackContract().roles.filter((role) => role.name !== "orchestrator").map((role) => `- ${roleTemplate(role.name)}: ${role.responsibility}`).join("\n");
|
|
1488
1415
|
}
|
|
1489
|
-
function renderArtifactSummary() {
|
|
1490
|
-
return getSddArtifactGraph().filter((artifact) => artifact.requiredFor.length === 0).map((artifact) => artifact.path).join(", ");
|
|
1491
|
-
}
|
|
1492
1416
|
function createOrchestratorPromptSections() {
|
|
1493
1417
|
const workflow = getSddWorkflowContract();
|
|
1494
1418
|
const policy = getAgentPackContract().orchestrationPolicy;
|
|
@@ -1504,10 +1428,19 @@ You are the adaptive root for thoth-agents. Keep requirements, decisions, execut
|
|
|
1504
1428
|
- Delegate only for net gain from specialization, context isolation, review, or safe parallelism. The maximum delegation depth is ${policy.maxDelegationDepth}; children never delegate.
|
|
1505
1429
|
- Maintain one writer for each mutable surface. Parallelize only independent work with no overlapping writes.
|
|
1506
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.
|
|
1507
1432
|
- Use \`{{userQuestionTool}}\` only when a material unresolved choice changes the result. Continue all safe non-blocked work first.
|
|
1508
1433
|
- Use \`{{progressTool}}\` only when the work genuinely has multiple dependent steps.
|
|
1509
1434
|
</operating-model>
|
|
1510
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
|
+
|
|
1511
1444
|
<routing>
|
|
1512
1445
|
${renderRoleDirectory()}
|
|
1513
1446
|
</routing>
|
|
@@ -1541,29 +1474,20 @@ ${renderRoleDirectory()}
|
|
|
1541
1474
|
</external-skills>
|
|
1542
1475
|
|
|
1543
1476
|
<memory>
|
|
1544
|
-
- Load the installed \`thoth-mem\` skill for resume or prior work
|
|
1545
|
-
- 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
|
|
1546
|
-
- Follow the skill at verified compaction
|
|
1547
|
-
- \`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.
|
|
1548
1481
|
</memory>
|
|
1549
1482
|
|
|
1550
1483
|
<artifacts>
|
|
1551
|
-
-
|
|
1552
|
-
-
|
|
1553
|
-
-
|
|
1554
|
-
- ${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.
|
|
1555
1487
|
</artifacts>
|
|
1556
1488
|
|
|
1557
|
-
<execution>
|
|
1558
|
-
- Validate contracts and tests first; use test-first work for behavior. Root or one writer implements; do not delegate merely because an agent exists.
|
|
1559
|
-
- ${roleTemplate("oracle")} owns selected plan review and every verification; root and writers never self-approve.
|
|
1560
|
-
- Preserve unrelated working-tree changes. Never instruct an agent to discard them.
|
|
1561
|
-
- Report changed files, evidence, risks, and capability gaps truthfully.
|
|
1562
|
-
</execution>
|
|
1563
|
-
|
|
1564
1489
|
<delegation>
|
|
1565
|
-
-
|
|
1566
|
-
- 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.
|
|
1567
1491
|
- Child return fields: conclusion, evidence, verification, risks, openQuestions, nextAction.
|
|
1568
1492
|
|
|
1569
1493
|
${renderSddPhaseDispatchTemplate()}
|
|
@@ -1741,6 +1665,15 @@ function renderRoleText(section, dialect) {
|
|
|
1741
1665
|
).replaceAll("{{userQuestionTool}}", dialect.tools.userQuestionTool).replaceAll("{{progressTool}}", dialect.tools.progressTool).replaceAll(
|
|
1742
1666
|
"{{lifecycleStatusAction}}",
|
|
1743
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
|
|
1744
1677
|
).replaceAll(
|
|
1745
1678
|
"{{lifecycleTerminalState}}",
|
|
1746
1679
|
dialect.tools.lifecycle.terminalState
|
package/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getOpenCodeVersion,
|
|
5
5
|
isOpenCodeInstalled,
|
|
6
6
|
opencodeAdapter
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-TKIDBRM3.js";
|
|
8
8
|
import {
|
|
9
9
|
CODEX_ROLE_NAMES,
|
|
10
10
|
REQUIRED_SKILLS,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
listOperationHarnesses,
|
|
48
48
|
normalizeEffortSelection,
|
|
49
49
|
syncOpenCodeOwnedSkills
|
|
50
|
-
} from "../chunk-
|
|
50
|
+
} from "../chunk-JBG7XMIG.js";
|
|
51
51
|
import {
|
|
52
52
|
ALL_AGENT_NAMES,
|
|
53
53
|
detectCurrentConfig,
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
resolveExecutingPackageVersion,
|
|
59
59
|
updateOpenCodeMainConfig,
|
|
60
60
|
writeLiteConfig
|
|
61
|
-
} from "../chunk-
|
|
61
|
+
} from "../chunk-M2WF46BP.js";
|
|
62
62
|
|
|
63
63
|
// src/cli/index.ts
|
|
64
64
|
import { pathToFileURL } from "url";
|
package/dist/cli/tui/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
defaultTuiOperations,
|
|
3
3
|
effortChoicesForModel,
|
|
4
4
|
listOperationHarnesses
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-JBG7XMIG.js";
|
|
6
|
+
import "../../chunk-M2WF46BP.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/tui/index.tsx
|
|
9
9
|
import { render } from "ink";
|
|
@@ -311,7 +311,7 @@ export declare const SDD_PHASE_PROTOCOLS: readonly [{
|
|
|
311
311
|
readonly id: "specify";
|
|
312
312
|
readonly objective: "Create a testable, implementation-neutral feature contract in spec.md.";
|
|
313
313
|
readonly requiredInputs: ["User intent and accepted scope", "Explore handoff when the route is full", "Project constitution and existing public contracts when relevant"];
|
|
314
|
-
readonly instructions: ["Record intent and scope as Why, Impact, and Affected capabilities before prescribing any contract.", "Define prioritized independent stories and map each story to its FR-### and SC-### contracts with Covers metadata.", "Give every normative MUST or SHALL requirement a descriptive title and declare it INTERNAL or as an ADDED, MODIFIED, REMOVED, or RENAMED durable capability delta.", "Classify every success criterion as buildable or outcome; both remain measurable, but only buildable criteria require implementation task coverage.", "Capture assumptions, acceptance scenarios, edge cases, dependencies, and explicit non-goals.", "Use a clarification marker only when no safe default exists and the answer materially changes scope or behavior."];
|
|
314
|
+
readonly instructions: ["Record intent and scope as Why, Impact, and Affected capabilities before prescribing any contract.", "Define prioritized independent stories and map each story to its FR-### and SC-### contracts with Covers metadata.", "Inspect each affected canonical capability before choosing durable metadata: ADDED is only for genuinely new behavior; MODIFIED and REMOVED preserve exact existing titles; RENAMED names the exact previous title; only ADDED is valid when the capability is absent.", "Give every normative MUST or SHALL requirement a descriptive title and declare it INTERNAL or as an ADDED, MODIFIED, REMOVED, or RENAMED durable capability delta; treat an ADDED warning on an existing capability as a required semantic-overlap review.", "Classify every success criterion as buildable or outcome; both remain measurable, but only buildable criteria require implementation task coverage.", "Capture assumptions, acceptance scenarios, edge cases, dependencies, and explicit non-goals.", "Use a clarification marker only when no safe default exists and the answer materially changes scope or behavior."];
|
|
315
315
|
readonly allowedWrites: ["openspec/changes/<feature>/spec.md"];
|
|
316
316
|
readonly outputSchema: ["spec.md path", "requirements summary", "open clarifications"];
|
|
317
317
|
readonly doneWhen: ["Every accepted FR and SC is testable, materially unambiguous, mapped to a story, and implementation-neutral."];
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
renderOpenCodeAgentConfigs,
|
|
4
4
|
spawn,
|
|
5
5
|
spawnSync
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TKIDBRM3.js";
|
|
7
7
|
import {
|
|
8
8
|
POLL_INTERVAL_BACKGROUND_MS,
|
|
9
9
|
context7,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
grep_app,
|
|
13
13
|
loadPluginConfig,
|
|
14
14
|
stripJsonComments
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-M2WF46BP.js";
|
|
16
16
|
|
|
17
17
|
// src/index.ts
|
|
18
18
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thoth-agents",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"description": "Adaptive multi-harness orchestration with seven roles, runtime-autonomous Spec Kit-compatible SDD routes, and external provider boundaries.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
{
|
|
35
35
|
"path": "agents/orchestrator.md",
|
|
36
36
|
"kind": "agent-config",
|
|
37
|
-
"sha256": "sha256:
|
|
37
|
+
"sha256": "sha256:9a1a9de425e7499110e457b58481d953391d07841dc319f0f8c7b09d64fa8998"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"path": "agents/quick.md",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thoth-agents",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"description": "Bundled Spec Kit-compatible SDD skills and MCP configuration; the seven-role global Codex layer requires thoth-agents CLI setup.",
|
|
5
5
|
"skills": "./skills/",
|
|
6
6
|
"mcpServers": "./codex.mcp.json"
|
|
@@ -13,10 +13,19 @@ You are the adaptive root for thoth-agents. Keep requirements, decisions, execut
|
|
|
13
13
|
- Delegate only for net gain from specialization, context isolation, review, or safe parallelism. The maximum delegation depth is 1; children never delegate.
|
|
14
14
|
- Maintain one writer for each mutable surface. Parallelize only independent work with no overlapping writes.
|
|
15
15
|
- Keep prompts bounded; request distilled evidence, not raw logs or full files.
|
|
16
|
+
- Preserve unrelated changes; report changed files, evidence, risks, and capability gaps.
|
|
16
17
|
- Use `AskUserQuestion` only when a material unresolved choice changes the result. Continue all safe non-blocked work first.
|
|
17
18
|
- Use `TodoWrite` only when the work genuinely has multiple dependent steps.
|
|
18
19
|
</operating-model>
|
|
19
20
|
|
|
21
|
+
<delegation-lifecycle>
|
|
22
|
+
- A new objective, SDD phase, mutable surface, or independent judgment is a work boundary: start a fresh specialist using a normal `Agent` invocation. Never treat completed agents as a reusable role pool.
|
|
23
|
+
- Independent context: do not use `fork` for independent work.
|
|
24
|
+
- Continue with `SendMessage` to the prior agent ID only to steer, complete, or clarify the same bounded assignment; never to cross a work boundary.
|
|
25
|
+
- TaskOutput on the same task session only collects the active nonterminal assignment and does not authorize later reuse.
|
|
26
|
+
- 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.
|
|
27
|
+
</delegation-lifecycle>
|
|
28
|
+
|
|
20
29
|
<routing>
|
|
21
30
|
- thoth-agents:explorer: Resolve broad or uncertain repository questions and return distilled evidence.
|
|
22
31
|
- thoth-agents:librarian: Gather current authoritative evidence and separate documented facts from inference.
|
|
@@ -55,29 +64,20 @@ You are the adaptive root for thoth-agents. Keep requirements, decisions, execut
|
|
|
55
64
|
</external-skills>
|
|
56
65
|
|
|
57
66
|
<memory>
|
|
58
|
-
- Load the installed `thoth-mem` skill for resume or prior work
|
|
59
|
-
- 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
|
|
60
|
-
- Follow the skill at verified compaction
|
|
61
|
-
- `openspec/` remains canonical; do not mirror SDD phase artifacts
|
|
67
|
+
- Load the installed `thoth-mem` skill for resume or prior work; never invent its protocol.
|
|
68
|
+
- 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.
|
|
69
|
+
- Follow the skill at verified compaction or a meaningful semantic boundary; children receive only bounded MEMORY and never own root lifecycle.
|
|
70
|
+
- `openspec/` remains canonical; do not mirror SDD phase artifacts. A memory failure does not block unrelated work.
|
|
62
71
|
</memory>
|
|
63
72
|
|
|
64
73
|
<artifacts>
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
- thoth-agents: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>/.
|
|
74
|
+
- In openspec/changes/<feature>/, Accelerated and Full require spec.md, plan.md, tasks.md, verify-report.md, and archive-report.md.
|
|
75
|
+
- Root owns openspec/ gates and task state, moves [~] -> [x] after evidence, and keeps one product writer.
|
|
76
|
+
- thoth-agents:oracle returns read-only findings; root persists verification and archives declared durable deltas after PASS.
|
|
69
77
|
</artifacts>
|
|
70
78
|
|
|
71
|
-
<execution>
|
|
72
|
-
- Validate contracts and tests first; use test-first work for behavior. Root or one writer implements; do not delegate merely because an agent exists.
|
|
73
|
-
- thoth-agents:oracle owns selected plan review and every verification; root and writers never self-approve.
|
|
74
|
-
- Preserve unrelated working-tree changes. Never instruct an agent to discard them.
|
|
75
|
-
- Report changed files, evidence, risks, and capability gaps truthfully.
|
|
76
|
-
</execution>
|
|
77
|
-
|
|
78
79
|
<delegation>
|
|
79
|
-
-
|
|
80
|
-
- Parallelize only independent work and await requested results before synthesis.
|
|
80
|
+
- Use this envelope for all `Agent` delegation; parallelize only independent work and await results.
|
|
81
81
|
- Child return fields: conclusion, evidence, verification, risks, openQuestions, nextAction.
|
|
82
82
|
|
|
83
83
|
## PHASE
|
|
@@ -31,6 +31,13 @@ The script reads delta metadata directly from `spec.md`:
|
|
|
31
31
|
- `[RENAMED capability FROM Previous title]` renames and replaces it.
|
|
32
32
|
- `[INTERNAL]` never changes `openspec/specs/`.
|
|
33
33
|
|
|
34
|
+
The SDD validator preflights these operations against the canonical requirement
|
|
35
|
+
titles from `specify` onward. Archive reuses the same ordered parser and
|
|
36
|
+
preflight as a final defense before staging writes, preserving stable
|
|
37
|
+
`SDD-SPEC-DELTA-*` incompatibility codes. An `ADDED` warning for an existing
|
|
38
|
+
nonempty capability requires semantic-overlap review because differently named
|
|
39
|
+
requirements cannot be proven distinct by exact-title tooling alone.
|
|
40
|
+
|
|
34
41
|
All delta targets are validated before any permanent specification changes. The
|
|
35
42
|
operation stages and rolls back the full canonical update if a delta, report
|
|
36
43
|
update, or final move raises a handled error in the active process. Report and
|
|
@@ -10,8 +10,13 @@ import {
|
|
|
10
10
|
writeFileSync,
|
|
11
11
|
} from 'node:fs';
|
|
12
12
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
13
|
+
import {
|
|
14
|
+
CAPABILITY_PATTERN,
|
|
15
|
+
parseCanonicalSpec,
|
|
16
|
+
parseRequirementDelta as parseSharedRequirementDelta,
|
|
17
|
+
preflightRequirementDeltas,
|
|
18
|
+
} from '../../thoth-sdd/scripts/durable-deltas.mjs';
|
|
13
19
|
|
|
14
|
-
const CAPABILITY_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
15
20
|
const TEST_FAULTS = new Set(
|
|
16
21
|
(process.env.THOTH_ARCHIVE_TEST_FAULT ?? '')
|
|
17
22
|
.split(',')
|
|
@@ -270,26 +275,8 @@ function assertArchivable(change, contract) {
|
|
|
270
275
|
}
|
|
271
276
|
|
|
272
277
|
function parseDeltaMetadata(metadata) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const change = /^(ADDED|MODIFIED|REMOVED)\s+(\S+)$/.exec(metadata);
|
|
276
|
-
if (change && CAPABILITY_PATTERN.test(change[2])) {
|
|
277
|
-
return { operation: change[1], capability: change[2] };
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const rename = /^RENAMED\s+(\S+)\s+FROM\s+(.+)$/.exec(metadata);
|
|
281
|
-
if (
|
|
282
|
-
rename &&
|
|
283
|
-
CAPABILITY_PATTERN.test(rename[1]) &&
|
|
284
|
-
rename[2].trim().length > 0
|
|
285
|
-
) {
|
|
286
|
-
return {
|
|
287
|
-
operation: 'RENAMED',
|
|
288
|
-
capability: rename[1],
|
|
289
|
-
previousTitle: rename[2].trim(),
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
|
|
278
|
+
const delta = parseSharedRequirementDelta(metadata);
|
|
279
|
+
if (delta) return delta;
|
|
293
280
|
throw new Error(`Invalid requirement delta metadata: [${metadata}]`);
|
|
294
281
|
}
|
|
295
282
|
|
|
@@ -418,27 +405,6 @@ function parseChangeSpec(spec) {
|
|
|
418
405
|
};
|
|
419
406
|
}
|
|
420
407
|
|
|
421
|
-
function parseCanonicalSpec(content) {
|
|
422
|
-
const headings = [...content.matchAll(/^### Requirement:\s+(.+?)\s*$/gm)];
|
|
423
|
-
const requirements = new Map();
|
|
424
|
-
const prefix =
|
|
425
|
-
headings.length === 0
|
|
426
|
-
? content.trimEnd()
|
|
427
|
-
: content.slice(0, headings[0].index).trimEnd();
|
|
428
|
-
|
|
429
|
-
for (const [index, heading] of headings.entries()) {
|
|
430
|
-
const start = heading.index ?? 0;
|
|
431
|
-
const end = headings[index + 1]?.index ?? content.length;
|
|
432
|
-
const title = heading[1].trim();
|
|
433
|
-
if (requirements.has(title)) {
|
|
434
|
-
throw new Error(`Canonical specification repeats requirement: ${title}`);
|
|
435
|
-
}
|
|
436
|
-
requirements.set(title, content.slice(start, end).trim());
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
return { prefix, requirements };
|
|
440
|
-
}
|
|
441
|
-
|
|
442
408
|
function newCanonicalSpec(capability) {
|
|
443
409
|
const title = capability
|
|
444
410
|
.split('-')
|
|
@@ -480,41 +446,34 @@ function planCanonicalUpdates(specRoot, deltas) {
|
|
|
480
446
|
for (const [capability, capabilityDeltas] of byCapability) {
|
|
481
447
|
const path = join(specRoot, capability, 'spec.md');
|
|
482
448
|
const present = existsSync(path);
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
449
|
+
let canonical;
|
|
450
|
+
try {
|
|
451
|
+
canonical = present
|
|
452
|
+
? parseCanonicalSpec(readFileSync(path, 'utf8'))
|
|
453
|
+
: newCanonicalSpec(capability);
|
|
454
|
+
} catch (error) {
|
|
455
|
+
throw new Error(
|
|
456
|
+
`SDD-SPEC-DELTA-BASELINE: ${capability} canonical baseline is invalid: ${errorMessage(error)}`,
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
const preflight = preflightRequirementDeltas({
|
|
460
|
+
capability,
|
|
461
|
+
present,
|
|
462
|
+
requirements: canonical.requirements,
|
|
463
|
+
deltas: capabilityDeltas,
|
|
464
|
+
});
|
|
465
|
+
if (preflight.errors.length > 0) {
|
|
466
|
+
const [first] = preflight.errors;
|
|
467
|
+
throw new Error(`${first.code}: ${first.message}`);
|
|
468
|
+
}
|
|
486
469
|
|
|
487
470
|
for (const delta of capabilityDeltas) {
|
|
488
471
|
if (delta.operation === 'ADDED') {
|
|
489
|
-
if (canonical.requirements.has(delta.title)) {
|
|
490
|
-
throw new Error(
|
|
491
|
-
`${capability} already contains requirement: ${delta.title}`,
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
472
|
canonical.requirements.set(delta.title, renderRequirement(delta));
|
|
495
473
|
continue;
|
|
496
474
|
}
|
|
497
475
|
|
|
498
|
-
if (!present) {
|
|
499
|
-
throw new Error(
|
|
500
|
-
`${capability} has no canonical specification for ${delta.operation}`,
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
476
|
if (delta.operation === 'RENAMED') {
|
|
505
|
-
if (!canonical.requirements.has(delta.previousTitle)) {
|
|
506
|
-
throw new Error(
|
|
507
|
-
`${capability} does not contain requirement: ${delta.previousTitle}`,
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
if (
|
|
511
|
-
delta.previousTitle !== delta.title &&
|
|
512
|
-
canonical.requirements.has(delta.title)
|
|
513
|
-
) {
|
|
514
|
-
throw new Error(
|
|
515
|
-
`${capability} already contains requirement: ${delta.title}`,
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
477
|
const entries = [...canonical.requirements.entries()];
|
|
519
478
|
canonical.requirements = new Map(
|
|
520
479
|
entries.map(([title, block]) =>
|
|
@@ -526,11 +485,6 @@ function planCanonicalUpdates(specRoot, deltas) {
|
|
|
526
485
|
continue;
|
|
527
486
|
}
|
|
528
487
|
|
|
529
|
-
if (!canonical.requirements.has(delta.title)) {
|
|
530
|
-
throw new Error(
|
|
531
|
-
`${capability} does not contain requirement: ${delta.title}`,
|
|
532
|
-
);
|
|
533
|
-
}
|
|
534
488
|
if (delta.operation === 'MODIFIED') {
|
|
535
489
|
canonical.requirements.set(delta.title, renderRequirement(delta));
|
|
536
490
|
} else if (delta.operation === 'REMOVED') {
|
|
@@ -11,6 +11,16 @@ implementation-neutral.
|
|
|
11
11
|
`None`).
|
|
12
12
|
- Define prioritized, independently testable `US#` stories. Every story needs
|
|
13
13
|
`Covers: FR-###, SC-###` and Given/When/Then acceptance scenarios.
|
|
14
|
+
- Before choosing durable delta metadata, read
|
|
15
|
+
`openspec/specs/<capability>/spec.md` when it exists and compare the exact
|
|
16
|
+
`### Requirement:` titles and normative behavior:
|
|
17
|
+
- use `ADDED` only when no canonical requirement already expresses the
|
|
18
|
+
behavior;
|
|
19
|
+
- use `MODIFIED` or `REMOVED` only with the exact existing title;
|
|
20
|
+
- use `RENAMED <capability> FROM <exact previous title>` when the title changes;
|
|
21
|
+
- only `ADDED` is valid when the canonical capability does not exist.
|
|
22
|
+
A validator warning on `ADDED` into an existing nonempty capability requires
|
|
23
|
+
semantic-overlap review; exact-title validity alone does not prove new intent.
|
|
14
24
|
- Give every sequential FR a descriptive title, a normative `MUST`/`SHALL`
|
|
15
25
|
statement, and exactly one delta marker: `INTERNAL`, `ADDED`, `MODIFIED`,
|
|
16
26
|
`REMOVED`, or `RENAMED ... FROM ...`.
|
|
@@ -20,4 +30,5 @@ implementation-neutral.
|
|
|
20
30
|
- State assumptions, dependencies, edge cases, and explicit non-goals.
|
|
21
31
|
|
|
22
32
|
Do not advance while a material ambiguity would change scope, behavior,
|
|
23
|
-
architecture, or durable delta intent.
|
|
33
|
+
architecture, or durable delta intent. Run the `specify` gate before planning;
|
|
34
|
+
do not defer canonical delta reconciliation until archive.
|