@planu/cli 5.3.15 → 5.3.17
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 +21 -0
- package/dist/engine/evidence-gates/evidence-autofill.d.ts +5 -0
- package/dist/engine/evidence-gates/evidence-autofill.js +51 -8
- package/dist/engine/evidence-index/done-drift.d.ts +1 -0
- package/dist/engine/evidence-index/done-drift.js +32 -16
- package/dist/engine/execution/validate-job-executor.js +51 -44
- package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-arm64.node.sbom.json +4 -4
- package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-x64.node.sbom.json +4 -4
- package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +4 -4
- package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +4 -4
- package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +4 -4
- package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +4 -4
- package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +4 -4
- package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +4 -4
- package/dist/engine/validation/validation-freshness.d.ts +7 -0
- package/dist/engine/validation/validation-freshness.js +46 -5
- package/dist/tools/update-status/evidence-gate.js +6 -1
- package/dist/tools/update-status/index.js +2 -1
- package/dist/types/evidence-autofill.d.ts +2 -0
- package/package.json +9 -9
- package/planu-native.json +1 -1
- package/planu-plugin.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [5.3.17] - 2026-08-11
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
- fix(spec-1487): normalize spec paths in toRepoRelativePath per implementation-review arbitration
|
|
5
|
+
- fix(spec-1487): exclude Planu bookkeeping paths from traceability autofill and done drift gate
|
|
6
|
+
|
|
7
|
+
### Chores
|
|
8
|
+
- chore(specs): record SPEC-1487 done transition
|
|
9
|
+
- chore(spec-1487): record implementation-review round and approved scope amendment
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## [5.3.16] - 2026-08-11
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
- fix(spec-1477): bound publication-window wait per implementation-review arbitration
|
|
16
|
+
- fix(spec-1477): publication window blocks same-identity lease supersession mid-receipt
|
|
17
|
+
|
|
18
|
+
### Chores
|
|
19
|
+
- chore(specs): record SPEC-1477 done transition and file SPEC-1487 dogfood bug
|
|
20
|
+
|
|
21
|
+
|
|
1
22
|
## [5.3.15] - 2026-08-11
|
|
2
23
|
|
|
3
24
|
### Bug Fixes
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { AutofillTraceabilityMatrixArgs, AutofillTraceabilityMatrixResult } from '../../types/evidence-autofill.js';
|
|
2
|
+
/** Exact Planu lifecycle files every spec branch mutates; never counted as implementation drift. */
|
|
3
|
+
export declare const PLANU_BOOKKEEPING_FILES: readonly ['planu/context.md', 'planu/session-context.md', 'planu/session.json', 'planu/status.json', 'planu/releases/pending.json', 'planu/conventions.json'];
|
|
4
|
+
/** Normalizes a spec.md path (absolute or already repo-relative) to a repo-relative,
|
|
5
|
+
* forward-slash path so it can be compared against `git diff` output. */
|
|
6
|
+
export declare function toRepoRelativePath(specPath: string, projectPath?: string): string;
|
|
2
7
|
/**
|
|
3
8
|
* Generate `traceability-matrix.json` in the handoff evidence store when it does
|
|
4
9
|
* not already exist. Never overwrites an existing file — if one is present this
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// legacy harnesses, etc.).
|
|
20
20
|
import { execFile } from 'node:child_process';
|
|
21
21
|
import { existsSync } from 'node:fs';
|
|
22
|
-
import { isAbsolute, join, resolve } from 'node:path';
|
|
22
|
+
import { isAbsolute, join, relative, resolve } from 'node:path';
|
|
23
23
|
import { promisify } from 'node:util';
|
|
24
24
|
import { extractAcceptanceCriteriaTexts } from '../spec-format/acceptance-criteria.js';
|
|
25
25
|
import { parseFrontmatterScenarios } from '../validator/spec-compliance-runner.js';
|
|
@@ -35,7 +35,28 @@ const defaultExec = async (command, args, options) => {
|
|
|
35
35
|
const { stdout } = await execFileAsync(command, args, { cwd: options.cwd, encoding: 'utf-8' });
|
|
36
36
|
return stdout;
|
|
37
37
|
};
|
|
38
|
-
/**
|
|
38
|
+
/** Exact Planu lifecycle files every spec branch mutates; never counted as implementation drift. */
|
|
39
|
+
export const PLANU_BOOKKEEPING_FILES = [
|
|
40
|
+
'planu/context.md',
|
|
41
|
+
'planu/session-context.md',
|
|
42
|
+
'planu/session.json',
|
|
43
|
+
'planu/status.json',
|
|
44
|
+
'planu/releases/pending.json',
|
|
45
|
+
'planu/conventions.json',
|
|
46
|
+
];
|
|
47
|
+
const OTHER_SPEC_MD_PATTERN = /^planu\/specs\/[^/]+\/spec\.md$/;
|
|
48
|
+
/** Normalizes a spec.md path (absolute or already repo-relative) to a repo-relative,
|
|
49
|
+
* forward-slash path so it can be compared against `git diff` output. */
|
|
50
|
+
export function toRepoRelativePath(specPath, projectPath) {
|
|
51
|
+
if (isAbsolute(specPath) && !projectPath) {
|
|
52
|
+
const normalized = specPath.replace(/\\/g, '/');
|
|
53
|
+
const specsIndex = normalized.lastIndexOf('planu/specs/');
|
|
54
|
+
return specsIndex === -1 ? normalized : normalized.slice(specsIndex);
|
|
55
|
+
}
|
|
56
|
+
const relativePath = isAbsolute(specPath) && projectPath ? relative(projectPath, specPath) : specPath;
|
|
57
|
+
return relativePath.replace(/\\/g, '/').replace(/^(\.\/)+/, '');
|
|
58
|
+
}
|
|
59
|
+
/** Best-effort `git diff --name-status <mergeBase>...HEAD`; never throws. */
|
|
39
60
|
async function computeChangedFilesFromGit(projectPath, exec, baseBranch) {
|
|
40
61
|
try {
|
|
41
62
|
const mergeBaseOut = await exec('git', ['merge-base', 'HEAD', baseBranch], {
|
|
@@ -45,13 +66,20 @@ async function computeChangedFilesFromGit(projectPath, exec, baseBranch) {
|
|
|
45
66
|
if (!mergeBase) {
|
|
46
67
|
return [];
|
|
47
68
|
}
|
|
48
|
-
const diffOut = await exec('git', ['diff', '--name-
|
|
69
|
+
const diffOut = await exec('git', ['diff', '--name-status', `${mergeBase}...HEAD`], {
|
|
49
70
|
cwd: projectPath,
|
|
50
71
|
});
|
|
51
72
|
return diffOut
|
|
52
73
|
.split('\n')
|
|
53
74
|
.map((line) => line.trim())
|
|
54
|
-
.filter((line) => line.length > 0)
|
|
75
|
+
.filter((line) => line.length > 0)
|
|
76
|
+
.map((line) => {
|
|
77
|
+
const fields = line.split('\t');
|
|
78
|
+
const path = fields[fields.length - 1] ?? '';
|
|
79
|
+
const status = (fields[0] ?? '').startsWith('A') ? 'Added' : 'Other';
|
|
80
|
+
return { status, path };
|
|
81
|
+
})
|
|
82
|
+
.filter((entry) => entry.path.length > 0);
|
|
55
83
|
}
|
|
56
84
|
catch (error) {
|
|
57
85
|
/* reliability-optional: EVIDENCE_AUTOFILL_GIT_DIFF — falls back to ## Files ownership */
|
|
@@ -59,6 +87,18 @@ async function computeChangedFilesFromGit(projectPath, exec, baseBranch) {
|
|
|
59
87
|
return [];
|
|
60
88
|
}
|
|
61
89
|
}
|
|
90
|
+
/** Drops Planu bookkeeping paths, this spec's own spec.md, and newly Added other-spec
|
|
91
|
+
* spec.md files — the diff still surfaces unowned src/ paths and Modified other-spec
|
|
92
|
+
* contracts so the done drift gate can flag genuine scope drift. */
|
|
93
|
+
function excludeBookkeepingChanges(entries, ownSpecMdPath) {
|
|
94
|
+
const bookkeeping = new Set(PLANU_BOOKKEEPING_FILES);
|
|
95
|
+
const kept = entries
|
|
96
|
+
.filter((entry) => !bookkeeping.has(entry.path))
|
|
97
|
+
.filter((entry) => entry.path !== ownSpecMdPath)
|
|
98
|
+
.filter((entry) => !(entry.status === 'Added' && OTHER_SPEC_MD_PATTERN.test(entry.path)))
|
|
99
|
+
.map((entry) => entry.path);
|
|
100
|
+
return [...new Set(kept)];
|
|
101
|
+
}
|
|
62
102
|
function filterExistingRepoFiles(projectPath, paths) {
|
|
63
103
|
return paths.filter((path) => {
|
|
64
104
|
if (isAbsolute(path)) {
|
|
@@ -111,15 +151,18 @@ export async function autofillTraceabilityMatrix(args) {
|
|
|
111
151
|
const scenarios = parseFrontmatterScenarios(args.specBody);
|
|
112
152
|
const exec = args.exec ?? defaultExec;
|
|
113
153
|
const baseBranch = args.baseBranch ?? 'main';
|
|
114
|
-
const
|
|
154
|
+
const gitEntries = args.projectPath
|
|
115
155
|
? await computeChangedFilesFromGit(args.projectPath, exec, baseBranch)
|
|
116
156
|
: [];
|
|
157
|
+
const gitChangedFiles = excludeBookkeepingChanges(gitEntries, args.ownSpecMdPath);
|
|
117
158
|
const ownership = extractCanonicalFileOwnership(args.specBody);
|
|
118
159
|
const ownershipFiles = [...ownership.toCreate, ...ownership.toModify, ...ownership.toTest];
|
|
119
160
|
const rawChangedFiles = gitChangedFiles.length > 0 ? gitChangedFiles : ownershipFiles;
|
|
120
|
-
const changedFiles =
|
|
121
|
-
|
|
122
|
-
|
|
161
|
+
const changedFiles = [
|
|
162
|
+
...new Set(args.projectPath
|
|
163
|
+
? filterExistingRepoFiles(args.projectPath, rawChangedFiles)
|
|
164
|
+
: rawChangedFiles),
|
|
165
|
+
];
|
|
123
166
|
const { validationEvidence, reviewerEvidence } = await readValidationReportSummary(args.projectId, args.specId);
|
|
124
167
|
const rows = criteria.map((acceptanceCriterion, index) => {
|
|
125
168
|
const testPaths = scenarios[index]?.tests?.map((test) => test.path) ?? [];
|
|
@@ -2,5 +2,6 @@ import type { EvidenceGateIssue, SpecEvidenceIndex } from '../../types/index.js'
|
|
|
2
2
|
export declare function checkDoneDriftContract(args: {
|
|
3
3
|
index: SpecEvidenceIndex;
|
|
4
4
|
approvedScopePaths: readonly string[];
|
|
5
|
+
ownSpecMdPath?: string;
|
|
5
6
|
}): EvidenceGateIssue[];
|
|
6
7
|
//# sourceMappingURL=done-drift.d.ts.map
|
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
import { normalizeChangedFilePath } from '../handoff-packager.js';
|
|
2
|
+
import { PLANU_BOOKKEEPING_FILES } from '../evidence-gates/evidence-autofill.js';
|
|
2
3
|
function normalizedChangedFile(value) {
|
|
3
4
|
const normalized = normalizeChangedFilePath(value);
|
|
4
5
|
return normalized.status === 'valid' ? normalized.path : null;
|
|
5
6
|
}
|
|
7
|
+
function buildNeverDriftPaths(ownSpecMdPath) {
|
|
8
|
+
const neverDriftPaths = new Set(PLANU_BOOKKEEPING_FILES);
|
|
9
|
+
const normalizedOwnSpecMdPath = ownSpecMdPath ? normalizedChangedFile(ownSpecMdPath) : null;
|
|
10
|
+
if (normalizedOwnSpecMdPath) {
|
|
11
|
+
neverDriftPaths.add(normalizedOwnSpecMdPath);
|
|
12
|
+
}
|
|
13
|
+
return neverDriftPaths;
|
|
14
|
+
}
|
|
15
|
+
function findUnapprovedChangedFiles(index, approved, neverDriftPaths) {
|
|
16
|
+
return index.criteria.flatMap((entry) => {
|
|
17
|
+
const hasScopeAmendment = entry.evidence.some((record) => record.kind === 'reviewer' && /scope amendment|approved scope/i.test(record.value));
|
|
18
|
+
if (hasScopeAmendment) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
return entry.evidence.flatMap((record) => {
|
|
22
|
+
if (record.kind !== 'changed-file' ||
|
|
23
|
+
(record.status !== 'valid' && record.status !== 'missing')) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
const normalized = normalizedChangedFile(record.value);
|
|
27
|
+
if (normalized && neverDriftPaths.has(normalized)) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return normalized && approved.has(normalized)
|
|
31
|
+
? []
|
|
32
|
+
: [`${entry.criterion}: ${normalized ?? 'invalid changed-file path'}`];
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
6
36
|
export function checkDoneDriftContract(args) {
|
|
7
37
|
const issues = [];
|
|
8
38
|
const uncovered = args.index.criteria.filter((entry) => {
|
|
@@ -39,22 +69,8 @@ export function checkDoneDriftContract(args) {
|
|
|
39
69
|
return normalized ? [normalized] : [];
|
|
40
70
|
});
|
|
41
71
|
const approved = new Set(approvedScopePaths);
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
if (hasScopeAmendment) {
|
|
45
|
-
return [];
|
|
46
|
-
}
|
|
47
|
-
return entry.evidence.flatMap((record) => {
|
|
48
|
-
if (record.kind !== 'changed-file' ||
|
|
49
|
-
(record.status !== 'valid' && record.status !== 'missing')) {
|
|
50
|
-
return [];
|
|
51
|
-
}
|
|
52
|
-
const normalized = normalizedChangedFile(record.value);
|
|
53
|
-
return normalized && approved.has(normalized)
|
|
54
|
-
? []
|
|
55
|
-
: [`${entry.criterion}: ${normalized ?? 'invalid changed-file path'}`];
|
|
56
|
-
});
|
|
57
|
-
});
|
|
72
|
+
const neverDriftPaths = buildNeverDriftPaths(args.ownSpecMdPath);
|
|
73
|
+
const unapproved = findUnapprovedChangedFiles(args.index, approved, neverDriftPaths);
|
|
58
74
|
if (unapproved.length > 0) {
|
|
59
75
|
const approvedHint = approvedScopePaths.length > 0
|
|
60
76
|
? ` Approved canonical paths: ${approvedScopePaths.join(', ')}.`
|
|
@@ -11,7 +11,7 @@ import { resolveStorageLayout } from '../../storage/storage-layout.js';
|
|
|
11
11
|
import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
|
|
12
12
|
import { createValidationReceiptAuthority, ensureValidationIssuerKey, issueValidationReceipt, LOCAL_VALIDATION_RECEIPT_ISSUER, preflightValidationReceiptSigner, } from '../validation/validation-receipt.js';
|
|
13
13
|
import { appendArtifact, readArtifact } from '../handoff-artifacts/io.js';
|
|
14
|
-
import { assertValidationFreshnessBarrier, beginValidationFreshnessBarrier, bindValidationFreshnessLease, closeValidationFreshnessLease, rebaselineValidationFreshnessLeaseAfterRecompute, } from '../validation/validation-freshness.js';
|
|
14
|
+
import { assertValidationFreshnessBarrier, beginValidationFreshnessBarrier, beginValidationFreshnessPublicationWindow, bindValidationFreshnessLease, closeValidationFreshnessLease, rebaselineValidationFreshnessLeaseAfterRecompute, } from '../validation/validation-freshness.js';
|
|
15
15
|
import { recoverValidateJobs } from './validate-job-recovery.js';
|
|
16
16
|
import { getRuntimePolicy } from '../runtime-policy.js';
|
|
17
17
|
import { isValidateJob, parseValidatePayload, rehydrateValidationPayload, } from './validate-job-payload.js';
|
|
@@ -664,62 +664,69 @@ export class ValidateJobExecutor {
|
|
|
664
664
|
policy.receiptCheckpointResultMaxBytes,
|
|
665
665
|
};
|
|
666
666
|
}
|
|
667
|
+
// eslint-disable-next-line max-lines-per-function -- publication window and the double freshness assert share one auditable receipt-issuance boundary
|
|
667
668
|
async issueReceipt(identity, payload, checkpoint, publicationLease, fencingToken, signal) {
|
|
668
669
|
const receiptBindings = checkpoint.receiptInput.bindings;
|
|
669
|
-
|
|
670
|
-
signal.throwIfAborted();
|
|
671
|
-
}
|
|
672
|
-
if (!(await assertValidationFreshnessBarrier(publicationLease, receiptBindings))) {
|
|
673
|
-
throw new Error('[Planu] Validation inputs changed before receipt publication');
|
|
674
|
-
}
|
|
675
|
-
const database = new RuntimeDatabase({ path: resolveStorageLayout().runtimeDatabase });
|
|
670
|
+
const endPublicationWindow = beginValidationFreshnessPublicationWindow(publicationLease);
|
|
676
671
|
try {
|
|
677
|
-
const signingKeyReference = await ensureValidationIssuerKey({
|
|
678
|
-
projectId: identity.projectId,
|
|
679
|
-
issuerId: LOCAL_VALIDATION_RECEIPT_ISSUER,
|
|
680
|
-
});
|
|
681
|
-
signal.throwIfAborted();
|
|
682
|
-
const { store } = createValidationReceiptAuthority({
|
|
683
|
-
database,
|
|
684
|
-
workspaceId: identity.workspaceId,
|
|
685
|
-
projectId: identity.projectId,
|
|
686
|
-
issuerId: LOCAL_VALIDATION_RECEIPT_ISSUER,
|
|
687
|
-
authorizePersistence: (persistenceDatabase) => {
|
|
688
|
-
persistenceDatabase.assertActiveJobLease({
|
|
689
|
-
id: identity.operationId,
|
|
690
|
-
projectId: identity.projectId,
|
|
691
|
-
workspaceId: identity.workspaceId,
|
|
692
|
-
workerId: this.workerId,
|
|
693
|
-
fencingToken,
|
|
694
|
-
leaseMs: this.workerTimingPolicy().workerLeaseMs,
|
|
695
|
-
now: new Date().toISOString(),
|
|
696
|
-
});
|
|
697
|
-
},
|
|
698
|
-
});
|
|
699
|
-
const receipt = await issueValidationReceipt(checkpoint.receiptInput, {
|
|
700
|
-
issuerId: LOCAL_VALIDATION_RECEIPT_ISSUER,
|
|
701
|
-
signingKeyReference,
|
|
702
|
-
store,
|
|
703
|
-
});
|
|
704
672
|
if (executionAborted(signal)) {
|
|
705
673
|
signal.throwIfAborted();
|
|
706
674
|
}
|
|
707
675
|
if (!(await assertValidationFreshnessBarrier(publicationLease, receiptBindings))) {
|
|
708
|
-
|
|
709
|
-
throw new Error('[Planu] Validation inputs changed during receipt publication');
|
|
676
|
+
throw new Error('[Planu] Validation inputs changed before receipt publication');
|
|
710
677
|
}
|
|
711
|
-
const
|
|
712
|
-
let enrichedReportSha;
|
|
678
|
+
const database = new RuntimeDatabase({ path: resolveStorageLayout().runtimeDatabase });
|
|
713
679
|
try {
|
|
714
|
-
|
|
680
|
+
const signingKeyReference = await ensureValidationIssuerKey({
|
|
681
|
+
projectId: identity.projectId,
|
|
682
|
+
issuerId: LOCAL_VALIDATION_RECEIPT_ISSUER,
|
|
683
|
+
});
|
|
684
|
+
signal.throwIfAborted();
|
|
685
|
+
const { store } = createValidationReceiptAuthority({
|
|
686
|
+
database,
|
|
687
|
+
workspaceId: identity.workspaceId,
|
|
688
|
+
projectId: identity.projectId,
|
|
689
|
+
issuerId: LOCAL_VALIDATION_RECEIPT_ISSUER,
|
|
690
|
+
authorizePersistence: (persistenceDatabase) => {
|
|
691
|
+
persistenceDatabase.assertActiveJobLease({
|
|
692
|
+
id: identity.operationId,
|
|
693
|
+
projectId: identity.projectId,
|
|
694
|
+
workspaceId: identity.workspaceId,
|
|
695
|
+
workerId: this.workerId,
|
|
696
|
+
fencingToken,
|
|
697
|
+
leaseMs: this.workerTimingPolicy().workerLeaseMs,
|
|
698
|
+
now: new Date().toISOString(),
|
|
699
|
+
});
|
|
700
|
+
},
|
|
701
|
+
});
|
|
702
|
+
const receipt = await issueValidationReceipt(checkpoint.receiptInput, {
|
|
703
|
+
issuerId: LOCAL_VALIDATION_RECEIPT_ISSUER,
|
|
704
|
+
signingKeyReference,
|
|
705
|
+
store,
|
|
706
|
+
});
|
|
707
|
+
if (executionAborted(signal)) {
|
|
708
|
+
signal.throwIfAborted();
|
|
709
|
+
}
|
|
710
|
+
if (!(await assertValidationFreshnessBarrier(publicationLease, receiptBindings))) {
|
|
711
|
+
await store.invalidateCurrentBindings(identity.projectId, payload.bindings.specId);
|
|
712
|
+
throw new Error('[Planu] Validation inputs changed during receipt publication');
|
|
713
|
+
}
|
|
714
|
+
const receiptKey = `validation-receipt:${receipt.receiptId.slice('sha256:'.length)}`;
|
|
715
|
+
let enrichedReportSha;
|
|
716
|
+
try {
|
|
717
|
+
enrichedReportSha = await this.persistReceiptArtifacts(identity, payload, receipt.receiptId, receiptKey);
|
|
718
|
+
}
|
|
719
|
+
catch (error) {
|
|
720
|
+
throw new ReceiptPublicationInterruptedError({ cause: error });
|
|
721
|
+
}
|
|
722
|
+
return buildReceiptResult(checkpoint.result, receipt.receiptId, receiptKey, enrichedReportSha);
|
|
715
723
|
}
|
|
716
|
-
|
|
717
|
-
|
|
724
|
+
finally {
|
|
725
|
+
database.close();
|
|
718
726
|
}
|
|
719
|
-
return buildReceiptResult(checkpoint.result, receipt.receiptId, receiptKey, enrichedReportSha);
|
|
720
727
|
}
|
|
721
728
|
finally {
|
|
722
|
-
|
|
729
|
+
endPublicationWindow();
|
|
723
730
|
}
|
|
724
731
|
}
|
|
725
732
|
async preparePublicationLease(payload, expectedBindings) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-aarch64-apple-darwin",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
"platform": "darwin",
|
|
18
18
|
"arch": "arm64",
|
|
19
19
|
"libc": null,
|
|
20
|
-
"artifactSha256": "
|
|
20
|
+
"artifactSha256": "bdc99fce3b870c27eafdd54b37d2822c37255eb3694c425ad6b651c6f5b97ac8",
|
|
21
21
|
"sbom": {
|
|
22
22
|
"format": "CycloneDX-1.5",
|
|
23
23
|
"path": "planu-core.darwin-arm64.node.sbom.json",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "11343948562c3b7f3bd3c819a0656a2fa9321431e1022850cda9e9ba5320f90c"
|
|
25
25
|
},
|
|
26
26
|
"provenance": {
|
|
27
27
|
"builder": "scripts/build-rust-local.sh",
|
|
28
|
-
"sourceCommit": "
|
|
28
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
29
29
|
"sourceTreeDirty": false,
|
|
30
30
|
"sourceDateEpoch": 1,
|
|
31
31
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -34,6 +34,6 @@
|
|
|
34
34
|
"signature": {
|
|
35
35
|
"algorithm": "Ed25519",
|
|
36
36
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
37
|
-
"value": "
|
|
37
|
+
"value": "VfCh5vWrZxDxMM6pCO1dpKf/FxS8hZDqFZlvpwtTd6GweAYf2mzdaWMZkNA/a6r0y7gzGfUVuzplXQ64t2w3Cg=="
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "bdc99fce3b870c27eafdd54b37d2822c37255eb3694c425ad6b651c6f5b97ac8"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-x86_64-apple-darwin",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
"platform": "darwin",
|
|
18
18
|
"arch": "x64",
|
|
19
19
|
"libc": null,
|
|
20
|
-
"artifactSha256": "
|
|
20
|
+
"artifactSha256": "bae60566a531f74f27a61531acb737a62c0b4d2c5d748cd8619421452c355d5e",
|
|
21
21
|
"sbom": {
|
|
22
22
|
"format": "CycloneDX-1.5",
|
|
23
23
|
"path": "planu-core.darwin-x64.node.sbom.json",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "817d459d6609a5434eb192614d137f2fa63e3fd9908587d05207b584eba246eb"
|
|
25
25
|
},
|
|
26
26
|
"provenance": {
|
|
27
27
|
"builder": "scripts/build-rust-local.sh",
|
|
28
|
-
"sourceCommit": "
|
|
28
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
29
29
|
"sourceTreeDirty": false,
|
|
30
30
|
"sourceDateEpoch": 1,
|
|
31
31
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -34,6 +34,6 @@
|
|
|
34
34
|
"signature": {
|
|
35
35
|
"algorithm": "Ed25519",
|
|
36
36
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
37
|
-
"value": "
|
|
37
|
+
"value": "HYqjCJjOvAVvkaW7hxI5rJ57eE+48Dd58M+y2/+RU+Qt+ddPDofOh1syhVCQmAHb/1IqORN+/sHSFy/bLK/bAg=="
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "bae60566a531f74f27a61531acb737a62c0b4d2c5d748cd8619421452c355d5e"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-aarch64-unknown-linux-gnu",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"platform": "linux",
|
|
17
17
|
"arch": "arm64",
|
|
18
18
|
"libc": "glibc",
|
|
19
|
-
"artifactSha256": "
|
|
19
|
+
"artifactSha256": "6079ee86b8ee1e650cfd2602f039eb28d3d91e15d8377e712eb851b3ec4746c4",
|
|
20
20
|
"sbom": {
|
|
21
21
|
"format": "CycloneDX-1.5",
|
|
22
22
|
"path": "planu-core.linux-arm64-gnu.node.sbom.json",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "c0fd691552bdaa6095d5c8220a3d7e5679d6f38ddc22919a552c0e98ad53d734"
|
|
24
24
|
},
|
|
25
25
|
"provenance": {
|
|
26
26
|
"builder": "scripts/build-rust-local.sh",
|
|
27
|
-
"sourceCommit": "
|
|
27
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
28
28
|
"sourceTreeDirty": false,
|
|
29
29
|
"sourceDateEpoch": 1,
|
|
30
30
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"signature": {
|
|
34
34
|
"algorithm": "Ed25519",
|
|
35
35
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
36
|
-
"value": "
|
|
36
|
+
"value": "85bAzK82CMXtjrkBbdc3D8X+9wN4/tsyeTzr/MZ5BmyWAe1D4jikLwJ4SW+ioyS+dDshLRCUgrUXSIUsjj0PAg=="
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "6079ee86b8ee1e650cfd2602f039eb28d3d91e15d8377e712eb851b3ec4746c4"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-aarch64-unknown-linux-musl",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"platform": "linux",
|
|
17
17
|
"arch": "arm64",
|
|
18
18
|
"libc": "musl",
|
|
19
|
-
"artifactSha256": "
|
|
19
|
+
"artifactSha256": "e6ee0ad20445313dbed5b14cbd5333a49ae08197ba4fa642e7292ff23bcbb2cf",
|
|
20
20
|
"sbom": {
|
|
21
21
|
"format": "CycloneDX-1.5",
|
|
22
22
|
"path": "planu-core.linux-arm64-musl.node.sbom.json",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "e2a76a395f0d058a97fd17388b74530059c4c80800515463480c73849b01659a"
|
|
24
24
|
},
|
|
25
25
|
"provenance": {
|
|
26
26
|
"builder": "scripts/build-rust-local.sh",
|
|
27
|
-
"sourceCommit": "
|
|
27
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
28
28
|
"sourceTreeDirty": false,
|
|
29
29
|
"sourceDateEpoch": 1,
|
|
30
30
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"signature": {
|
|
34
34
|
"algorithm": "Ed25519",
|
|
35
35
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
36
|
-
"value": "
|
|
36
|
+
"value": "LUWtVfzWce5DbAtjGkmxVudiKCoD8sqcxuzz7wG1uUCyrZ8rMN7foWoytKdNdID7if12WlSVvFDME63D9Ls/BA=="
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "e6ee0ad20445313dbed5b14cbd5333a49ae08197ba4fa642e7292ff23bcbb2cf"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-x86_64-unknown-linux-gnu",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"platform": "linux",
|
|
17
17
|
"arch": "x64",
|
|
18
18
|
"libc": "glibc",
|
|
19
|
-
"artifactSha256": "
|
|
19
|
+
"artifactSha256": "b10b9708c07c07e43b9acc098dc7887b4940bedad5e4e85ac4062b554100cd59",
|
|
20
20
|
"sbom": {
|
|
21
21
|
"format": "CycloneDX-1.5",
|
|
22
22
|
"path": "planu-core.linux-x64-gnu.node.sbom.json",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "b05d18430dca3a6fb1ba1c2e493326d2cd2f6072d469721c31088811efb6274d"
|
|
24
24
|
},
|
|
25
25
|
"provenance": {
|
|
26
26
|
"builder": "scripts/build-rust-local.sh",
|
|
27
|
-
"sourceCommit": "
|
|
27
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
28
28
|
"sourceTreeDirty": false,
|
|
29
29
|
"sourceDateEpoch": 1,
|
|
30
30
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"signature": {
|
|
34
34
|
"algorithm": "Ed25519",
|
|
35
35
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
36
|
-
"value": "
|
|
36
|
+
"value": "1R1IPcr3P53ndUQe0CtgdHIKbrMFWNMDTNiPjcabQavBBnisW6crL1EcueYHY+1hiMMcRRX8j3OXCrzteE/wAw=="
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "b10b9708c07c07e43b9acc098dc7887b4940bedad5e4e85ac4062b554100cd59"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-x86_64-unknown-linux-musl",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"platform": "linux",
|
|
17
17
|
"arch": "x64",
|
|
18
18
|
"libc": "musl",
|
|
19
|
-
"artifactSha256": "
|
|
19
|
+
"artifactSha256": "e32cde49858959e41c0df273dcb2e7c49412c4432ae983f358c19c6f8f705796",
|
|
20
20
|
"sbom": {
|
|
21
21
|
"format": "CycloneDX-1.5",
|
|
22
22
|
"path": "planu-core.linux-x64-musl.node.sbom.json",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "2d4f452d04f8d5e536ae26d5e0321d0bc3d61a87b62b4833edd80ed2a6a5e98f"
|
|
24
24
|
},
|
|
25
25
|
"provenance": {
|
|
26
26
|
"builder": "scripts/build-rust-local.sh",
|
|
27
|
-
"sourceCommit": "
|
|
27
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
28
28
|
"sourceTreeDirty": false,
|
|
29
29
|
"sourceDateEpoch": 1,
|
|
30
30
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"signature": {
|
|
34
34
|
"algorithm": "Ed25519",
|
|
35
35
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
36
|
-
"value": "
|
|
36
|
+
"value": "hl7v/J/DAlDB3yKZ6KPCBz78JEXS6/Y77mT7dM3Q5xABC13P6gTFl4/ts6HFQBC/ILPBJAIe+M2jjNVXPTJRAg=="
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "e32cde49858959e41c0df273dcb2e7c49412c4432ae983f358c19c6f8f705796"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-aarch64-pc-windows-msvc",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"platform": "win32",
|
|
17
17
|
"arch": "arm64",
|
|
18
18
|
"libc": null,
|
|
19
|
-
"artifactSha256": "
|
|
19
|
+
"artifactSha256": "abe713832d59d280780993de17bfe271501f3c6e368cc7660fd73cfe448f855b",
|
|
20
20
|
"sbom": {
|
|
21
21
|
"format": "CycloneDX-1.5",
|
|
22
22
|
"path": "planu-core.win32-arm64-msvc.node.sbom.json",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "fedb07ccec7d0db216ee7cf665995024312f4222579437d1b2f4dd99f024f6d9"
|
|
24
24
|
},
|
|
25
25
|
"provenance": {
|
|
26
26
|
"builder": "scripts/build-rust-local.sh",
|
|
27
|
-
"sourceCommit": "
|
|
27
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
28
28
|
"sourceTreeDirty": false,
|
|
29
29
|
"sourceDateEpoch": 1,
|
|
30
30
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"signature": {
|
|
34
34
|
"algorithm": "Ed25519",
|
|
35
35
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
36
|
-
"value": "
|
|
36
|
+
"value": "cvRigJR42Bz/XnqcHBVMdkfCDTUK3468XFQxFJfwA+dgdffXXne/hZYvu2+Qtc5VDPh+VI/gDgy4S+JjNjXIAw=="
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "abe713832d59d280780993de17bfe271501f3c6e368cc7660fd73cfe448f855b"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"cliVersion": "5.3.
|
|
4
|
-
"engineVersion": "5.3.
|
|
5
|
-
"buildId": "1-5.3.
|
|
3
|
+
"cliVersion": "5.3.17",
|
|
4
|
+
"engineVersion": "5.3.17",
|
|
5
|
+
"buildId": "1-5.3.17-x86_64-pc-windows-msvc",
|
|
6
6
|
"protocolAbi": 1,
|
|
7
7
|
"capabilityAbi": 2,
|
|
8
8
|
"nodeApiAbi": 4,
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"platform": "win32",
|
|
17
17
|
"arch": "x64",
|
|
18
18
|
"libc": null,
|
|
19
|
-
"artifactSha256": "
|
|
19
|
+
"artifactSha256": "142bcb2e061e280bf04929920bd88189ad37b14913f39bdd499bf45e287a53eb",
|
|
20
20
|
"sbom": {
|
|
21
21
|
"format": "CycloneDX-1.5",
|
|
22
22
|
"path": "planu-core.win32-x64-msvc.node.sbom.json",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "e2345850af3b261c8eac493694d218e9b770c1deeac3131bf62e55655054b29f"
|
|
24
24
|
},
|
|
25
25
|
"provenance": {
|
|
26
26
|
"builder": "scripts/build-rust-local.sh",
|
|
27
|
-
"sourceCommit": "
|
|
27
|
+
"sourceCommit": "903b141393635e71607722637a08977e153b8b56",
|
|
28
28
|
"sourceTreeDirty": false,
|
|
29
29
|
"sourceDateEpoch": 1,
|
|
30
30
|
"rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"signature": {
|
|
34
34
|
"algorithm": "Ed25519",
|
|
35
35
|
"keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
|
|
36
|
-
"value": "
|
|
36
|
+
"value": "IQNeo8h8MLaX/wTJMVV3zdR1F1gX7oV9gLw58botIZo4c/OKtyXpiTQ3iRhXu/hpNQ1rs+hSb7C0AWCt+u6nAA=="
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"version": 1,
|
|
5
5
|
"metadata": {
|
|
6
6
|
"component": {
|
|
7
|
-
"bom-ref": "pkg:cargo/planu-core@5.3.
|
|
7
|
+
"bom-ref": "pkg:cargo/planu-core@5.3.17",
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "planu-core",
|
|
10
|
-
"version": "5.3.
|
|
10
|
+
"version": "5.3.17",
|
|
11
11
|
"hashes": [
|
|
12
12
|
{
|
|
13
13
|
"alg": "SHA-256",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "142bcb2e061e280bf04929920bd88189ad37b14913f39bdd499bf45e287a53eb"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
"dependsOn": []
|
|
1107
1107
|
},
|
|
1108
1108
|
{
|
|
1109
|
-
"ref": "pkg:cargo/planu-core@5.3.
|
|
1109
|
+
"ref": "pkg:cargo/planu-core@5.3.17",
|
|
1110
1110
|
"dependsOn": [
|
|
1111
1111
|
"pkg:cargo/core-foundation@0.10.1",
|
|
1112
1112
|
"pkg:cargo/hmac@0.12.1",
|
|
@@ -29,6 +29,13 @@ export declare function injectValidationWatchEventForTests(input: {
|
|
|
29
29
|
}): ValidationWatchEventClassification | undefined;
|
|
30
30
|
/** Pause or observe authoritative verification turns without changing watcher topology. */
|
|
31
31
|
export declare function setValidationFreshnessVerificationHookForTests(hook: (() => Promise<void>) | undefined): void;
|
|
32
|
+
/**
|
|
33
|
+
* Mark one exact epoch's receipt publication as in flight. A same-identity
|
|
34
|
+
* resubmission that arrives while the window is open waits for the returned
|
|
35
|
+
* closer before superseding this epoch, instead of closing it mid-publication.
|
|
36
|
+
* Returns a no-op closer once the epoch is no longer the active one.
|
|
37
|
+
*/
|
|
38
|
+
export declare function beginValidationFreshnessPublicationWindow(lease: Pick<ValidationFreshnessLease, 'projectId' | 'specId' | 'epoch'>): () => void;
|
|
32
39
|
/** Start both watchers before snapshotting and invalidate any older receipt immediately. */
|
|
33
40
|
export declare function beginValidationFreshnessBarrier(input: {
|
|
34
41
|
projectId: string;
|
|
@@ -71,6 +71,19 @@ let verificationHookForTests;
|
|
|
71
71
|
function key(projectId, specId) {
|
|
72
72
|
return `${projectId}:${specId}`;
|
|
73
73
|
}
|
|
74
|
+
function noop() {
|
|
75
|
+
/* no-op */
|
|
76
|
+
}
|
|
77
|
+
function raceWithTimeout(promise, timeoutMs) {
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
80
|
+
timer.unref();
|
|
81
|
+
void promise.finally(() => {
|
|
82
|
+
clearTimeout(timer);
|
|
83
|
+
resolve();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
74
87
|
async function invalidateDurably(projectId, specId) {
|
|
75
88
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
76
89
|
try {
|
|
@@ -380,6 +393,29 @@ async function evidenceFingerprint(path) {
|
|
|
380
393
|
}
|
|
381
394
|
return hash.digest('hex');
|
|
382
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Mark one exact epoch's receipt publication as in flight. A same-identity
|
|
398
|
+
* resubmission that arrives while the window is open waits for the returned
|
|
399
|
+
* closer before superseding this epoch, instead of closing it mid-publication.
|
|
400
|
+
* Returns a no-op closer once the epoch is no longer the active one.
|
|
401
|
+
*/
|
|
402
|
+
export function beginValidationFreshnessPublicationWindow(lease) {
|
|
403
|
+
const state = active.get(key(lease.projectId, lease.specId));
|
|
404
|
+
if (state?.epoch !== lease.epoch) {
|
|
405
|
+
return noop;
|
|
406
|
+
}
|
|
407
|
+
let release;
|
|
408
|
+
const window = new Promise((resolve) => {
|
|
409
|
+
release = resolve;
|
|
410
|
+
});
|
|
411
|
+
state.publicationInFlight = window;
|
|
412
|
+
return () => {
|
|
413
|
+
release();
|
|
414
|
+
if (state.publicationInFlight === window) {
|
|
415
|
+
state.publicationInFlight = undefined;
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
}
|
|
383
419
|
/** Start both watchers before snapshotting and invalidate any older receipt immediately. */
|
|
384
420
|
// eslint-disable-next-line max-lines-per-function -- serialized setup and rollback form one auditable ownership boundary
|
|
385
421
|
export async function beginValidationFreshnessBarrier(input) {
|
|
@@ -395,11 +431,16 @@ export async function beginValidationFreshnessBarrier(input) {
|
|
|
395
431
|
try {
|
|
396
432
|
const previous = active.get(identity);
|
|
397
433
|
if (previous) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
434
|
+
if (previous.publicationInFlight) {
|
|
435
|
+
await raceWithTimeout(previous.publicationInFlight, getRuntimePolicy().validation.receiptPublicationDeadlineMs + 1000);
|
|
436
|
+
}
|
|
437
|
+
if (active.get(identity) === previous) {
|
|
438
|
+
await closeValidationFreshnessLease({
|
|
439
|
+
projectId: input.projectId,
|
|
440
|
+
specId: input.specId,
|
|
441
|
+
epoch: previous.epoch,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
403
444
|
}
|
|
404
445
|
await mkdir(input.handoffPath, { recursive: true, mode: 0o700 });
|
|
405
446
|
const initialEvidenceFingerprint = await evidenceFingerprint(input.handoffPath);
|
|
@@ -57,6 +57,7 @@ import { readEvidenceArtifacts } from '../../engine/evidence-gates/artifact-read
|
|
|
57
57
|
import { checkLifecycleEvidenceGate } from '../../engine/evidence-gates/lifecycle-gate.js';
|
|
58
58
|
import { buildSpecEvidenceIndex } from '../../engine/evidence-index/index-builder.js';
|
|
59
59
|
import { checkDoneDriftContract } from '../../engine/evidence-index/done-drift.js';
|
|
60
|
+
import { toRepoRelativePath } from '../../engine/evidence-gates/evidence-autofill.js';
|
|
60
61
|
import { parseGroundedTechnicalPaths } from '../../engine/spec-grounding/contract.js';
|
|
61
62
|
import { extractAcceptanceCriteriaTexts } from '../../engine/spec-format/acceptance-criteria.js';
|
|
62
63
|
import { formatKeyValue } from '../output-formatter.js';
|
|
@@ -168,7 +169,11 @@ export async function checkLifecycleEvidenceTransitionGate(args) {
|
|
|
168
169
|
message: `Approved canonical ownership is invalid: ${[...new Set(safeBlockers)].join(', ')}.`,
|
|
169
170
|
});
|
|
170
171
|
}
|
|
171
|
-
result.issues.push(...checkDoneDriftContract({
|
|
172
|
+
result.issues.push(...checkDoneDriftContract({
|
|
173
|
+
index,
|
|
174
|
+
approvedScopePaths,
|
|
175
|
+
ownSpecMdPath: toRepoRelativePath(args.spec.specPath, args.projectPath),
|
|
176
|
+
}));
|
|
172
177
|
}
|
|
173
178
|
if (result.issues.length === 0) {
|
|
174
179
|
return null;
|
|
@@ -17,7 +17,7 @@ import { withApprovalSpecLock } from '../../storage/approval-operation-lock.js';
|
|
|
17
17
|
import { isLocked, getLock } from '../../storage/spec-lock-store.js';
|
|
18
18
|
import { checkDoneGates, checkComplianceGate, checkApprovedFormatGate, checkSpecReviewGate, deriveDoneReviewDigest, } from './dod-gates.js';
|
|
19
19
|
import { checkLifecycleEvidenceTransitionGate } from './evidence-gate.js';
|
|
20
|
-
import { autofillTraceabilityMatrix } from '../../engine/evidence-gates/evidence-autofill.js';
|
|
20
|
+
import { autofillTraceabilityMatrix, toRepoRelativePath, } from '../../engine/evidence-gates/evidence-autofill.js';
|
|
21
21
|
import { buildStatusResponse, buildDryRunResponse } from './response-builder.js';
|
|
22
22
|
import { recordDoneMetrics, syncSpecFiles, tryReconcile, recordTerminalTransitionEvent, } from './file-sync.js';
|
|
23
23
|
import { appendEntry, getLastHash } from '../../storage/audit-trail-store.js';
|
|
@@ -165,6 +165,7 @@ async function runTraceabilityAutofillGate(args) {
|
|
|
165
165
|
specId: args.specId,
|
|
166
166
|
projectPath: args.projectPath,
|
|
167
167
|
specBody,
|
|
168
|
+
ownSpecMdPath: toRepoRelativePath(args.spec.specPath, args.projectPath),
|
|
168
169
|
});
|
|
169
170
|
if (!result.written) {
|
|
170
171
|
return null;
|
|
@@ -21,6 +21,8 @@ export interface AutofillTraceabilityMatrixArgs {
|
|
|
21
21
|
exec?: EvidenceAutofillExec;
|
|
22
22
|
/** Branch to diff against for changed-files detection. Defaults to `main`. */
|
|
23
23
|
baseBranch?: string;
|
|
24
|
+
/** Repo-relative path of this spec's own spec.md, excluded from changedFiles as lifecycle bookkeeping. */
|
|
25
|
+
ownSpecMdPath?: string;
|
|
24
26
|
}
|
|
25
27
|
export type AutofillTraceabilityMatrixResult = {
|
|
26
28
|
written: true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planu/cli",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.17",
|
|
4
4
|
"description": "Planu — MCP Server for Spec Driven Development with native Rust acceleration for hot paths. Cross-platform (Linux/macOS/Windows, x64/arm64, glibc/musl).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"packageName": "@planu/core"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"@planu/core-darwin-arm64": "5.3.
|
|
39
|
-
"@planu/core-darwin-x64": "5.3.
|
|
40
|
-
"@planu/core-linux-arm64-gnu": "5.3.
|
|
41
|
-
"@planu/core-linux-arm64-musl": "5.3.
|
|
42
|
-
"@planu/core-linux-x64-gnu": "5.3.
|
|
43
|
-
"@planu/core-linux-x64-musl": "5.3.
|
|
44
|
-
"@planu/core-win32-arm64-msvc": "5.3.
|
|
45
|
-
"@planu/core-win32-x64-msvc": "5.3.
|
|
38
|
+
"@planu/core-darwin-arm64": "5.3.17",
|
|
39
|
+
"@planu/core-darwin-x64": "5.3.17",
|
|
40
|
+
"@planu/core-linux-arm64-gnu": "5.3.17",
|
|
41
|
+
"@planu/core-linux-arm64-musl": "5.3.17",
|
|
42
|
+
"@planu/core-linux-x64-gnu": "5.3.17",
|
|
43
|
+
"@planu/core-linux-x64-musl": "5.3.17",
|
|
44
|
+
"@planu/core-win32-arm64-msvc": "5.3.17",
|
|
45
|
+
"@planu/core-win32-x64-msvc": "5.3.17"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|
|
48
48
|
"node": ">=24.0.0"
|
package/planu-native.json
CHANGED
package/planu-plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dev.planu.cli",
|
|
3
3
|
"displayName": "Planu — Spec Driven Development",
|
|
4
4
|
"description": "Manage software specs, estimations, and autonomous SDD workflows. Language-agnostic MCP server for Claude Code.",
|
|
5
|
-
"version": "5.3.
|
|
5
|
+
"version": "5.3.17",
|
|
6
6
|
"icon": "assets/plugin/icon.svg",
|
|
7
7
|
"command": ["npx", "@planu/cli@latest"],
|
|
8
8
|
"packageName": "@planu/cli",
|