thoth-agents 0.4.2 → 0.5.0
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/LICENSE +30 -0
- package/README.md +86 -58
- package/dist/agents/prompt-sections.d.ts +5 -3
- package/dist/agents/prompt-utils.d.ts +1 -1
- package/dist/agents/worker.d.ts +2 -0
- package/dist/{chunk-STCURXAQ.js → chunk-MRFCA3U2.js} +33 -67
- package/dist/{chunk-EFGSGPYM.js → chunk-OW6I7ZUU.js} +391 -416
- package/dist/chunk-V7HSGRMB.js +1016 -0
- package/dist/{chunk-WCLUZZHI.js → chunk-VUNYH263.js} +1580 -351
- package/dist/cli/claude-code-paths.d.ts +2 -2
- package/dist/cli/codex-install.d.ts +5 -2
- package/dist/cli/codex-paths.d.ts +2 -2
- package/dist/cli/index.js +47 -11
- package/dist/cli/operations/pi.d.ts +1 -0
- package/dist/cli/pi-effort.d.ts +1 -1
- package/dist/cli/pi-external-package.d.ts +24 -0
- package/dist/cli/pi-git-source.d.ts +1 -0
- package/dist/cli/pi-install.d.ts +92 -15
- package/dist/cli/pi-managed-write.d.ts +3 -0
- package/dist/cli/pi-model-config.d.ts +17 -0
- package/dist/cli/pi-native-probe.d.ts +2 -0
- package/dist/cli/pi-paths.d.ts +2 -0
- package/dist/cli/pi-resources.d.ts +3 -1
- package/dist/cli/pi-tool-config.d.ts +32 -0
- package/dist/cli/tui/index.js +3 -3
- package/dist/cli/types.d.ts +2 -0
- package/dist/config/constants.d.ts +4 -8
- package/dist/config/schema.d.ts +7 -36
- package/dist/harness/adapters/claude-code.d.ts +2 -4
- package/dist/harness/core/agent-pack.d.ts +52 -42
- package/dist/harness/core/memory-governance.d.ts +2 -2
- package/dist/harness/core/sdd.d.ts +159 -319
- package/dist/harness/writers/pi-agent.d.ts +3 -1
- package/dist/index.js +12 -6
- package/dist/pi/tools-panel.d.ts +51 -0
- package/dist/pi.d.ts +44 -2
- package/dist/pi.js +471 -9
- package/dist/utils/subprocess.d.ts +1 -0
- package/package.json +18 -4
- package/pi/.thoth-agents-assets.json +5 -6
- package/pi/agents/thoth-designer.md +23 -8
- package/pi/agents/thoth-explorer.md +29 -9
- package/pi/agents/thoth-librarian.md +30 -8
- package/pi/agents/thoth-oracle.md +18 -10
- package/pi/agents/thoth-worker.md +96 -0
- package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +7 -12
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/agents/designer.md +13 -5
- package/plugin/agents/explorer.md +16 -5
- package/plugin/agents/librarian.md +15 -4
- package/plugin/agents/oracle.md +13 -7
- package/plugin/agents/orchestrator.md +82 -91
- package/plugin/agents/worker.md +76 -0
- package/plugin/skills/plan-reviewer/SKILL.md +39 -141
- package/plugin/skills/thoth-archive/SKILL.md +50 -47
- package/plugin/skills/thoth-archive/scripts/archive.mjs +287 -654
- package/plugin/skills/thoth-constitution/SKILL.md +23 -42
- package/plugin/skills/thoth-constitution/templates/constitution.md +54 -44
- package/plugin/skills/thoth-init/SKILL.md +19 -29
- package/plugin/skills/thoth-init/scripts/init.mjs +73 -66
- package/plugin/skills/thoth-sdd/SKILL.md +164 -117
- package/plugin/skills/thoth-sdd/references/phases/checklist.md +2 -22
- package/plugin/skills/thoth-sdd/references/phases/clarify.md +14 -12
- package/plugin/skills/thoth-sdd/references/phases/converge.md +2 -13
- package/plugin/skills/thoth-sdd/references/phases/explore.md +3 -8
- package/plugin/skills/thoth-sdd/references/phases/implement.md +58 -57
- package/plugin/skills/thoth-sdd/references/phases/plan.md +2 -18
- package/plugin/skills/thoth-sdd/references/phases/specify.md +2 -33
- package/plugin/skills/thoth-sdd/references/phases/tasks.md +4 -45
- package/plugin/skills/thoth-sdd/references/phases/verify.md +4 -22
- package/plugin/skills/thoth-sdd/scripts/validate.mjs +610 -1232
- package/plugin/skills/thoth-sdd/templates/change.md +94 -0
- package/skills/README.md +11 -13
- package/skills/plan-reviewer/SKILL.md +39 -141
- package/skills/thoth-archive/SKILL.md +50 -47
- package/skills/thoth-archive/scripts/archive.mjs +287 -654
- package/skills/thoth-constitution/SKILL.md +23 -42
- package/skills/thoth-constitution/templates/constitution.md +54 -44
- package/skills/thoth-init/SKILL.md +19 -29
- package/skills/thoth-init/scripts/init.mjs +73 -66
- package/skills/thoth-sdd/SKILL.md +164 -117
- package/skills/thoth-sdd/references/phases/checklist.md +2 -22
- package/skills/thoth-sdd/references/phases/clarify.md +14 -12
- package/skills/thoth-sdd/references/phases/converge.md +2 -13
- package/skills/thoth-sdd/references/phases/explore.md +3 -8
- package/skills/thoth-sdd/references/phases/implement.md +58 -57
- package/skills/thoth-sdd/references/phases/plan.md +2 -18
- package/skills/thoth-sdd/references/phases/specify.md +2 -33
- package/skills/thoth-sdd/references/phases/tasks.md +4 -45
- package/skills/thoth-sdd/references/phases/verify.md +4 -22
- package/skills/thoth-sdd/scripts/validate.mjs +610 -1232
- package/skills/thoth-sdd/templates/change.md +94 -0
- package/thoth-agents.schema.json +9 -77
- package/dist/agents/deep.d.ts +0 -2
- package/dist/agents/quick.d.ts +0 -2
- package/dist/chunk-2U5MBLLV.js +0 -312
- package/pi/agents/thoth-deep.md +0 -81
- package/pi/agents/thoth-quick.md +0 -81
- package/plugin/agents/deep.md +0 -68
- package/plugin/agents/quick.md +0 -68
- package/plugin/skills/plan-reviewer/templates/plan-review.md +0 -65
- package/plugin/skills/thoth-sdd/templates/archive-report.md +0 -25
- package/plugin/skills/thoth-sdd/templates/checklist.md +0 -27
- package/plugin/skills/thoth-sdd/templates/plan.md +0 -46
- package/plugin/skills/thoth-sdd/templates/spec.md +0 -62
- package/plugin/skills/thoth-sdd/templates/tasks.md +0 -58
- package/plugin/skills/thoth-sdd/templates/verify-report.md +0 -28
- package/skills/plan-reviewer/templates/plan-review.md +0 -65
- package/skills/thoth-sdd/templates/archive-report.md +0 -25
- package/skills/thoth-sdd/templates/checklist.md +0 -27
- package/skills/thoth-sdd/templates/plan.md +0 -46
- package/skills/thoth-sdd/templates/spec.md +0 -62
- package/skills/thoth-sdd/templates/tasks.md +0 -58
- package/skills/thoth-sdd/templates/verify-report.md +0 -28
|
@@ -1,53 +1,34 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: thoth-constitution
|
|
3
|
-
description: Create or explicitly amend the
|
|
3
|
+
description: Create or explicitly amend the active .thoth constitution with SemVer and sync-impact lifecycle validation.
|
|
4
4
|
license: MIT
|
|
5
|
-
compatibility: Requires Node.js >=22.19 for bundled validation
|
|
5
|
+
compatibility: Requires Node.js >=22.19 for bundled validation.
|
|
6
6
|
metadata:
|
|
7
7
|
author: thoth-agents
|
|
8
|
-
version: "
|
|
8
|
+
version: "2.0"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Thoth Constitution
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
1. Read the current constitution and every affected template, instruction, and
|
|
32
|
-
durable workflow document.
|
|
33
|
-
2. Classify the governance version bump:
|
|
34
|
-
- **MAJOR** removes or redefines a principle or compatibility boundary.
|
|
35
|
-
- **MINOR** adds a principle/section or materially expands guidance.
|
|
36
|
-
- **PATCH** clarifies wording without semantic change.
|
|
37
|
-
3. Preserve the original ratification date, set `Last amended` to today, and
|
|
38
|
-
update `Version` using complete `MAJOR.MINOR.PATCH` SemVer.
|
|
39
|
-
4. Prepend or refresh the HTML-comment `Sync Impact Report`: old → new version,
|
|
40
|
-
modified principles, added/removed sections, affected templates with status,
|
|
41
|
-
and follow-up TODOs.
|
|
42
|
-
5. Propagate the accepted rule to every affected template, instruction, and
|
|
43
|
-
documentation surface in the same change.
|
|
44
|
-
6. Remove unexplained placeholders and deferred TODOs, then run:
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
node "<skill-dir>/scripts/validate.mjs" \
|
|
48
|
-
--constitution openspec/memory/constitution.md --json
|
|
13
|
+
Canonical active governance is `.thoth/constitution.md`; substantial change
|
|
14
|
+
records and durable specifications live under `.thoth/`. Historical changes are
|
|
15
|
+
preserved and are not an active workflow dependency. Routine SDD reads relevant
|
|
16
|
+
principles but does not amend constitution metadata.
|
|
17
|
+
|
|
18
|
+
Only explicit user direction or an accepted material governance change activates
|
|
19
|
+
amendment. Preserve original ratification, set last-amended to the amendment
|
|
20
|
+
date, choose MAJOR for redefinition/removal, MINOR for addition/material
|
|
21
|
+
expansion, PATCH for clarification, and refresh the Sync Impact Report (old/new
|
|
22
|
+
version, modified principles, added/removed sections, affected templates,
|
|
23
|
+
follow-up). This requirement for explicit activation is not replaced by a
|
|
24
|
+
defaulted choice. Any orchestrator choice presented during amendment follows the
|
|
25
|
+
shared per-question recommendation policy; a safe deferral keeps unresolved
|
|
26
|
+
human-owned intent open, and missing facts or secrets are never invented.
|
|
27
|
+
Propagate changes to affected instruction and template surfaces, then run:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
node "<skill-dir>/scripts/validate.mjs" --constitution .thoth/constitution.md --json
|
|
49
31
|
```
|
|
50
32
|
|
|
51
|
-
Initialization copies
|
|
52
|
-
|
|
53
|
-
overwrites a project-owned constitution.
|
|
33
|
+
Initialization copies the bundled template only when the constitution is absent,
|
|
34
|
+
replaces date placeholders, and never overwrites project-owned governance.
|
|
@@ -15,57 +15,67 @@ Sync Impact Report
|
|
|
15
15
|
|
|
16
16
|
## Principles
|
|
17
17
|
|
|
18
|
-
### I.
|
|
18
|
+
### I. Native authority and human choice
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
The active harness owns dispatch, status, wait, cancellation, and terminal
|
|
21
|
+
results. Workflow guidance MUST NOT build a scheduler, state mirror, or process
|
|
22
|
+
tools. Every change completes proportional explore, specify, and clarify
|
|
23
|
+
reasoning before the orchestrator classifies by meaningful coordination and
|
|
24
|
+
contract impact, uncertainty, and risk. File count alone does not increase scope:
|
|
25
|
+
a clear, low-risk localized mechanical change may touch several files and remain
|
|
26
|
+
small. Material product, architecture, security, and destructive decisions
|
|
27
|
+
remain human-owned; unresolved material intent blocks classification and
|
|
28
|
+
implementation. Whenever an orchestrator presents a choice with a meaningful
|
|
29
|
+
recommended action, it states that recommendation. For each choice separately,
|
|
30
|
+
repeat the same question after the first and second confirmed answerless native
|
|
31
|
+
returns without taking dependent action; after the third, select the
|
|
32
|
+
recommendation. Explicit answers and `Stop` win. Pending, unavailable, failed,
|
|
33
|
+
interrupted, or host-prohibited attempts do not count; report higher-priority
|
|
34
|
+
host limits accurately. Never fabricate facts or secrets. A safe deferral may be
|
|
35
|
+
the recommendation for unresolved human-owned intent and leaves it unresolved.
|
|
22
36
|
|
|
23
|
-
### II.
|
|
37
|
+
### II. Minimal recoverable SDD
|
|
24
38
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
Small, clear, low-risk work uses test-first implementation and focused
|
|
40
|
+
verification without a persistent record. Substantial work uses one compact
|
|
41
|
+
`.thoth/changes/<id>/<id>.md` record for grounded exploration, intent, acceptance,
|
|
42
|
+
clarifications, decisions, plan, tasks, authorization, and verification. A
|
|
43
|
+
patch-sized change can still require planning when coordination impact,
|
|
44
|
+
uncertainty, or risk warrants it. Increased scope or risk reopens understanding
|
|
45
|
+
and classification. Avoid mandatory sidecar reports, evidence directories,
|
|
46
|
+
worker packets, or generated process tools. Historical changes remain untouched.
|
|
47
|
+
Provider memory is independent of project records.
|
|
32
48
|
|
|
33
|
-
### III.
|
|
49
|
+
### III. Bounded ownership and verification
|
|
34
50
|
|
|
35
|
-
|
|
36
|
-
|
|
51
|
+
Delegation depth is one and each mutable surface has one writer. Root accepts
|
|
52
|
+
terminal dependency results before releasing consumers. At substantial `ready`,
|
|
53
|
+
root always offers Oracle plan review (Recommended) or proceeding without review,
|
|
54
|
+
even if implementation was authorized; an unanswered offer never means skip.
|
|
55
|
+
After `[OKAY]`, root separately offers the Implement (Recommended) / Stop choice,
|
|
56
|
+
honors prior explicit authorization, and lets explicit Stop supersede it. Record
|
|
57
|
+
selection provenance as `EXPLICIT_REVIEW`, `EXPLICIT_SKIP`, or
|
|
58
|
+
`DEFAULT_REVIEW_AFTER_3`; only `EXPLICIT_SKIP` permits `SKIPPED`, and `OKAY`
|
|
59
|
+
requires explicit review or the third-return recommendation. A plan review is not
|
|
60
|
+
implementation authorization or final verification. Every change is verified;
|
|
61
|
+
substantial or materially risky work needs a fresh independent Oracle judgment,
|
|
62
|
+
and no implementation writer approves their own work. Archive only after
|
|
63
|
+
complete acceptance evidence and verification still match the actual record and
|
|
64
|
+
sources.
|
|
37
65
|
|
|
38
|
-
### IV.
|
|
66
|
+
### IV. Durable governance
|
|
39
67
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
reviewer. Pre-implementation plan review is optional and is selected explicitly
|
|
46
|
-
or by the bounded recommended fallback; when offered, any explicit answer wins.
|
|
47
|
-
After the third answerless result,
|
|
48
|
-
`Review plan with Oracle (Recommended)` counts as selected. Actionable review
|
|
49
|
-
rejections MUST be repaired and revalidated before a fresh reviewer round until
|
|
50
|
-
approval or a material human-owned blocker. After approval, Root MUST give an
|
|
51
|
-
approved plan summary before asking `Implement (Recommended)` or `Stop`; any
|
|
52
|
-
explicit answer wins, while the third answerless result selects implementation.
|
|
53
|
-
Plan review never substitutes for final verification.
|
|
54
|
-
|
|
55
|
-
### V. Traceable delivery
|
|
56
|
-
|
|
57
|
-
Specifications, plans, tasks, implementation evidence, verification verdicts,
|
|
58
|
-
and archive reports MUST remain traceable without relying on chat history.
|
|
68
|
+
Declare ADDED, MODIFIED, REMOVED, or RENAMED requirement deltas by capability and
|
|
69
|
+
exact title against `.thoth/specs/`. Apply only reviewed deltas at transactional
|
|
70
|
+
archive; preserve unaffected canonical requirements and historical changes.
|
|
71
|
+
Recovery inspects retained transactions before retry and never blindly replays
|
|
72
|
+
external effects.
|
|
59
73
|
|
|
60
74
|
## Governance
|
|
61
75
|
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
and propagation to affected templates, instructions, and documentation.
|
|
69
|
-
- MAJOR versions remove or redefine governance compatibility.
|
|
70
|
-
- MINOR versions add a principle or materially expand guidance.
|
|
71
|
-
- PATCH versions clarify wording without changing its meaning.
|
|
76
|
+
- Amendments require explicit user direction, a refreshed Sync Impact Report,
|
|
77
|
+
and propagation to affected templates and instructions.
|
|
78
|
+
- Routine work reads relevant active principles; it does not amend lifecycle metadata.
|
|
79
|
+
- MAJOR versions remove or redefine a principle or compatibility boundary.
|
|
80
|
+
- MINOR versions add principles or materially expand guidance.
|
|
81
|
+
- PATCH versions clarify wording without changing semantic behavior.
|
|
@@ -1,43 +1,33 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: thoth-init
|
|
3
|
-
description: Initialize
|
|
3
|
+
description: Initialize canonical offline .thoth governance without modifying existing project records.
|
|
4
4
|
license: MIT
|
|
5
|
-
compatibility: Requires Node.js >=22.19 and write access to
|
|
5
|
+
compatibility: Requires Node.js >=22.19 and write access to target project.
|
|
6
6
|
metadata:
|
|
7
7
|
author: thoth-agents
|
|
8
|
-
version: "
|
|
8
|
+
version: "2.0"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Thoth Init
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
installed skill bundle. Resolve `<skill-dir>` as the directory containing this
|
|
15
|
-
`SKILL.md`, then run the bundled script by absolute path:
|
|
13
|
+
Run the installed script by absolute skill-root path:
|
|
16
14
|
|
|
17
15
|
```text
|
|
18
16
|
node "<skill-dir>/scripts/init.mjs" --project <project-root> --json
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
The initializer never creates, copies, validates, reads, or synchronizes SDD
|
|
37
|
-
workflow templates. Those assets remain in the installed `thoth-sdd` skill and
|
|
38
|
-
are consumed directly from that bundle by the workflow phase contracts.
|
|
39
|
-
|
|
40
|
-
This operation is offline, idempotent, and harness-neutral. Every write stays
|
|
41
|
-
inside `openspec/`. It never installs or synchronizes skills, agents, plugins,
|
|
42
|
-
harness configuration, external dependencies, or global instruction files;
|
|
43
|
-
those are responsibilities of `npx thoth-agents install`.
|
|
19
|
+
For a new project, initialize `.thoth/changes/archive/`, `.thoth/specs/`, and
|
|
20
|
+
`.thoth/constitution.md`. A missing constitution comes from the sibling
|
|
21
|
+
thoth-constitution template with date placeholders filled. Preserve an existing
|
|
22
|
+
constitution and all existing `.thoth` change/spec history byte-for-byte; never
|
|
23
|
+
auto-migrate or overwrite project governance. Refuse symlinked ancestors,
|
|
24
|
+
unknown path collisions, or an active legacy OpenSpec tree rather than creating a
|
|
25
|
+
duplicate active store. Migration is an explicit project change, not an init side
|
|
26
|
+
effect.
|
|
27
|
+
|
|
28
|
+
The operation is offline and idempotent. It creates no manifests, change records,
|
|
29
|
+
workflow templates, OpenSpec tree, process tools, or mirrored state. Return JSON
|
|
30
|
+
`created` and `preserved` paths. No installer or network access is involved.
|
|
31
|
+
This skill presents no interactive choices and does not infer missing target
|
|
32
|
+
facts. Any orchestrator choice around initialization follows the shared SDD
|
|
33
|
+
recommendation and per-question retry policy.
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
existsSync,
|
|
5
|
-
lstatSync,
|
|
6
|
-
mkdirSync,
|
|
7
|
-
readFileSync,
|
|
8
|
-
writeFileSync,
|
|
9
|
-
} from 'node:fs';
|
|
10
|
-
import { dirname, join, resolve } from 'node:path';
|
|
2
|
+
import { lstatSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, parse, resolve, sep } from 'node:path';
|
|
11
4
|
import { fileURLToPath } from 'node:url';
|
|
12
5
|
|
|
13
6
|
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|
|
14
7
|
const SKILL_ROOT = dirname(dirname(SCRIPT_PATH));
|
|
15
8
|
const BUNDLE_ROOT = dirname(SKILL_ROOT);
|
|
16
|
-
const
|
|
17
|
-
'
|
|
9
|
+
const THOTH_DIRECTORIES = [
|
|
10
|
+
'.thoth',
|
|
11
|
+
join('.thoth', 'changes'),
|
|
12
|
+
join('.thoth', 'changes', 'archive'),
|
|
13
|
+
join('.thoth', 'specs'),
|
|
14
|
+
];
|
|
15
|
+
const LEGACY_ACTIVE_PATHS = [
|
|
18
16
|
join('openspec', 'changes'),
|
|
19
|
-
join('openspec', 'changes', 'archive'),
|
|
20
17
|
join('openspec', 'specs'),
|
|
21
|
-
join('openspec', 'memory'),
|
|
18
|
+
join('openspec', 'memory', 'constitution.md'),
|
|
22
19
|
];
|
|
23
20
|
|
|
24
21
|
function parseArgs(argv) {
|
|
@@ -33,25 +30,65 @@ function parseArgs(argv) {
|
|
|
33
30
|
return options;
|
|
34
31
|
}
|
|
35
32
|
|
|
33
|
+
function lstatMaybe(path) {
|
|
34
|
+
try {
|
|
35
|
+
return lstatSync(path);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error.code === 'ENOENT' || error.code === 'ENOTDIR') return undefined;
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function assertNoSymlinkAncestors(path, label) {
|
|
43
|
+
const absolute = resolve(path);
|
|
44
|
+
const { root } = parse(absolute);
|
|
45
|
+
let cursor = root;
|
|
46
|
+
for (const part of absolute.slice(root.length).split(sep).filter(Boolean)) {
|
|
47
|
+
cursor = join(cursor, part);
|
|
48
|
+
if (lstatMaybe(cursor)?.isSymbolicLink()) {
|
|
49
|
+
throw new Error(`${label} has a symlinked ancestor: ${cursor}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
36
54
|
function assertDirectory(path, label) {
|
|
37
|
-
|
|
38
|
-
const stat =
|
|
39
|
-
if (stat.
|
|
55
|
+
assertNoSymlinkAncestors(path, label);
|
|
56
|
+
const stat = lstatMaybe(path);
|
|
57
|
+
if (stat && (!stat.isDirectory() || stat.isSymbolicLink())) {
|
|
40
58
|
throw new Error(`${label} must be a directory: ${path}`);
|
|
41
59
|
}
|
|
42
60
|
}
|
|
43
61
|
|
|
44
62
|
function assertRegularFile(path, label) {
|
|
45
|
-
|
|
46
|
-
const stat =
|
|
47
|
-
if (stat.
|
|
63
|
+
assertNoSymlinkAncestors(path, label);
|
|
64
|
+
const stat = lstatMaybe(path);
|
|
65
|
+
if (stat && (!stat.isFile() || stat.isSymbolicLink())) {
|
|
48
66
|
throw new Error(`${label} must be a regular file: ${path}`);
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
69
|
|
|
70
|
+
function assertNoLegacyActiveStore(project) {
|
|
71
|
+
const openspec = join(project, 'openspec');
|
|
72
|
+
assertDirectory(openspec, 'Legacy OpenSpec path');
|
|
73
|
+
for (const relativePath of LEGACY_ACTIVE_PATHS) {
|
|
74
|
+
const target = join(project, relativePath);
|
|
75
|
+
assertNoSymlinkAncestors(target, 'Legacy OpenSpec path');
|
|
76
|
+
if (lstatMaybe(target)) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Active legacy OpenSpec content requires explicit migration before init: ${target}`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
52
84
|
function preflight(project) {
|
|
53
|
-
|
|
54
|
-
|
|
85
|
+
assertNoSymlinkAncestors(project, 'Project root');
|
|
86
|
+
const projectStat = lstatMaybe(project);
|
|
87
|
+
if (
|
|
88
|
+
!projectStat ||
|
|
89
|
+
!projectStat.isDirectory() ||
|
|
90
|
+
projectStat.isSymbolicLink()
|
|
91
|
+
) {
|
|
55
92
|
throw new Error(
|
|
56
93
|
`--project must reference an existing project directory: ${project}`,
|
|
57
94
|
);
|
|
@@ -64,64 +101,40 @@ function preflight(project) {
|
|
|
64
101
|
'constitution.md',
|
|
65
102
|
);
|
|
66
103
|
assertRegularFile(constitutionSource, 'Bundled constitution template');
|
|
67
|
-
if (!
|
|
104
|
+
if (!lstatMaybe(constitutionSource)) {
|
|
68
105
|
throw new Error(
|
|
69
106
|
`Bundled constitution template is missing: ${constitutionSource}`,
|
|
70
107
|
);
|
|
71
108
|
}
|
|
72
109
|
|
|
73
|
-
for (const directory of
|
|
74
|
-
assertDirectory(join(project, directory), '
|
|
110
|
+
for (const directory of THOTH_DIRECTORIES) {
|
|
111
|
+
assertDirectory(join(project, directory), 'Thoth path');
|
|
75
112
|
}
|
|
76
113
|
|
|
77
|
-
const constitutionTarget = join(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
);
|
|
83
|
-
const manifestTarget = join(project, 'openspec', '.thoth-agents.json');
|
|
84
|
-
assertRegularFile(constitutionTarget, 'OpenSpec constitution path');
|
|
85
|
-
assertRegularFile(manifestTarget, 'OpenSpec manifest path');
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
constitutionSource,
|
|
89
|
-
constitutionTarget,
|
|
90
|
-
manifestTarget,
|
|
91
|
-
};
|
|
114
|
+
const constitutionTarget = join(project, '.thoth', 'constitution.md');
|
|
115
|
+
assertRegularFile(constitutionTarget, 'Thoth constitution path');
|
|
116
|
+
assertNoLegacyActiveStore(project);
|
|
117
|
+
|
|
118
|
+
return { constitutionSource, constitutionTarget };
|
|
92
119
|
}
|
|
93
120
|
|
|
94
121
|
function createDirectory(target, report) {
|
|
95
|
-
if (
|
|
122
|
+
if (lstatMaybe(target)) return;
|
|
96
123
|
mkdirSync(target);
|
|
97
124
|
report.created.push(target);
|
|
98
125
|
}
|
|
99
126
|
|
|
100
127
|
function writePreservingExisting(target, content, report) {
|
|
101
|
-
if (
|
|
128
|
+
if (lstatMaybe(target)) {
|
|
102
129
|
report.preserved.push(target);
|
|
103
130
|
return;
|
|
104
131
|
}
|
|
105
|
-
writeFileSync(target, content);
|
|
132
|
+
writeFileSync(target, content, { flag: 'wx' });
|
|
106
133
|
report.created.push(target);
|
|
107
134
|
}
|
|
108
135
|
|
|
109
|
-
function
|
|
110
|
-
|
|
111
|
-
writeFileSync(target, content);
|
|
112
|
-
report.created.push(target);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
if (readFileSync(target, 'utf8') === content) {
|
|
116
|
-
report.preserved.push(target);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
writeFileSync(target, content);
|
|
120
|
-
report.managed.push(target);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function synchronizeOpenSpec(project, assets, report) {
|
|
124
|
-
for (const directory of OPEN_SPEC_DIRECTORIES) {
|
|
136
|
+
function initializeThoth(project, assets, report) {
|
|
137
|
+
for (const directory of THOTH_DIRECTORIES) {
|
|
125
138
|
createDirectory(join(project, directory), report);
|
|
126
139
|
}
|
|
127
140
|
|
|
@@ -134,11 +147,6 @@ function synchronizeOpenSpec(project, assets, report) {
|
|
|
134
147
|
),
|
|
135
148
|
report,
|
|
136
149
|
);
|
|
137
|
-
synchronizeManagedFile(
|
|
138
|
-
assets.manifestTarget,
|
|
139
|
-
`${JSON.stringify({ version: 1, initializedBy: 'thoth-agents' }, null, 2)}\n`,
|
|
140
|
-
report,
|
|
141
|
-
);
|
|
142
150
|
}
|
|
143
151
|
|
|
144
152
|
try {
|
|
@@ -149,15 +157,14 @@ try {
|
|
|
149
157
|
status: 'ready',
|
|
150
158
|
project,
|
|
151
159
|
created: [],
|
|
152
|
-
managed: [],
|
|
153
160
|
preserved: [],
|
|
154
161
|
};
|
|
155
162
|
|
|
156
|
-
|
|
163
|
+
initializeThoth(project, assets, report);
|
|
157
164
|
|
|
158
165
|
const output = options.json
|
|
159
166
|
? JSON.stringify(report)
|
|
160
|
-
: `thoth-agents
|
|
167
|
+
: `thoth-agents initialized .thoth governance in ${project}`;
|
|
161
168
|
process.stdout.write(`${output}\n`);
|
|
162
169
|
} catch (error) {
|
|
163
170
|
process.stderr.write(
|