@ngockhoale/ukit 3.4.42 → 3.4.43
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.43 - 2026-10-13
|
|
13
|
+
|
|
14
|
+
**Completion Gate: an ordered `git tag` is discharged by the tag itself, so the live release Stop is accepted.**
|
|
15
|
+
- Live root cause (3.4.42 still blocked this session): the prompt ordered a tag, so the git-integrity goal required target `tag`. A real tag created inside a compound command (`... && git tag ...; echo $?`) is a masked mutation and records as failed, and the independent remote-parity recovery only accepted `commit`/`push` targets, so `operation-verification` stayed missing although the tag, remote and registry were all correct.
|
|
16
|
+
- Fix: the gate-time git authority also lists the tags that dereference to live HEAD (`git tag --points-at HEAD`, peels annotated tags). When `tag` is a required target, a tag at HEAD plus the existing remote-parity proof (remote sha == HEAD on the tracking remote, clean tree, observed after every mutation attempt) recovers it. No tag at HEAD, a diverged remote, a dirty tree or a later mutation still blocks.
|
|
17
|
+
- Regressions in `tests/hooks/stopHookRelease.test.js`: masked tag with an annotated tag at HEAD -> ACCEPT (fails without the fix); no tag at HEAD -> BLOCK.
|
|
18
|
+
|
|
12
19
|
## 3.4.42 - 2026-10-13
|
|
13
20
|
|
|
14
21
|
**Completion Gate: `cd <repo>; <command>` is a checked command, so a finished release is recognized by the live Stop hook.**
|
package/package.json
CHANGED
|
@@ -3280,7 +3280,10 @@ function gitAuthority(cwd) {
|
|
|
3280
3280
|
if (!head || !branch) return null;
|
|
3281
3281
|
const remote = gitOutput(['config', `branch.${branch}.remote`], cwd);
|
|
3282
3282
|
const dirty = gitOutput(['status', '--porcelain'], cwd);
|
|
3283
|
-
|
|
3283
|
+
// Tags that dereference (`--points-at` peels annotated tags) to live HEAD: a masked `git tag` is recovered by
|
|
3284
|
+
// this independent local state, exactly like a masked push is recovered by remote parity.
|
|
3285
|
+
const tagsAtHead = (gitOutput(['tag', '--points-at', 'HEAD'], cwd) || '').split('\n').map((t) => t.trim()).filter(Boolean).slice(0, 16);
|
|
3286
|
+
return { head, branch, remote, tagsAtHead, clean: dirty === null && gitOutput(['rev-parse', '--git-dir'], cwd) !== null };
|
|
3284
3287
|
}
|
|
3285
3288
|
function withGitAuthority(ledger, cwd) {
|
|
3286
3289
|
const gitAuth = ledger && Object.keys(ledger).length ? gitAuthority(cwd) : null;
|
|
@@ -95,7 +95,7 @@ export function operationEvidenceStatus(goal, ledger = {}) {
|
|
|
95
95
|
// `ledger.gitAuthority` is the gate-time local truth; without it (or on any mismatch) nothing is proven.
|
|
96
96
|
const auth = ledger.gitAuthority;
|
|
97
97
|
if (goal.domain === 'git-integrity' && validRemoteSync(op.remoteSync) && auth && auth.clean === true
|
|
98
|
-
&& requiredTargets.every((t) => t === 'commit' || t === 'push')
|
|
98
|
+
&& requiredTargets.every((t) => t === 'commit' || t === 'push' || (t === 'tag' && Array.isArray(auth.tagsAtHead) && auth.tagsAtHead.length > 0))
|
|
99
99
|
&& attempts.every((r) => (Number.isSafeInteger(op.remoteSync.observedSequence) ? op.remoteSync.observedSequence : observation.sequence) > r.sequence)
|
|
100
100
|
&& op.remoteSync.sha === auth.head && op.remoteSync.ref === `refs/heads/${auth.branch}`
|
|
101
101
|
&& op.remoteSync.remote === auth.remote) return { complete: true, operationProof: 'remote-parity' };
|