@imix-js/taproot 0.5.0 → 0.6.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/README.md +38 -28
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/commithook.js +68 -35
- package/dist/commands/commithook.js.map +1 -1
- package/dist/commands/coverage.d.ts +4 -0
- package/dist/commands/coverage.js +32 -0
- package/dist/commands/coverage.js.map +1 -1
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.js +160 -14
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/truth-sign.js +30 -5
- package/dist/commands/truth-sign.js.map +1 -1
- package/dist/core/dor-runner.js +116 -2
- package/dist/core/dor-runner.js.map +1 -1
- package/dist/core/impl-reader.d.ts +1 -0
- package/dist/core/impl-reader.js +8 -0
- package/dist/core/impl-reader.js.map +1 -1
- package/dist/validators/structure-rules.d.ts +1 -0
- package/dist/validators/structure-rules.js +15 -0
- package/dist/validators/structure-rules.js.map +1 -1
- package/package.json +3 -2
- package/skills/commit.md +13 -1
- package/skills/define-truth.md +24 -8
- package/skills/ineed.md +18 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
2
3
|
import { flattenTree } from '../core/fs-walker.js';
|
|
3
4
|
const KEBAB_CASE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
4
5
|
export function checkDuplicateMarkers(node) {
|
|
@@ -76,9 +77,23 @@ export function checkEmptyFolder(node) {
|
|
|
76
77
|
message: `${node.marker} folder "${node.name}" has no child folders`,
|
|
77
78
|
}];
|
|
78
79
|
}
|
|
80
|
+
export function checkGlobalTruthsIntent(root) {
|
|
81
|
+
const globalTruthsIntentPath = join(root.absolutePath, 'global-truths', 'intent.md');
|
|
82
|
+
if (!existsSync(globalTruthsIntentPath))
|
|
83
|
+
return [];
|
|
84
|
+
return [{
|
|
85
|
+
type: 'warning',
|
|
86
|
+
filePath: globalTruthsIntentPath,
|
|
87
|
+
code: 'GLOBAL_TRUTHS_INTENT_CONFLICT',
|
|
88
|
+
message: '`global-truths/` is a taproot-managed truth store — `intent.md` does not belong here. ' +
|
|
89
|
+
'Remove `global-truths/intent.md` (and any behaviours beneath it) and use truth files + ' +
|
|
90
|
+
'`check-if-affected-by` entries in `.taproot/settings.yaml` to enforce them instead.',
|
|
91
|
+
}];
|
|
92
|
+
}
|
|
79
93
|
export function validateStructure(root, options) {
|
|
80
94
|
const violations = [];
|
|
81
95
|
const nodes = flattenTree(root);
|
|
96
|
+
violations.push(...checkGlobalTruthsIntent(root));
|
|
82
97
|
for (const node of nodes) {
|
|
83
98
|
violations.push(...checkDuplicateMarkers(node));
|
|
84
99
|
if (node !== root)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structure-rules.js","sourceRoot":"","sources":["../../src/validators/structure-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"structure-rules.js","sourceRoot":"","sources":["../../src/validators/structure-rules.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imix-js/taproot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "AI-driven specs, enforced at commit time. Code without traceability doesn't merge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"test": "vitest run",
|
|
28
28
|
"test:watch": "vitest",
|
|
29
29
|
"test:coverage": "vitest run --coverage",
|
|
30
|
-
"typecheck": "tsc --noEmit"
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"preflight": "bash scripts/preflight.sh"
|
|
31
32
|
},
|
|
32
33
|
"repository": {
|
|
33
34
|
"type": "git",
|
package/skills/commit.md
CHANGED
|
@@ -60,7 +60,19 @@ Execute the full commit procedure: classify the commit type, run the appropriate
|
|
|
60
60
|
|
|
61
61
|
3. If a `check:` condition requires action you cannot take (e.g. failing tests), report: "Cannot commit — `<condition>` is unresolved and requires: `<correction hint>`." Stop and wait.
|
|
62
62
|
|
|
63
|
-
4.
|
|
63
|
+
4. **Truth consistency check** — if `taproot/global-truths/` exists:
|
|
64
|
+
a. Collect all truth files applicable at impl level: intent-scoped truths (always), behaviour-scoped truths, and impl-scoped truths.
|
|
65
|
+
b. Read each applicable truth file. If a file is unreadable, note it and skip.
|
|
66
|
+
c. Check the staged impl.md and source changes for consistency with applicable truths:
|
|
67
|
+
- Are defined architectural patterns and project conventions being followed?
|
|
68
|
+
- Are implementation-level rules respected?
|
|
69
|
+
- Are domain terms used consistently with their definitions?
|
|
70
|
+
d. If a conflict is found, surface it before proceeding:
|
|
71
|
+
> "Truth conflict: `<excerpt>` in staged changes conflicts with `global-truths/<file>`: `<truth excerpt>`. [A] Fix the implementation | [B] Update the truth | [C] Proceed with conflict noted"
|
|
72
|
+
Wait for the developer's choice. Do not proceed to step 5 until resolved.
|
|
73
|
+
e. If no conflicts (or all resolved): run `taproot truth-sign` to record the session marker the hook validates.
|
|
74
|
+
|
|
75
|
+
5. Stage source files + all matched impl.md files and commit with a concise one-line message.
|
|
64
76
|
|
|
65
77
|
### Declaration commit
|
|
66
78
|
|
package/skills/define-truth.md
CHANGED
|
@@ -38,9 +38,25 @@ Create or update a truth entry in `taproot/global-truths/` — a fact, business
|
|
|
38
38
|
|
|
39
39
|
Wait for the developer's choice.
|
|
40
40
|
|
|
41
|
-
### Phase 3 —
|
|
41
|
+
### Phase 3 — Name the File
|
|
42
42
|
|
|
43
|
-
4.
|
|
43
|
+
4. Propose a category-level name for the file — one that can hold multiple related truths, not the specific term being captured now:
|
|
44
|
+
|
|
45
|
+
> "What should the file be called? Pick a category name so related truths can live together:
|
|
46
|
+
>
|
|
47
|
+
> Suggested names by scope:
|
|
48
|
+
> - **intent**: `glossary` · `principles` · `ux-principles` · `domain-model` · `system-context`
|
|
49
|
+
> - **behaviour**: `principles` · `guarantees` · `rules`
|
|
50
|
+
> - **impl**: `architecture` · `tech-choices` · `patterns`
|
|
51
|
+
>
|
|
52
|
+
> (Or enter your own name — keep it generic enough to hold future truths of the same kind.)"
|
|
53
|
+
|
|
54
|
+
If a file with that name already exists at the target path, note it:
|
|
55
|
+
> "A file `<name>_<scope>.md` already exists — I'll append to it rather than create a new one."
|
|
56
|
+
|
|
57
|
+
### Phase 4 — Choose Convention
|
|
58
|
+
|
|
59
|
+
5. Ask which storage convention to use:
|
|
44
60
|
> "Which convention do you prefer?
|
|
45
61
|
> - **[S] Suffix** — `<name>_<scope>.md` in `taproot/global-truths/` (e.g. `glossary_intent.md`)
|
|
46
62
|
> - **[F] Sub-folder** — `<scope>/<name>.md` in `taproot/global-truths/` (e.g. `intent/glossary.md`)
|
|
@@ -50,25 +66,25 @@ Create or update a truth entry in `taproot/global-truths/` — a fact, business
|
|
|
50
66
|
If the project already has truth files using one convention, note it:
|
|
51
67
|
> "Your project currently uses the <suffix|sub-folder> convention — using it here keeps things consistent."
|
|
52
68
|
|
|
53
|
-
### Phase
|
|
69
|
+
### Phase 5 — Write the File
|
|
54
70
|
|
|
55
|
-
|
|
71
|
+
6. Determine the file path:
|
|
56
72
|
- **Suffix**: `taproot/global-truths/<name>_<scope>.md`
|
|
57
73
|
- **Sub-folder**: `taproot/global-truths/<scope>/<name>.md`
|
|
58
74
|
|
|
59
75
|
Create `taproot/global-truths/` if it does not exist.
|
|
60
76
|
|
|
61
|
-
|
|
77
|
+
7. If the file already exists, read it and present:
|
|
62
78
|
> "A truth file already exists at `<path>`. Here's the current content: [excerpt]. Do you want to [A] append to it, [B] replace it, or [C] cancel?"
|
|
63
79
|
Wait for the developer's choice.
|
|
64
80
|
|
|
65
|
-
|
|
81
|
+
8. Write the truth file with the confirmed content. Report:
|
|
66
82
|
> "✓ Written: `<path>` (scope: <scope>)"
|
|
67
83
|
|
|
68
|
-
|
|
84
|
+
9. **Scope ambiguity check** — if the file was placed directly in `taproot/global-truths/` with no `_<scope>` suffix and not inside a scoped sub-folder, warn:
|
|
69
85
|
> "`<filename>` has no scope signal — it defaults to intent scope (applies everywhere). Add a `_intent`, `_behaviour`, or `_impl` suffix, or move it to a scoped sub-folder, to make the scope explicit."
|
|
70
86
|
|
|
71
|
-
|
|
87
|
+
10. **Conflicting scope signals check** — if the file has both a suffix and is inside a scoped sub-folder that disagree, warn:
|
|
72
88
|
> "`<path>` has conflicting scope signals — sub-folder (`<folder-scope>`) is more restrictive than suffix (`<suffix-scope>`). The restrictive scope (`<folder-scope>`) applies. Rename or move the file to resolve."
|
|
73
89
|
|
|
74
90
|
> 💡 If this session is getting long, consider running `/compact` or starting a fresh context before the next task.
|
package/skills/ineed.md
CHANGED
|
@@ -10,7 +10,24 @@ Route a natural language requirement to the right place in the taproot hierarchy
|
|
|
10
10
|
|
|
11
11
|
## Steps
|
|
12
12
|
|
|
13
|
-
0. **
|
|
13
|
+
0. **Global truth check** — Before anything else, determine if the requirement is a **principle, fact, or rule to capture** rather than a feature to build or enforce.
|
|
14
|
+
|
|
15
|
+
Global truth signals:
|
|
16
|
+
- User explicitly says "as a global truth", "add this as a truth", "capture this as a principle"
|
|
17
|
+
- The requirement is a design principle or quality attribute with no concrete actor or user-visible action (e.g. "fail early", "discoverable by default", "no surprises")
|
|
18
|
+
- The requirement describes how the system *should be* rather than what it *should do*
|
|
19
|
+
|
|
20
|
+
If a global truth signal is present, **interrupt before proceeding**:
|
|
21
|
+
> "That sounds like a **global truth** — a design principle to capture in `taproot/global-truths/`, not a feature to build. Should I route it there, or is this something that should actively enforce on every implementation via a DoD gate?
|
|
22
|
+
> **[A]** Global truth → route to `/tr-define-truth`
|
|
23
|
+
> **[B]** Enforcement gate → apply `check-if-affected-by` pattern
|
|
24
|
+
> **[C]** New requirement → continue with normal routing"
|
|
25
|
+
|
|
26
|
+
- **[A]**: call `/tr-define-truth` with the principle. Stop — do not continue routing.
|
|
27
|
+
- **[B]**: proceed to pattern check below.
|
|
28
|
+
- **[C]** or no global truth signal: proceed to pattern check below.
|
|
29
|
+
|
|
30
|
+
0a. **Pattern check** — If `.taproot/docs/patterns.md` exists, scan the stated requirement for semantic matches against the patterns listed there. Match signals:
|
|
14
31
|
- "apply to all / every implementation / every skill / everywhere" → `check-if-affected-by`
|
|
15
32
|
- "guide agents / architecture rules / agents should follow / enforce a rule" → `check-if-affected-by`
|
|
16
33
|
- "enforce documentation / docs must stay current / keep docs accurate" → `document-current`
|