@chrisdudek/yg 5.2.2 → 5.2.4
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 +2 -2
- package/dist/bin.js +21 -18
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @chrisdudek/yg
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Stop babysitting your agent.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Your architecture rules become checks it can't skip, run on every change before it moves on. A script runs them locally for free, or an LLM reviews the call a script can't make. Checks run against your code, not your diffs. The feedback is specific, and the agent has to fix before it can move on. Works with Claude Code, Cursor, Copilot, Codex, Cline, and more.
|
|
6
6
|
|
|
7
7
|
See the [main README](https://github.com/krzysztofdudek/Yggdrasil#readme) for documentation, or visit
|
|
8
8
|
[krzysztofdudek.github.io/Yggdrasil](https://krzysztofdudek.github.io/Yggdrasil/).
|
package/dist/bin.js
CHANGED
|
@@ -3621,13 +3621,12 @@ async function writeLock(yggRoot, lock, opts = {}) {
|
|
|
3621
3621
|
}
|
|
3622
3622
|
const { det, nondet } = partitionVerdicts(lock.verdicts, detIds);
|
|
3623
3623
|
if (scope === "deterministic") {
|
|
3624
|
-
|
|
3625
|
-
await writeFileIfChanged(detLockPath(yggRoot), content20);
|
|
3624
|
+
await writeOrRemoveSplitFile(detLockPath(yggRoot), lock.version, det, {});
|
|
3626
3625
|
return;
|
|
3627
3626
|
}
|
|
3628
|
-
await
|
|
3627
|
+
await writeOrRemoveSplitFile(nondetLockPath(yggRoot), lock.version, nondet, {});
|
|
3629
3628
|
await writeOrRemoveSplitFile(logsLockPath(yggRoot), lock.version, {}, lock.nodes);
|
|
3630
|
-
await
|
|
3629
|
+
await writeOrRemoveSplitFile(detLockPath(yggRoot), lock.version, det, {});
|
|
3631
3630
|
}
|
|
3632
3631
|
|
|
3633
3632
|
// src/cli/preamble.ts
|
|
@@ -15822,20 +15821,20 @@ function registerCheckCommand(program2) {
|
|
|
15822
15821
|
const gitFiles = collectGitFiles(projectRoot);
|
|
15823
15822
|
const wantsTop = opts.top !== void 0;
|
|
15824
15823
|
if (wantsTop && opts.summary) {
|
|
15825
|
-
process.
|
|
15824
|
+
process.stderr.write(chalk8.red(buildIssueMessage({
|
|
15826
15825
|
what: "--top and --summary cannot be combined.",
|
|
15827
15826
|
why: "Both are read-only triage VIEWS of the same `yg check` result \u2014 --top renders the N highest-priority blocks, --summary renders per-node counts only. Asking for both at once is ambiguous; pick one lens.",
|
|
15828
15827
|
next: "Run: yg check --top <n> (priority blocks), or yg check --summary (per-node counts)."
|
|
15829
|
-
}) + "\n");
|
|
15828
|
+
}) + "\n"));
|
|
15830
15829
|
await exitAfterFlush(1);
|
|
15831
15830
|
return;
|
|
15832
15831
|
}
|
|
15833
15832
|
if ((wantsTop || opts.summary) && opts.approve) {
|
|
15834
|
-
process.
|
|
15833
|
+
process.stderr.write(chalk8.red(buildIssueMessage({
|
|
15835
15834
|
what: `${wantsTop ? "--top" : "--summary"} cannot be combined with --approve.`,
|
|
15836
15835
|
why: "--top and --summary triage the READ-ONLY check wall (they narrow the output of plain `yg check`, which writes nothing). --approve is the writer path; its own free cost preview is --dry-run. Mixing a read-only triage view with the writer is contradictory.",
|
|
15837
15836
|
next: `Run: yg check ${wantsTop ? "--top <n>" : "--summary"} (read-only triage), or yg check --approve --dry-run (preview the writer's cost).`
|
|
15838
|
-
}) + "\n");
|
|
15837
|
+
}) + "\n"));
|
|
15839
15838
|
await exitAfterFlush(1);
|
|
15840
15839
|
return;
|
|
15841
15840
|
}
|
|
@@ -15845,22 +15844,22 @@ function registerCheckCommand(program2) {
|
|
|
15845
15844
|
} else if (wantsTop) {
|
|
15846
15845
|
const n = resolveTopValue(opts.top);
|
|
15847
15846
|
if (n === null) {
|
|
15848
|
-
process.
|
|
15847
|
+
process.stderr.write(chalk8.red(buildIssueMessage({
|
|
15849
15848
|
what: `--top expects a non-negative whole number; got "${String(opts.top)}".`,
|
|
15850
15849
|
why: "--top N prints the N highest-priority issue blocks. A negative, fractional, or non-numeric value is meaningless, and printing the full wall instead would silently hide that the flag was ignored \u2014 masking the very output you tried to narrow.",
|
|
15851
15850
|
next: "Run: yg check --top 5 (top 5 blocks), yg check --top (just the suggestedNext block), or yg check (full output)."
|
|
15852
|
-
}) + "\n");
|
|
15851
|
+
}) + "\n"));
|
|
15853
15852
|
await exitAfterFlush(1);
|
|
15854
15853
|
return;
|
|
15855
15854
|
}
|
|
15856
15855
|
view = { kind: "top", n };
|
|
15857
15856
|
}
|
|
15858
15857
|
if (opts.dryRun && !opts.approve) {
|
|
15859
|
-
process.
|
|
15858
|
+
process.stderr.write(chalk8.red(buildIssueMessage({
|
|
15860
15859
|
what: "--dry-run requires --approve.",
|
|
15861
15860
|
why: "--dry-run previews what `yg check --approve` would fill (the reviewer-call budget and per-node breakdown) without writing or calling the reviewer; it is a mode of --approve, not a variant of the plain read. Plain `yg check` is already a free, no-write read.",
|
|
15862
15861
|
next: "Run: yg check --approve --dry-run (cost preview), or yg check (plain read)."
|
|
15863
|
-
}) + "\n");
|
|
15862
|
+
}) + "\n"));
|
|
15864
15863
|
await exitAfterFlush(1);
|
|
15865
15864
|
return;
|
|
15866
15865
|
}
|
|
@@ -15880,7 +15879,7 @@ function registerCheckCommand(program2) {
|
|
|
15880
15879
|
return;
|
|
15881
15880
|
}
|
|
15882
15881
|
const hasErrors2 = fill.checkResult.issues.some((i) => i.severity === "error");
|
|
15883
|
-
|
|
15882
|
+
await exitAfterFlush(hasErrors2 ? 1 : 0);
|
|
15884
15883
|
return;
|
|
15885
15884
|
} catch (err) {
|
|
15886
15885
|
if (err instanceof FillGatingError) {
|
|
@@ -15893,7 +15892,7 @@ function registerCheckCommand(program2) {
|
|
|
15893
15892
|
const result = await runCheck(graph, gitFiles);
|
|
15894
15893
|
process.stdout.write(formatOutput(result, view));
|
|
15895
15894
|
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
15896
|
-
|
|
15895
|
+
await exitAfterFlush(hasErrors ? 1 : 0);
|
|
15897
15896
|
} catch (error) {
|
|
15898
15897
|
debugWrite(`[check] error: ${error.message}`);
|
|
15899
15898
|
abortOnUnexpectedError(error, "running check");
|
|
@@ -19534,10 +19533,14 @@ pairs on that node \u2014 a legitimate vacuous pass, no verdict, no entry.
|
|
|
19534
19533
|
\`yg knowledge read log-management\`) and the append-only log integrity baseline.
|
|
19535
19534
|
The source fingerprint is the log gate's drift basis, so it is recorded ONLY for
|
|
19536
19535
|
\`log_required\` nodes \u2014 a non-log_required node gets a \`nodes\` entry only when it
|
|
19537
|
-
owns a \`log.md\` (then holding just the \`log\` baseline, no \`source\`).
|
|
19538
|
-
|
|
19539
|
-
is not written at all
|
|
19540
|
-
|
|
19536
|
+
owns a \`log.md\` (then holding just the \`log\` baseline, no \`source\`).
|
|
19537
|
+
- Empty section \u21D2 no file. Each of the three split files is written ONLY when its
|
|
19538
|
+
section is non-empty; when empty it is not written at all (an existing empty husk
|
|
19539
|
+
is removed). So a repo with no LLM aspects has no \`yg-lock.nondeterministic.json\`,
|
|
19540
|
+
one with no \`log_required\` node and no \`log.md\` has no \`yg-lock.logs.json\`, and
|
|
19541
|
+
one with no deterministic aspects has no \`.yg-lock.deterministic.json\`. readLock
|
|
19542
|
+
treats an absent file as empty state, so this is transparent to every reader \u2014 a
|
|
19543
|
+
repo only carries the lock files it actually needs.
|
|
19541
19544
|
- The built-in relation-conformance check is NOT stored in the lock \u2014 it is
|
|
19542
19545
|
recomputed live on every \`yg check\`. The lock holds only aspect \`verdicts\`
|
|
19543
19546
|
and per-node \`nodes\` facts; there is no relation section. See "Relation
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrisdudek/yg",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.4",
|
|
4
4
|
"description": "Architecture rules your AI coding agent can't ignore. It gets the rules for a file before it edits, and every change is checked — by a free local script or an LLM reviewer — before it moves on. Works with Claude Code, Cursor, Copilot, Codex, Cline.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"@tree-sitter-grammars/tree-sitter-kotlin": "^1.1.0",
|
|
86
86
|
"@tree-sitter-grammars/tree-sitter-toml": "^0.7.0",
|
|
87
87
|
"@tree-sitter-grammars/tree-sitter-yaml": "^0.7.1",
|
|
88
|
-
"@types/node": "^
|
|
88
|
+
"@types/node": "^26.0.0",
|
|
89
89
|
"@types/semver": "^7.7.1",
|
|
90
90
|
"@vitest/coverage-v8": "^4.1.8",
|
|
91
91
|
"eslint": "^10.4.1",
|