rhachet-roles-bhrain 0.31.0 → 0.31.2
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/dist/contract/cli/learn.d.ts +9 -0
- package/dist/contract/cli/learn.js +342 -0
- package/dist/contract/cli/learn.js.map +1 -0
- package/dist/contract/cli/route.js +42 -33
- package/dist/contract/cli/route.js.map +1 -1
- package/dist/domain.objects/Driver/PassageReport.d.ts +13 -2
- package/dist/domain.objects/Driver/PassageReport.js.map +1 -1
- package/dist/domain.objects/Driver/RouteStoneDisposition.d.ts +19 -0
- package/dist/domain.objects/Driver/RouteStoneDisposition.js +3 -0
- package/dist/domain.objects/Driver/RouteStoneDisposition.js.map +1 -0
- package/dist/domain.objects/Driver/RouteStoneGuardBlockerReport.d.ts +10 -3
- package/dist/domain.objects/Driver/RouteStoneGuardBlockerReport.js.map +1 -1
- package/dist/domain.operations/cli/getInvocationArgs.d.ts +8 -0
- package/dist/domain.operations/cli/getInvocationArgs.js +17 -0
- package/dist/domain.operations/cli/getInvocationArgs.js.map +1 -0
- package/dist/domain.operations/cli/isNodeEvalMode.d.ts +13 -0
- package/dist/domain.operations/cli/isNodeEvalMode.js +27 -0
- package/dist/domain.operations/cli/isNodeEvalMode.js.map +1 -0
- package/dist/domain.operations/learn/genDomainTermsScaffold.d.ts +18 -0
- package/dist/domain.operations/learn/genDomainTermsScaffold.js +90 -0
- package/dist/domain.operations/learn/genDomainTermsScaffold.js.map +1 -0
- package/dist/domain.operations/learn/genFile.d.ts +25 -0
- package/dist/domain.operations/learn/genFile.js +72 -0
- package/dist/domain.operations/learn/genFile.js.map +1 -0
- package/dist/domain.operations/learn/genSymlink.d.ts +26 -0
- package/dist/domain.operations/learn/genSymlink.js +78 -0
- package/dist/domain.operations/learn/genSymlink.js.map +1 -0
- package/dist/domain.operations/learn/getDomainTermsPaths.d.ts +25 -0
- package/dist/domain.operations/learn/getDomainTermsPaths.js +65 -0
- package/dist/domain.operations/learn/getDomainTermsPaths.js.map +1 -0
- package/dist/domain.operations/learn/getFsErrorCode.d.ts +9 -0
- package/dist/domain.operations/learn/getFsErrorCode.js +20 -0
- package/dist/domain.operations/learn/getFsErrorCode.js.map +1 -0
- package/dist/domain.operations/learn/getSweepProgress.d.ts +13 -0
- package/dist/domain.operations/learn/getSweepProgress.js +61 -0
- package/dist/domain.operations/learn/getSweepProgress.js.map +1 -0
- package/dist/domain.operations/learn/isProgressArticulated.d.ts +23 -0
- package/dist/domain.operations/learn/isProgressArticulated.js +33 -0
- package/dist/domain.operations/learn/isProgressArticulated.js.map +1 -0
- package/dist/domain.operations/learn/isSweepStale.d.ts +20 -0
- package/dist/domain.operations/learn/isSweepStale.js +32 -0
- package/dist/domain.operations/learn/isSweepStale.js.map +1 -0
- package/dist/domain.operations/route/drive/asRouteDisplayPath.d.ts +11 -0
- package/dist/domain.operations/route/drive/asRouteDisplayPath.js +38 -0
- package/dist/domain.operations/route/drive/asRouteDisplayPath.js.map +1 -0
- package/dist/domain.operations/route/drive/asRouteStoneDisposition.d.ts +16 -0
- package/dist/domain.operations/route/drive/asRouteStoneDisposition.js +52 -0
- package/dist/domain.operations/route/drive/asRouteStoneDisposition.js.map +1 -0
- package/dist/domain.operations/route/drive/formatRouteDriveBudgetExhausted.d.ts +14 -0
- package/dist/domain.operations/route/drive/formatRouteDriveBudgetExhausted.js +60 -0
- package/dist/domain.operations/route/drive/formatRouteDriveBudgetExhausted.js.map +1 -0
- package/dist/domain.operations/route/drive/getCurrentExhaustedSlugs.d.ts +16 -0
- package/dist/domain.operations/route/drive/getCurrentExhaustedSlugs.js +36 -0
- package/dist/domain.operations/route/drive/getCurrentExhaustedSlugs.js.map +1 -0
- package/dist/domain.operations/route/drive/getRouteDriveBlockerMessage.js +6 -106
- package/dist/domain.operations/route/drive/getRouteDriveBlockerMessage.js.map +1 -1
- package/dist/domain.operations/route/drive/getRouteDriveExhaustedMessage.d.ts +13 -0
- package/dist/domain.operations/route/drive/getRouteDriveExhaustedMessage.js +30 -0
- package/dist/domain.operations/route/drive/getRouteDriveExhaustedMessage.js.map +1 -0
- package/dist/domain.operations/route/drive/getStoneGuardBlockerReport.js +12 -10
- package/dist/domain.operations/route/drive/getStoneGuardBlockerReport.js.map +1 -1
- package/dist/domain.operations/route/drive/setStoneGuardBlockerReport.d.ts +7 -2
- package/dist/domain.operations/route/drive/setStoneGuardBlockerReport.js +5 -0
- package/dist/domain.operations/route/drive/setStoneGuardBlockerReport.js.map +1 -1
- package/dist/domain.operations/route/passage/getAllLatestPassageByStone.d.ts +18 -0
- package/dist/domain.operations/route/passage/getAllLatestPassageByStone.js +29 -0
- package/dist/domain.operations/route/passage/getAllLatestPassageByStone.js.map +1 -0
- package/dist/domain.operations/route/passage/getAllPassageReports.d.ts +1 -1
- package/dist/domain.operations/route/passage/getAllPassageReports.js +3 -40
- package/dist/domain.operations/route/passage/getAllPassageReports.js.map +1 -1
- package/dist/domain.operations/route/passage/getAllPassageReportsRaw.d.ts +18 -0
- package/dist/domain.operations/route/passage/getAllPassageReportsRaw.js +61 -0
- package/dist/domain.operations/route/passage/getAllPassageReportsRaw.js.map +1 -0
- package/dist/domain.operations/route/passage/getLatestPassageForStone.d.ts +23 -0
- package/dist/domain.operations/route/passage/getLatestPassageForStone.js +31 -0
- package/dist/domain.operations/route/passage/getLatestPassageForStone.js.map +1 -0
- package/dist/domain.operations/route/statusLine/asStatusLine.d.ts +36 -5
- package/dist/domain.operations/route/statusLine/asStatusLine.js +86 -10
- package/dist/domain.operations/route/statusLine/asStatusLine.js.map +1 -1
- package/dist/domain.operations/route/stepRouteDrive.js +131 -45
- package/dist/domain.operations/route/stepRouteDrive.js.map +1 -1
- package/dist/domain.operations/route/stepRouteStatusLine.d.ts +8 -9
- package/dist/domain.operations/route/stepRouteStatusLine.js +250 -16
- package/dist/domain.operations/route/stepRouteStatusLine.js.map +1 -1
- package/dist/domain.operations/route/stones/genStoneGuardBlockedEmit.d.ts +2 -2
- package/dist/domain.operations/route/stones/setStoneAsContemplated.js +15 -0
- package/dist/domain.operations/route/stones/setStoneAsContemplated.js.map +1 -1
- package/dist/domain.operations/route/stones/setStoneAsPassed.js +34 -7
- package/dist/domain.operations/route/stones/setStoneAsPassed.js.map +1 -1
- package/dist/domain.operations/route/stones/setStoneAsPromised.d.ts +4 -2
- package/dist/domain.operations/route/stones/setStoneAsPromised.js +18 -2
- package/dist/domain.operations/route/stones/setStoneAsPromised.js.map +1 -1
- package/dist/domain.roles/learner/boot.yml +10 -0
- package/dist/domain.roles/learner/briefs/howto.domain-term-disputes.[guide].md +75 -0
- package/dist/domain.roles/learner/briefs/im_an.obsessive_learner.for.domain.terms.md +86 -0
- package/dist/domain.roles/learner/briefs/im_an.obsessive_learner.md +2 -0
- package/dist/domain.roles/learner/briefs/readme.domain-terms.md +39 -0
- package/dist/domain.roles/learner/briefs/rule.forbid.domain-term-synonyms.md +50 -0
- package/dist/domain.roles/learner/briefs/rule.require.domain-term-itemization.md +61 -0
- package/dist/domain.roles/learner/briefs/template.domain-term.md +106 -0
- package/dist/domain.roles/learner/getLearnerRole.js +10 -0
- package/dist/domain.roles/learner/getLearnerRole.js.map +1 -1
- package/dist/domain.roles/learner/skills/learn.domain.terms.sh +27 -0
- package/package.json +5 -4
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = cli entrypoint for the learn.domain.terms skill (both faces)
|
|
3
|
+
* .why = the onStop hook nudges when the distillation is stale; the clone runs it
|
|
4
|
+
* to reflect + distill
|
|
5
|
+
*
|
|
6
|
+
* exits 0 when fresh (hook), after the guide (clone), or after --help
|
|
7
|
+
* exits 2 when stale (hook) to hold the stop open (never a write)
|
|
8
|
+
*/
|
|
9
|
+
export declare const learnDomainTerms: () => Promise<void>;
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.learnDomainTerms = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* .what = cli entrypoint for the learner learn.domain.terms skill
|
|
6
|
+
* .why = enables shell invocation via package-level import, isolated on its own
|
|
7
|
+
* cli subpath so the onStop hook loads minimal modules (see
|
|
8
|
+
* rule.require.isolated-cli-subpath-exports)
|
|
9
|
+
*
|
|
10
|
+
* two faces, one skill (mirrors the driver's route.drive):
|
|
11
|
+
* --when hook.onStop → staleness check; exit 2 to hold the stop when the
|
|
12
|
+
* distillation is stale, else exit 0 (read-only, never writes)
|
|
13
|
+
* (no --when) → the clone's reflect-and-distill guide; findserts the
|
|
14
|
+
* glossary scaffold, then prints how to distill
|
|
15
|
+
*/
|
|
16
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
17
|
+
const getInvocationArgs_1 = require("../../domain.operations/cli/getInvocationArgs");
|
|
18
|
+
const genDomainTermsScaffold_1 = require("../../domain.operations/learn/genDomainTermsScaffold");
|
|
19
|
+
const getDomainTermsPaths_1 = require("../../domain.operations/learn/getDomainTermsPaths");
|
|
20
|
+
const getSweepProgress_1 = require("../../domain.operations/learn/getSweepProgress");
|
|
21
|
+
const isProgressArticulated_1 = require("../../domain.operations/learn/isProgressArticulated");
|
|
22
|
+
const isSweepStale_1 = require("../../domain.operations/learn/isSweepStale");
|
|
23
|
+
/**
|
|
24
|
+
* .what = emit the established two-line header — mascot + slogan, then scroll + command
|
|
25
|
+
* .why = all three faces (clone guide, onStop nudge, --help) open the SAME way; render
|
|
26
|
+
* from ONE place so the headers can never drift out of sync
|
|
27
|
+
* (rule.require.single-source-of-truth-for-render). the slogan varies by face
|
|
28
|
+
* (the nudge is a staleness reminder, the others a plain invocation) but the
|
|
29
|
+
* shape — `🦉 <slogan>` / blank / `📜 <command>` — is identical for all
|
|
30
|
+
*/
|
|
31
|
+
const emitHeader = (emit, input) => {
|
|
32
|
+
emit(`🦉 ${input.slogan}`);
|
|
33
|
+
emit('');
|
|
34
|
+
emit(`📜 ${input.command}`);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* .what = the flag portion of a token — the part before any `=` (e.g. `--help=x` → `--help`)
|
|
38
|
+
* .why = one splitter so both the help check and the allowlist parse the combined
|
|
39
|
+
* `--flag=value` form the same way (rule.require.ubiqlang — one parse of a token)
|
|
40
|
+
*/
|
|
41
|
+
const asFlagName = (arg) => arg.split('=')[0];
|
|
42
|
+
/**
|
|
43
|
+
* .what = the flags the rhachet harness always injects to identify the invocation
|
|
44
|
+
* .why = `rhx <skill>` prepends --skill/--role/--repo (each with a value) to the argv it
|
|
45
|
+
* hands the wrapper; they name WHICH skill ran, they are NOT part of this skill's
|
|
46
|
+
* own surface. they must be stripped before the strict allowlist runs, else
|
|
47
|
+
* assertKnownFlags rejects the harness's own flags and the onStop hook can never fire
|
|
48
|
+
*/
|
|
49
|
+
const RHACHET_INJECTED_FLAGS = ['--skill', '--role', '--repo'];
|
|
50
|
+
/**
|
|
51
|
+
* .what = the caller's own args — the invocation args minus the rhachet-injected flags
|
|
52
|
+
* .why = leaves only this skill's surface (--when / --help) for strict validation, so a
|
|
53
|
+
* genuine typo or stray positional is still caught while the harness flags pass
|
|
54
|
+
* through. handles both the space form (`--skill x`) and the combined (`--skill=x`)
|
|
55
|
+
*/
|
|
56
|
+
const getOwnArgs = (argv) => {
|
|
57
|
+
const args = (0, getInvocationArgs_1.getInvocationArgs)(argv);
|
|
58
|
+
// mark each injected flag token, plus the value token after a space-form one
|
|
59
|
+
const dropped = new Set();
|
|
60
|
+
args.forEach((arg, index) => {
|
|
61
|
+
if (!RHACHET_INJECTED_FLAGS.includes(asFlagName(arg)))
|
|
62
|
+
return;
|
|
63
|
+
dropped.add(index);
|
|
64
|
+
// `--skill=x` carries its value inline; `--skill x` puts it in the next token
|
|
65
|
+
if (!arg.includes('='))
|
|
66
|
+
dropped.add(index + 1);
|
|
67
|
+
});
|
|
68
|
+
return args.filter((_, index) => !dropped.has(index));
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* .what = detect a --help / -h request in argv (both bare and `--help=` combined forms)
|
|
72
|
+
* .why = a help request must short-circuit BEFORE either face runs, so the clone face
|
|
73
|
+
* never writes on a --help (rule.require.help-on-demand). the combined `--help=x`
|
|
74
|
+
* form must also count, else it silently falls through to the clone face that writes
|
|
75
|
+
*/
|
|
76
|
+
const isHelpRequested = (argv) => {
|
|
77
|
+
const args = getOwnArgs(argv);
|
|
78
|
+
return args.some((arg) => ['--help', '-h'].includes(asFlagName(arg)));
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* .what = the flags this skill recognizes (its whole surface)
|
|
82
|
+
* .why = one allowlist so assertKnownFlags can reject all else — a typo like
|
|
83
|
+
* --wen must fail loud, never silently fall through to the clone face
|
|
84
|
+
*/
|
|
85
|
+
const KNOWN_FLAGS = ['--when', '--help', '-h'];
|
|
86
|
+
/**
|
|
87
|
+
* .what = is this token one the skill recognizes?
|
|
88
|
+
* .why = accepts the conventional combined `--flag=value` form a human expects
|
|
89
|
+
* (rule.forbid.friction-hazards), via asFlagName. the posix `--` marker is
|
|
90
|
+
* already filtered by getInvocationArgs, so it never reaches here
|
|
91
|
+
*/
|
|
92
|
+
const isKnownToken = (arg) => KNOWN_FLAGS.includes(asFlagName(arg));
|
|
93
|
+
/**
|
|
94
|
+
* .what = reject any token the skill does not recognize (unknown flags AND stray positionals)
|
|
95
|
+
* .why = an unrecognized token — a typo `--wen`, a `--verbose`, or a bare positional `foo` —
|
|
96
|
+
* must NOT be silently ignored, else the clone face runs and writes when the caller
|
|
97
|
+
* intended the hook face or a no-op. this skill has ZERO positional args, so any token
|
|
98
|
+
* that is not a known flag (nor a --when value) is a fault. fail-loud
|
|
99
|
+
* (rule.forbid.friction-hazards, safe-by-default)
|
|
100
|
+
*/
|
|
101
|
+
const assertKnownFlags = (argv) => {
|
|
102
|
+
const args = getOwnArgs(argv);
|
|
103
|
+
// the token right after a space-form `--when` is its VALUE, not a flag — skip it so
|
|
104
|
+
// a value that starts with `-` (e.g. `--when -x`) reads as the value and parseWhen
|
|
105
|
+
// gives the precise `invalid --when: -x` error, not a generic unknown-token one
|
|
106
|
+
const whenIndex = args.indexOf('--when');
|
|
107
|
+
const whenValueIndex = whenIndex === -1 ? -1 : whenIndex + 1;
|
|
108
|
+
const unknown = args.filter((arg, index) => index !== whenValueIndex && !isKnownToken(arg));
|
|
109
|
+
if (unknown.length === 0)
|
|
110
|
+
return;
|
|
111
|
+
throw new helpful_errors_1.BadRequestError(`unexpected arg(s): ${unknown.join(', ')}. this skill accepts only: --when hook.onStop | --help | -h`, { unknown });
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* .what = validate a --when value into the one supported hook context
|
|
115
|
+
* .why = an absent or wrong value is a caller error, never a silent fall-through to
|
|
116
|
+
* the clone face (which writes). fail-loud on both (rule.forbid.failhide)
|
|
117
|
+
*/
|
|
118
|
+
const asWhenValue = (value) => {
|
|
119
|
+
if (value === 'hook.onStop')
|
|
120
|
+
return 'hook.onStop';
|
|
121
|
+
// render the fault legibly: an absent token reads '(absent)', an empty value
|
|
122
|
+
// (e.g. the combined `--when=` form) reads '(empty)' — never a blank before the
|
|
123
|
+
// period, which would read as a cryptic error (rule.forbid.friction-hazards)
|
|
124
|
+
const shown = value === undefined ? '(absent)' : value === '' ? '(empty)' : value;
|
|
125
|
+
throw new helpful_errors_1.BadRequestError(`invalid --when: ${shown}. only 'hook.onStop' is supported`, { when: value ?? null });
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* .what = parse the --when hook context from argv
|
|
129
|
+
* .why = selects the hook face vs the clone face; only hook.onStop is a hook
|
|
130
|
+
* context here (this skill has no onBoot face). accepts both the combined
|
|
131
|
+
* `--when=value` and the space-separated `--when value` forms
|
|
132
|
+
*/
|
|
133
|
+
const parseWhen = (argv) => {
|
|
134
|
+
const args = getOwnArgs(argv);
|
|
135
|
+
// combined form `--when=value` → validate its inline value
|
|
136
|
+
const combined = args.find((arg) => arg.startsWith('--when='));
|
|
137
|
+
if (combined)
|
|
138
|
+
return asWhenValue(combined.slice('--when='.length));
|
|
139
|
+
// no --when at all → clone face
|
|
140
|
+
const whenIndex = args.indexOf('--when');
|
|
141
|
+
if (whenIndex === -1)
|
|
142
|
+
return undefined;
|
|
143
|
+
// space-separated form `--when value` → validate the next token
|
|
144
|
+
return asWhenValue(args[whenIndex + 1]);
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* .what = the shared distill guidance body — the how (reflect + act) + the canon
|
|
148
|
+
* .why = both faces teach the SAME moves and cite the SAME canon; render them from
|
|
149
|
+
* ONE place, into a caller-supplied sink (stdout for the clone guide, stderr
|
|
150
|
+
* for the onStop nudge), so the two renders can never drift
|
|
151
|
+
* (rule.require.single-source-of-truth-for-render,
|
|
152
|
+
* rule.forbid.duplicate-format-tree-operations). every line is a mid-branch
|
|
153
|
+
* (`├─`), so each face wraps it with its own opener and closer
|
|
154
|
+
*/
|
|
155
|
+
const emitDistillMoves = (emit, input) => {
|
|
156
|
+
emit(' ├─ do this now — review + redistill the terms this round touched');
|
|
157
|
+
emit(' │ ├─ 1. recall — which domain objects & operations did you declare or engage?');
|
|
158
|
+
emit(' │ │ split each name into its terms (getStone → verb `get` + noun `stone`)');
|
|
159
|
+
emit(' │ ├─ 2. conform-or-dispute each EXTANT term (already in the glossary):');
|
|
160
|
+
emit(' │ │ ├─ your contract uses the canonical word → conform, you are done');
|
|
161
|
+
emit(' │ │ └─ you reached for a synonym → rename to the canonical word,');
|
|
162
|
+
emit(' │ │ or open a dispute in its `.reason` (adhere, or argue — never drift)');
|
|
163
|
+
emit(' │ ├─ 3. pave the path for each NEW term (born this round, not yet in the glossary):');
|
|
164
|
+
emit(' │ │ ├─ write its `term=<x>._.choice.*` cluster:');
|
|
165
|
+
emit(' │ │ │ ├─ term=<x>._.choice._.md (say: chosen word, kind, forbidden synonyms)');
|
|
166
|
+
emit(' │ │ │ ├─ term=<x>._.choice.reason.md (ref: etymology, disputes, evidence — required)');
|
|
167
|
+
emit(' │ │ │ └─ term=<x>._.choice.example=<abc>.md (ref: one per notable example — optional)');
|
|
168
|
+
emit(' │ │ └─ or cite it — point to the extant declaration you reused');
|
|
169
|
+
emit(' │ └─ 4. articulate progress.md — REQUIRED, the last step every round:');
|
|
170
|
+
emit(' │ ├─ what you conformed, disputed, and paved this round — and why');
|
|
171
|
+
emit(' │ ├─ a term the round SETTLED (declared dobj/dop, judged synonym) → capture it NOW');
|
|
172
|
+
emit(' │ ├─ defer ONLY a term you truly cannot finish (needs discovery, dispute still open)');
|
|
173
|
+
emit(` │ └─ sentinel = ${input.progressPath}`);
|
|
174
|
+
emit(' │');
|
|
175
|
+
// the canon — the booted briefs + rules that DEFINE a domain-term lesson + its rules,
|
|
176
|
+
// so the reader recalls exactly what a term is + why it is kept
|
|
177
|
+
emit(' ├─ the canon — what a term is + why it is kept');
|
|
178
|
+
emit(' │ ├─ why · im_an.obsessive_learner.for.domain.terms.md (the trait)');
|
|
179
|
+
emit(' │ ├─ rule · rule.require.domain-term-itemization (itemize each declared term)');
|
|
180
|
+
emit(' │ ├─ rule · rule.forbid.domain-term-synonyms (canonical term, or dispute)');
|
|
181
|
+
emit(' │ ├─ how · template.domain-term.md + howto.domain-term-disputes.[guide].md');
|
|
182
|
+
emit(` │ └─ glos · ${input.glossaryReadmePath}`);
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* .what = emit the onStop staleness nudge to stderr
|
|
186
|
+
* .why = stderr (not stdout) per rule.forbid.stdout-on-exit-errors; cli hooks
|
|
187
|
+
* surface stderr on non-zero exit
|
|
188
|
+
*
|
|
189
|
+
* structure: ask → why → [shared how + canon] → the-time-is-now → close, so the ask is
|
|
190
|
+
* never abstract — the reader learns WHAT to do, WHY it matters, HOW to do it, WHICH
|
|
191
|
+
* booted briefs/rules define the concepts, and that the moment to act is now
|
|
192
|
+
*/
|
|
193
|
+
const emitStaleNudge = (input) => {
|
|
194
|
+
const emit = (line) => console.error(line);
|
|
195
|
+
emitHeader(emit, {
|
|
196
|
+
slogan: 'time again, to tend the terms',
|
|
197
|
+
command: 'learn.domain.terms --when hook.onStop',
|
|
198
|
+
});
|
|
199
|
+
emit(' │');
|
|
200
|
+
emit(' ├─ the ask — now, before you rest');
|
|
201
|
+
emit(' │ └─ review the terms this round touched, then redistill: conform-or-dispute');
|
|
202
|
+
emit(' │ the extant ones, and pave the path for any new ones. the steps are below');
|
|
203
|
+
emit(' │');
|
|
204
|
+
emit(' ├─ the why');
|
|
205
|
+
emit(' │ └─ the repo vocabulary compiles hour by hour; a term touched but not tended');
|
|
206
|
+
emit(' │ is a lesson lost — the next traveler re-derives it, or drifts to a synonym.');
|
|
207
|
+
emit(' │ an hour has passed, so the moment to tend it is now');
|
|
208
|
+
emit(' │');
|
|
209
|
+
emitDistillMoves(emit, input);
|
|
210
|
+
emit(' │');
|
|
211
|
+
emit(' ├─ the time to capture is now');
|
|
212
|
+
emit(' │ └─ your distillation went stale (> 1 hour) — tend it before you rest');
|
|
213
|
+
emit(' │');
|
|
214
|
+
emit(' └─ 🪷 distill, then rest — the glossary grows, the floor rises for all who follow');
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* .what = emit the scaffold-status line(s) of the clone guide
|
|
218
|
+
* .why = split out so the guide stays flat — a guard clause + early return keeps
|
|
219
|
+
* the two cases (no-op run vs written) linear, no else branch
|
|
220
|
+
* (rule.forbid.else-branches). a no-op pass is silent: the scaffold already
|
|
221
|
+
* converged, so there is no news to report — silence keeps the guide on the
|
|
222
|
+
* one thing that matters, the distillation (rule.require.status-feedback:
|
|
223
|
+
* report what CHANGED; an unchanged scaffold is not a change)
|
|
224
|
+
*/
|
|
225
|
+
const emitScaffoldStatus = (input) => {
|
|
226
|
+
// a no-op run wrote no path this pass (every piece already converged) — stay silent
|
|
227
|
+
if (input.created.length === 0)
|
|
228
|
+
return;
|
|
229
|
+
// otherwise, name each artifact written this pass (findsert create or upsert reconcile)
|
|
230
|
+
console.log(' ├─ scaffold written');
|
|
231
|
+
input.created.forEach((path, index) => {
|
|
232
|
+
const isLast = index === input.created.length - 1;
|
|
233
|
+
console.log(` │ ${isLast ? '└─' : '├─'} ${path}`);
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* .what = emit the clone-face reflect-and-distill guide to stdout
|
|
238
|
+
* .why = the sweep does no work on its own — the learner decides what the round
|
|
239
|
+
* was worth. this guide names the glossary + scaffold status, then renders
|
|
240
|
+
* the SAME shared how + canon body the onStop nudge does (emitDistillMoves),
|
|
241
|
+
* so the clone face and the hook face can never teach a divergent guide
|
|
242
|
+
*/
|
|
243
|
+
const emitReflectionGuide = (input) => {
|
|
244
|
+
const emit = (line) => console.log(line);
|
|
245
|
+
emitHeader(emit, { slogan: 'tend the terms', command: 'learn.domain.terms' });
|
|
246
|
+
emit(` ├─ glossary = ${input.glossaryDir}`);
|
|
247
|
+
emitScaffoldStatus({ created: input.created });
|
|
248
|
+
emit(' │');
|
|
249
|
+
emitDistillMoves(emit, {
|
|
250
|
+
progressPath: input.progressPath,
|
|
251
|
+
glossaryReadmePath: input.glossaryReadmePath,
|
|
252
|
+
});
|
|
253
|
+
emit(' │');
|
|
254
|
+
emit(' └─ 🪷 distill, then rest — the glossary grows, the floor rises for all who follow');
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* .what = emit the --help usage to stdout (both faces, args, exit codes)
|
|
258
|
+
* .why = every user-faced op must explain itself on demand; help is not an error,
|
|
259
|
+
* so it goes to stdout + exits 0 (rule.require.help-on-demand)
|
|
260
|
+
*/
|
|
261
|
+
const emitHelp = () => {
|
|
262
|
+
const emit = (line) => console.log(line);
|
|
263
|
+
emitHeader(emit, { slogan: 'tend the terms', command: 'learn.domain.terms' });
|
|
264
|
+
emit('');
|
|
265
|
+
emit(' usage:');
|
|
266
|
+
console.log(' learn.domain.terms # clone face: write the scaffold,');
|
|
267
|
+
console.log(' # then guide the reflect-and-distill');
|
|
268
|
+
console.log(' learn.domain.terms --when hook.onStop');
|
|
269
|
+
console.log(' # hook face: staleness check');
|
|
270
|
+
console.log(' learn.domain.terms --help | -h # this help');
|
|
271
|
+
console.log('');
|
|
272
|
+
console.log(' faces:');
|
|
273
|
+
console.log(' ├─ clone (no --when) → writes the scaffold, prints the guide; exit 0');
|
|
274
|
+
console.log(' └─ hook (--when hook.onStop) → read-only staleness check');
|
|
275
|
+
console.log(' ├─ fresh distillation (< 1 hour) → exit 0 (session rests)');
|
|
276
|
+
console.log(' └─ stale (> 1 hour) → exit 2 (holds the stop, never a write)');
|
|
277
|
+
console.log('');
|
|
278
|
+
console.log(' --when values: hook.onStop (only)');
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* .what = cli entrypoint for the learn.domain.terms skill (both faces)
|
|
282
|
+
* .why = the onStop hook nudges when the distillation is stale; the clone runs it
|
|
283
|
+
* to reflect + distill
|
|
284
|
+
*
|
|
285
|
+
* exits 0 when fresh (hook), after the guide (clone), or after --help
|
|
286
|
+
* exits 2 when stale (hook) to hold the stop open (never a write)
|
|
287
|
+
*/
|
|
288
|
+
const learnDomainTerms = async () => {
|
|
289
|
+
// --help: print usage, exit 0, never mutate. a help request must not run the
|
|
290
|
+
// clone face (which writes the scaffold) — safe-by-default (rule.require.help-on-demand)
|
|
291
|
+
if (isHelpRequested(process.argv)) {
|
|
292
|
+
emitHelp();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
// a bad --when is a caller-constraint, not a malfunction — exit 2, not 1
|
|
296
|
+
// (rule.require.exit-code-semantics). allowlist BadRequestError only; any other
|
|
297
|
+
// throw propagates to the wrapper's exit-1 backstop (no failhide)
|
|
298
|
+
const when = (() => {
|
|
299
|
+
try {
|
|
300
|
+
assertKnownFlags(process.argv);
|
|
301
|
+
return parseWhen(process.argv);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
if (!(error instanceof helpful_errors_1.BadRequestError))
|
|
305
|
+
throw error;
|
|
306
|
+
console.error(error.message);
|
|
307
|
+
return process.exit(2);
|
|
308
|
+
}
|
|
309
|
+
})();
|
|
310
|
+
const paths = (0, getDomainTermsPaths_1.getDomainTermsPaths)();
|
|
311
|
+
// hook face: read-only staleness check
|
|
312
|
+
if (when === 'hook.onStop') {
|
|
313
|
+
// freshness turns on BOTH a recent mtime AND a real articulation in the content,
|
|
314
|
+
// so a bare `touch` cannot silence the nudge (guards the one hard requirement)
|
|
315
|
+
const progress = await (0, getSweepProgress_1.getSweepProgress)({ path: paths.progressPath });
|
|
316
|
+
const articulated = (0, isProgressArticulated_1.isProgressArticulated)({ content: progress.content });
|
|
317
|
+
const stale = (0, isSweepStale_1.isSweepStale)({
|
|
318
|
+
mtime: progress.mtime,
|
|
319
|
+
articulated,
|
|
320
|
+
now: new Date(),
|
|
321
|
+
});
|
|
322
|
+
// fresh, articulated distillation → let the session rest
|
|
323
|
+
if (!stale)
|
|
324
|
+
return;
|
|
325
|
+
// stale → hold the stop open with a gentle nudge (never blocks a write)
|
|
326
|
+
emitStaleNudge({
|
|
327
|
+
progressPath: paths.progressPath,
|
|
328
|
+
glossaryReadmePath: paths.readmePath,
|
|
329
|
+
});
|
|
330
|
+
process.exit(2);
|
|
331
|
+
}
|
|
332
|
+
// clone face: findsert the scaffold, then guide the reflection
|
|
333
|
+
const scaffold = await (0, genDomainTermsScaffold_1.genDomainTermsScaffold)();
|
|
334
|
+
emitReflectionGuide({
|
|
335
|
+
glossaryDir: scaffold.glossaryDir,
|
|
336
|
+
glossaryReadmePath: paths.readmePath,
|
|
337
|
+
created: scaffold.created,
|
|
338
|
+
progressPath: paths.progressPath,
|
|
339
|
+
});
|
|
340
|
+
};
|
|
341
|
+
exports.learnDomainTerms = learnDomainTerms;
|
|
342
|
+
//# sourceMappingURL=learn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learn.js","sourceRoot":"","sources":["../../../src/contract/cli/learn.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,7 @@ const fs = __importStar(require("fs/promises"));
|
|
|
29
29
|
const helpful_errors_1 = require("helpful-errors");
|
|
30
30
|
const path = __importStar(require("path"));
|
|
31
31
|
const RouteStoneGuard_1 = require("../../domain.objects/Driver/RouteStoneGuard");
|
|
32
|
+
const getInvocationArgs_1 = require("../../domain.operations/cli/getInvocationArgs");
|
|
32
33
|
const delRouteBind_1 = require("../../domain.operations/route/bind/delRouteBind");
|
|
33
34
|
const getRouteBind_1 = require("../../domain.operations/route/bind/getRouteBind");
|
|
34
35
|
const getRouteBindByBranch_1 = require("../../domain.operations/route/bind/getRouteBindByBranch");
|
|
@@ -61,26 +62,6 @@ const findStoneByName_1 = require("../../domain.operations/route/stones/findSton
|
|
|
61
62
|
const getAllStones_1 = require("../../domain.operations/route/stones/getAllStones");
|
|
62
63
|
const isPromisedActionSlugAbsent_1 = require("../../domain.operations/route/stones/isPromisedActionSlugAbsent");
|
|
63
64
|
const enumFilesFromGlob_1 = require("../../utils/enumFilesFromGlob");
|
|
64
|
-
/**
|
|
65
|
-
* .what = detects if node was invoked via `node -e "code"` (eval mode)
|
|
66
|
-
* .why = in eval mode, argv has no entrypoint path and args come after --
|
|
67
|
-
*
|
|
68
|
-
* argv patterns:
|
|
69
|
-
* normal: ['node', '/path/to/entry.js', '--arg', 'val']
|
|
70
|
-
* eval: ['node', 'arg1', 'arg2'] (node strips -e and code from argv!)
|
|
71
|
-
*
|
|
72
|
-
* detection: if argv[1] doesn't look like a file path, assume eval mode
|
|
73
|
-
*/
|
|
74
|
-
const isNodeEvalMode = (argv) => {
|
|
75
|
-
const secondArg = argv[1];
|
|
76
|
-
if (!secondArg)
|
|
77
|
-
return false;
|
|
78
|
-
// entrypoint path (ends with js/ts extension) = normal mode
|
|
79
|
-
if (/\.(js|ts|mjs|cjs)$/.test(secondArg))
|
|
80
|
-
return false;
|
|
81
|
-
// otherwise assume eval mode (node strips -e and code from argv)
|
|
82
|
-
return true;
|
|
83
|
-
};
|
|
84
65
|
/**
|
|
85
66
|
* .what = copies bytes read from a buffer into a new buffer
|
|
86
67
|
* .why = encapsulates buffer slice for readability in stdin read loops
|
|
@@ -167,13 +148,11 @@ const isValidStonePassageAction = (input) => {
|
|
|
167
148
|
return !!input.action && VALID_STONE_PASSAGE_ACTIONS.has(input.action);
|
|
168
149
|
};
|
|
169
150
|
/**
|
|
170
|
-
* .what = extracts clean args from argv,
|
|
171
|
-
* .why =
|
|
151
|
+
* .what = extracts clean args from argv, skips node/entrypoint args and the `--` separator
|
|
152
|
+
* .why = the canonical eval-mode slice now lives in one place (domain.operations/cli/
|
|
153
|
+
* getInvocationArgs), so route + learn share it instead of divergent copies
|
|
172
154
|
*/
|
|
173
|
-
const getCleanArgsFromArgv = (input) =>
|
|
174
|
-
const skipCount = isNodeEvalMode(input.argv) ? 1 : 2;
|
|
175
|
-
return input.argv.slice(skipCount).filter((arg) => arg !== '--');
|
|
176
|
-
};
|
|
155
|
+
const getCleanArgsFromArgv = (input) => (0, getInvocationArgs_1.getInvocationArgs)(input.argv);
|
|
177
156
|
/**
|
|
178
157
|
* .what = parses cli args into options object
|
|
179
158
|
* .why = simple arg parser without external dependencies
|
|
@@ -447,6 +426,16 @@ options:
|
|
|
447
426
|
onStop: show guidance, exit 2 (block premature stop)
|
|
448
427
|
--help show this help message
|
|
449
428
|
|
|
429
|
+
output:
|
|
430
|
+
when the stone can self-drive, route.drive echoes the current stone + guidance.
|
|
431
|
+
when it has halted and needs a human, it switches to a halt message instead:
|
|
432
|
+
✋ halted, stone marked blocked a driver wall (--as blocked) — clear it
|
|
433
|
+
👋 halted, peer reviewer budget exhausted approve as-is, or extend the budget
|
|
434
|
+
💥 halted, guard malfunction a reviewer or judge broke — a human must fix
|
|
435
|
+
onStop honors the same halt: exit 2 keeps the route in motion, exit 0 allows a
|
|
436
|
+
clean stop, exit 1 escalates a malfunction (per rule.require.exit-code-semantics).
|
|
437
|
+
onBoot always exits 0 (it never blocks session start).
|
|
438
|
+
|
|
450
439
|
examples:
|
|
451
440
|
route.drive # echo current stone
|
|
452
441
|
route.drive --when hook.onBoot # show stone, exit 0 (for onBoot hooks)
|
|
@@ -467,10 +456,20 @@ options:
|
|
|
467
456
|
--help show this help message
|
|
468
457
|
|
|
469
458
|
output:
|
|
470
|
-
bound, stone
|
|
471
|
-
bound, all stones passed 🗿 route complete
|
|
459
|
+
bound, stone + phase 🗿 <stone>, <phase> <emoji>
|
|
460
|
+
bound, all stones passed 🗿 route complete 🌴🤙
|
|
472
461
|
unbound / no stones (empty line)
|
|
473
462
|
|
|
463
|
+
the phase suffix names where inside the stone the driver is, tipped with an
|
|
464
|
+
attention-color emoji at the end of the line (read the color, then the words):
|
|
465
|
+
yield 🌾 the stone yields its artifact — calm, no attention
|
|
466
|
+
review.self, r7/r10 🔍 self-reviews, r{done}/r{total} — machine's turn
|
|
467
|
+
review.peer, l3@i002 🔍 peer review, l{level}@i{rounds} — machine's turn
|
|
468
|
+
judge, approved? 👋 a human must approve — attention needed
|
|
469
|
+
..., exhausted 👋 peer budget spent, a human must approve or extend
|
|
470
|
+
..., blocked ✋ blocked, act now — attention needed
|
|
471
|
+
..., malfunction 💥 a reviewer or judge broke, a human must fix
|
|
472
|
+
|
|
474
473
|
errors:
|
|
475
474
|
a genuine fault is logged to stderr and exits non-zero; the harness then renders
|
|
476
475
|
a blank line (the fault is surfaced on stderr, never silently hidden)
|
|
@@ -1469,7 +1468,9 @@ const routeMutateGrant = async () => {
|
|
|
1469
1468
|
grantOption: options.grant,
|
|
1470
1469
|
});
|
|
1471
1470
|
if (!action || !['allow', 'block', 'get'].includes(action)) {
|
|
1472
|
-
|
|
1471
|
+
// usage on an invalid/absent action is an error path → stderr, not stdout
|
|
1472
|
+
// (rule.forbid.stdout-on-exit-errors: stdout may be hidden on non-zero exit)
|
|
1473
|
+
console.error(`
|
|
1473
1474
|
route.mutate grant - manage route protection privilege
|
|
1474
1475
|
|
|
1475
1476
|
usage:
|
|
@@ -1480,7 +1481,9 @@ usage:
|
|
|
1480
1481
|
options:
|
|
1481
1482
|
--route <path> route path (default: auto-detect from branch)
|
|
1482
1483
|
`);
|
|
1483
|
-
|
|
1484
|
+
// exit 2 = constraint: the caller gave a bad action and must fix the invocation
|
|
1485
|
+
// (rule.require.exit-code-semantics: 0 ok, 1 malfunction, 2 constraint)
|
|
1486
|
+
process.exit(2);
|
|
1484
1487
|
}
|
|
1485
1488
|
try {
|
|
1486
1489
|
// get route from option or auto-detect
|
|
@@ -1679,7 +1682,9 @@ const routeGuardBudget = async () => {
|
|
|
1679
1682
|
// validate --add option
|
|
1680
1683
|
const addStr = options.add;
|
|
1681
1684
|
if (!addStr) {
|
|
1682
|
-
|
|
1685
|
+
// usage on an absent required flag is an error path → stderr, not stdout
|
|
1686
|
+
// (rule.forbid.stdout-on-exit-errors: stdout may be hidden on non-zero exit)
|
|
1687
|
+
console.error(`
|
|
1683
1688
|
route.guard.budget - extend peer reviewer budget
|
|
1684
1689
|
|
|
1685
1690
|
usage:
|
|
@@ -1694,12 +1699,16 @@ options:
|
|
|
1694
1699
|
--peer peer reviewer slug to extend (default: all peers)
|
|
1695
1700
|
--route path to route directory (default: auto-detect from branch)
|
|
1696
1701
|
`);
|
|
1697
|
-
|
|
1702
|
+
// exit 2 = constraint: the caller omitted a required flag and must fix the invocation
|
|
1703
|
+
// (rule.require.exit-code-semantics: 0 ok, 1 malfunction, 2 constraint)
|
|
1704
|
+
process.exit(2);
|
|
1698
1705
|
}
|
|
1699
1706
|
const addAmount = asPositiveIntegerOrNull({ value: addStr });
|
|
1700
1707
|
if (addAmount === null) {
|
|
1701
1708
|
console.error('error: --add must be a positive integer');
|
|
1702
|
-
|
|
1709
|
+
// exit 2 = constraint: the caller passed a malformed value and must fix the
|
|
1710
|
+
// invocation (rule.require.exit-code-semantics: 0 ok, 1 malfunction, 2 constraint)
|
|
1711
|
+
process.exit(2);
|
|
1703
1712
|
}
|
|
1704
1713
|
const peerSlug = options.peer;
|
|
1705
1714
|
const stoneName = options.stone;
|