@ctxr/skill-llm-wiki 1.0.2 → 1.2.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/CHANGELOG.md +128 -0
- package/README.md +11 -8
- package/SKILL.md +11 -11
- package/guide/cli.md +3 -2
- package/guide/correctness/safety.md +2 -2
- package/guide/layout/in-place-mode.md +1 -1
- package/guide/substrate/operators.md +1 -1
- package/guide/substrate/tiered-ai.md +6 -5
- package/guide/ux/user-intent.md +1 -1
- package/package.json +13 -4
- package/scripts/cli.mjs +92 -2
- package/scripts/lib/balance.mjs +579 -0
- package/scripts/lib/cluster-detect.mjs +482 -4
- package/scripts/lib/contract.mjs +53 -4
- package/scripts/lib/decision-log.mjs +121 -15
- package/scripts/lib/draft.mjs +127 -20
- package/scripts/lib/frontmatter.mjs +45 -9
- package/scripts/lib/heal.mjs +5 -0
- package/scripts/lib/intent.mjs +370 -4
- package/scripts/lib/join-constants.mjs +22 -0
- package/scripts/lib/join.mjs +917 -0
- package/scripts/lib/nest-applier.mjs +395 -32
- package/scripts/lib/operators.mjs +472 -38
- package/scripts/lib/orchestrator.mjs +419 -12
- package/scripts/lib/root-containment.mjs +351 -0
- package/scripts/lib/similarity-cache.mjs +115 -20
- package/scripts/lib/similarity.mjs +11 -0
- package/scripts/lib/soft-dag.mjs +726 -0
- package/scripts/lib/tier2-protocol.mjs +169 -37
- package/scripts/lib/tiered.mjs +42 -18
- package/scripts/lib/validate.mjs +22 -0
package/scripts/cli.mjs
CHANGED
|
@@ -326,9 +326,38 @@ Layout-mode flags (build/extend/rebuild/fix/join):
|
|
|
326
326
|
--target <path> Explicit destination (required for hosted)
|
|
327
327
|
|
|
328
328
|
Tiered-AI flags:
|
|
329
|
-
--quality-mode tiered-fast|claude-first|
|
|
329
|
+
--quality-mode tiered-fast|claude-first|deterministic
|
|
330
330
|
Default: tiered-fast (TF-IDF → embeddings
|
|
331
|
-
→ Claude ladder).
|
|
331
|
+
→ Claude ladder). The 'deterministic' mode
|
|
332
|
+
resolves every decision algorithmically
|
|
333
|
+
(no Tier 2 calls) for byte-reproducible
|
|
334
|
+
builds. See guide/tiered-ai.md.
|
|
335
|
+
|
|
336
|
+
Post-convergence enforcement flags (build/rebuild):
|
|
337
|
+
--fanout-target <N> Post-convergence phase ATTEMPTS to
|
|
338
|
+
sub-cluster any directory whose movable
|
|
339
|
+
leaf count exceeds N × 1.5 (subdirs aren't
|
|
340
|
+
counted — the rebalance can only carve
|
|
341
|
+
clusters from leaves, so subdir-heavy
|
|
342
|
+
dirs are un-actionable). An overfull dir
|
|
343
|
+
is left unchanged when no coherent
|
|
344
|
+
cluster is detected (leaves too diverse
|
|
345
|
+
or too few). N must be an integer in
|
|
346
|
+
[2, 100]. No-op when omitted.
|
|
347
|
+
--max-depth <D> Post-convergence phase flattens any
|
|
348
|
+
single-child passthrough deeper than D. D
|
|
349
|
+
must be an integer in [1, 10]. No-op when
|
|
350
|
+
omitted.
|
|
351
|
+
--soft-dag-parents Post-convergence phase synthesises
|
|
352
|
+
soft-parent pointers in each leaf's
|
|
353
|
+
parents[] based on TF-IDF cosine
|
|
354
|
+
similarity against candidate category
|
|
355
|
+
directories. Leaves appear in multiple
|
|
356
|
+
index.md entries[] (DAG view) rather
|
|
357
|
+
than only their direct parent. Uses
|
|
358
|
+
SOFT_PARENT_AFFINITY_THRESHOLD (0.35)
|
|
359
|
+
and caps at SOFT_PARENT_MAX_PER_LEAF (3)
|
|
360
|
+
per leaf. No-op when omitted.
|
|
332
361
|
|
|
333
362
|
UX flags:
|
|
334
363
|
--no-prompt Never prompt; fail loud on ambiguity
|
|
@@ -378,6 +407,9 @@ const FLAG_WITH_VALUE = new Set([
|
|
|
378
407
|
"--to",
|
|
379
408
|
"--canonical",
|
|
380
409
|
"--quality-mode",
|
|
410
|
+
"--fanout-target",
|
|
411
|
+
"--max-depth",
|
|
412
|
+
"--id-collision",
|
|
381
413
|
]);
|
|
382
414
|
const FLAG_BOOLEAN = new Set([
|
|
383
415
|
"--no-prompt",
|
|
@@ -386,6 +418,7 @@ const FLAG_BOOLEAN = new Set([
|
|
|
386
418
|
"--accept-dirty",
|
|
387
419
|
"--accept-foreign-target",
|
|
388
420
|
"--review",
|
|
421
|
+
"--soft-dag-parents",
|
|
389
422
|
]);
|
|
390
423
|
|
|
391
424
|
function parseSubArgv(raw) {
|
|
@@ -815,12 +848,69 @@ async function main() {
|
|
|
815
848
|
}
|
|
816
849
|
const opId = newOpId(cmd);
|
|
817
850
|
const startedIso = new Date().toISOString();
|
|
851
|
+
// X.9 progress: stream each orchestrator phase's `record()`
|
|
852
|
+
// output to stderr as it fires. On by default for interactive
|
|
853
|
+
// use; suppressed in JSON mode so stderr stays reserved for
|
|
854
|
+
// structured JSON diagnostics/errors (build/rebuild/fix/join
|
|
855
|
+
// still print their human-readable summary to stdout under
|
|
856
|
+
// --json, but a consumer tailing stderr under --json expects
|
|
857
|
+
// it to be empty on success or carry only structured
|
|
858
|
+
// diagnostics — progress breadcrumbs would mix into that
|
|
859
|
+
// channel). Also suppressed via `LLM_WIKI_NO_PROGRESS=1` for
|
|
860
|
+
// CI / hermetic runs that want the pre-X.9 silent shape.
|
|
861
|
+
// Progress goes to stderr (never stdout) so consumers piping
|
|
862
|
+
// the command's stdout don't conflate phase chatter with the
|
|
863
|
+
// final op-summary payload.
|
|
864
|
+
const suppressProgress =
|
|
865
|
+
jsonMode || process.env.LLM_WIKI_NO_PROGRESS === "1";
|
|
866
|
+
// A closed-stderr scenario (downstream pipe consumer that
|
|
867
|
+
// drops the stderr pipe, e.g. `… | head`) surfaces two ways:
|
|
868
|
+
// a synchronous throw on `.write()` (try/catch below), and
|
|
869
|
+
// an async `'error'` event with code EPIPE that the default
|
|
870
|
+
// Node handler escalates to an unhandled exception. Attach a
|
|
871
|
+
// best-effort one-time 'error' listener to swallow EPIPE
|
|
872
|
+
// while progress is enabled; other stream errors still
|
|
873
|
+
// surface via Node's default handler so we aren't masking
|
|
874
|
+
// bugs unrelated to the progress stream.
|
|
875
|
+
let stderrEpipeSilenced = false;
|
|
876
|
+
const onProgress = suppressProgress
|
|
877
|
+
? null
|
|
878
|
+
: (phase) => {
|
|
879
|
+
if (!stderrEpipeSilenced) {
|
|
880
|
+
stderrEpipeSilenced = true;
|
|
881
|
+
try {
|
|
882
|
+
process.stderr.on("error", (err) => {
|
|
883
|
+
if (err && err.code === "EPIPE") return;
|
|
884
|
+
// Re-emit non-EPIPE errors so we don't hide real
|
|
885
|
+
// problems — Node's default handler will decide.
|
|
886
|
+
throw err;
|
|
887
|
+
});
|
|
888
|
+
} catch {
|
|
889
|
+
/* attach failed — progress reporter will best-effort */
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
// `.destroyed` / `.writableEnded` guards let us skip the
|
|
893
|
+
// write before it would throw, which is cheaper than
|
|
894
|
+
// catching the exception and matches the behaviour on
|
|
895
|
+
// an already-closed stream.
|
|
896
|
+
if (process.stderr.destroyed || process.stderr.writableEnded) {
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
try {
|
|
900
|
+
process.stderr.write(
|
|
901
|
+
`[${opId} ${phase.index}] ${phase.name}: ${phase.summary}\n`,
|
|
902
|
+
);
|
|
903
|
+
} catch {
|
|
904
|
+
/* Best-effort — a closed stderr shouldn't halt the op. */
|
|
905
|
+
}
|
|
906
|
+
};
|
|
818
907
|
let result;
|
|
819
908
|
try {
|
|
820
909
|
result = await runOperation(plan, {
|
|
821
910
|
opId,
|
|
822
911
|
source: plan.source,
|
|
823
912
|
startedIso,
|
|
913
|
+
onProgress,
|
|
824
914
|
});
|
|
825
915
|
} catch (err) {
|
|
826
916
|
if (err instanceof NonInteractiveError) {
|