@ngockhoale/ukit 3.4.28 → 3.4.29
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
CHANGED
|
@@ -9,6 +9,13 @@ All notable changes to UKit are documented here.
|
|
|
9
9
|
- New `/ukit:ci-check` command + `ci-check.mjs` helper (core pack): prechecks, fail-closed budget guard, local preflight, at most one dispatch per invocation, write-ahead run-id state, `status` (never dispatches), `--ref`, `--dry-run`, per-OS report. Never pushes, merges or publishes.
|
|
10
10
|
- Default-branch bootstrap stub documented in `docs/design/CI-CROSS-PLATFORM-MATRIX.md` (requires separate approval).
|
|
11
11
|
|
|
12
|
+
## 3.4.29 - 2026-10-09
|
|
13
|
+
|
|
14
|
+
**Fixes (no new features).**
|
|
15
|
+
- `ukit install` inside the UKit source repo no longer overwrites the hand-curated root `CLAUDE.md` / `AGENTS.md` (repo-only Release Policy was lost). Self-install now seeds but never overwrites them, like `docs/`; downstream projects still get them refreshed. Regression: `tests/core/buildPlan.test.js`.
|
|
16
|
+
- `ukit status` no longer reads the ambient project's `context-capacity.json` (CLAUDE_PROJECT_DIR/cwd); the capacity record is scoped to the reported project root, so `statusCommand.test.js` passes with or without a live runtime cache.
|
|
17
|
+
- Completion gate: `yarn release:verify; echo "exit=$?"` (and `&&`/`|` variants without a space) is now recognised as a verification command, so the green run records `verification-evidence`. Failed runs still record as failed. Regression: `tests/hooks/executionLedgerReleaseVerify.test.js`.
|
|
18
|
+
|
|
12
19
|
## 3.4.28 - 2026-10-09
|
|
13
20
|
|
|
14
21
|
**Release-safety close-out: config preservation, safe `ukit update`, OMP eval/Bash hardening (local RC; not yet published).**
|
package/package.json
CHANGED
package/src/core/buildPlan.js
CHANGED
|
@@ -45,6 +45,16 @@ function safeResolve(basePath, relativePath) {
|
|
|
45
45
|
return resolvedPath;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// Root instruction files are hand-curated canonical sources in the UKit repo itself (they carry
|
|
49
|
+
// the repo-only Release Policy, rendered from instructions/ + the repo overlay), so a
|
|
50
|
+
// self-install must seed them but never overwrite them.
|
|
51
|
+
const SELF_INSTALL_PROTECTED_ROOT_FILES = new Set(['CLAUDE.md', 'AGENTS.md']);
|
|
52
|
+
|
|
53
|
+
function isSelfInstallProtectedTarget(targetPath, projectRoot) {
|
|
54
|
+
return isDocsTarget(targetPath, projectRoot)
|
|
55
|
+
|| SELF_INSTALL_PROTECTED_ROOT_FILES.has(path.relative(projectRoot, targetPath));
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
function isDocsTarget(targetPath, projectRoot) {
|
|
49
59
|
const relative = path.relative(projectRoot, targetPath);
|
|
50
60
|
return relative === 'docs' || relative.startsWith(`docs${path.sep}`);
|
|
@@ -88,7 +98,7 @@ async function downgradeSelfInstallDocOverwrites(planEntries, { templatesRoot, p
|
|
|
88
98
|
if (entry.type === 'link' || entry.mergeStrategy !== 'overwrite_with_backup') {
|
|
89
99
|
continue;
|
|
90
100
|
}
|
|
91
|
-
if (
|
|
101
|
+
if (isSelfInstallProtectedTarget(entry.targetPath, projectRoot)) {
|
|
92
102
|
entry.mergeStrategy = 'skip';
|
|
93
103
|
}
|
|
94
104
|
}
|
package/src/core/status.js
CHANGED
|
@@ -146,7 +146,9 @@ export async function buildStatusReport(projectRoot) {
|
|
|
146
146
|
const compactSummary = buildCompactSummary(compactHistory);
|
|
147
147
|
const compactPressure = await buildCompactPressureState(
|
|
148
148
|
await readStatusJson(runtimePaths.compactPressurePath),
|
|
149
|
-
|
|
149
|
+
// Scope the negotiated-capacity record to the reported project; without projectRoot the
|
|
150
|
+
// reader falls back to CLAUDE_PROJECT_DIR/cwd and leaks another project's runtime cache.
|
|
151
|
+
{ ...config, projectRoot },
|
|
150
152
|
);
|
|
151
153
|
const promptCacheStats = buildPromptCacheStats(await readStatusJson(runtimePaths.promptCachePath));
|
|
152
154
|
const outputCompressionStats = summarizeOutputHistory(await readStatusJson(runtimePaths.outputHistoryPath));
|
|
@@ -501,15 +501,17 @@ function extractExitCode(payload = {}) {
|
|
|
501
501
|
return null;
|
|
502
502
|
}
|
|
503
503
|
|
|
504
|
+
// The trailing boundary accepts shell terminators (`;`, `&`, `|`, `)`) so
|
|
505
|
+
// `yarn release:verify; echo "exit=$?"` — the real-exit-code idiom — still mints a receipt.
|
|
504
506
|
function isVerificationCommand(command) {
|
|
505
507
|
const text = String(command || '').trim();
|
|
506
508
|
if (!text) return false;
|
|
507
509
|
return [
|
|
508
|
-
/(?:^|\s|\.bin\/)(?:vitest|jest|mocha|ava|pytest|py\.test)(?:\s
|
|
509
|
-
/(?:^|\s)(?:npm|pnpm|yarn|bun)(?:\s+run)?\s+(?:test|lint|typecheck|check|build)(?:\s
|
|
510
|
-
/(?:^|\s)(?:npm|pnpm|yarn|bun)(?:\s+run)?\s+release:verify(?:\s
|
|
511
|
-
/(?:^|\s|\.bin\/)(?:tsc|eslint|biome|ruff|mypy)(?:\s
|
|
512
|
-
/(?:^|\s)node\s+--check(?:\s
|
|
510
|
+
/(?:^|\s|\.bin\/)(?:vitest|jest|mocha|ava|pytest|py\.test)(?:\s|$|[;&|)])/i,
|
|
511
|
+
/(?:^|\s)(?:npm|pnpm|yarn|bun)(?:\s+run)?\s+(?:test|lint|typecheck|check|build)(?:\s|$|[;&|)])/i,
|
|
512
|
+
/(?:^|\s)(?:npm|pnpm|yarn|bun)(?:\s+run)?\s+release:verify(?:\s|$|[;&|)])/i,
|
|
513
|
+
/(?:^|\s|\.bin\/)(?:tsc|eslint|biome|ruff|mypy)(?:\s|$|[;&|)])/i,
|
|
514
|
+
/(?:^|\s)node\s+--check(?:\s|$|[;&|)])/i,
|
|
513
515
|
].some((pattern) => pattern.test(text));
|
|
514
516
|
}
|
|
515
517
|
|