docguard-cli 0.40.0 → 0.40.2
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/cli/release-pr-policy.mjs +107 -0
- package/extensions/spec-kit-docguard/extension.yml +1 -1
- package/extensions/spec-kit-docguard/skills/docguard-fix/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-guard/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-review/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-score/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/skills/docguard-sync/SKILL.md +2 -2
- package/extensions/spec-kit-docguard/templates/github-workflows/docguard-autofix.yml +1 -1
- package/extensions/spec-kit-docguard/templates/github-workflows/docguard-guard.yml +1 -1
- package/package.json +1 -1
- package/templates/ci/github-actions.yml +1 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure policy for privileged release pull-request evaluation.
|
|
3
|
+
*
|
|
4
|
+
* @implements docguard.tokenless-scheduled-releases#FR-005
|
|
5
|
+
* @implements docguard.tokenless-scheduled-releases#FR-006
|
|
6
|
+
* @implements docguard.tokenless-scheduled-releases#FR-007
|
|
7
|
+
* @implements docguard.tokenless-scheduled-releases#FR-008
|
|
8
|
+
* @implements docguard.tokenless-scheduled-releases#FR-011
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const REQUIRED_RELEASE_JOBS = Object.freeze([
|
|
12
|
+
'test (18)',
|
|
13
|
+
'test (20)',
|
|
14
|
+
'test (22)',
|
|
15
|
+
'test (24)',
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
export const RELEASE_PATH_ALLOWLIST = /^(package(-lock)?\.json|pyproject\.toml|server\.json|CHANGELOG\.md|templates\/ci\/github-actions\.yml|extensions\/spec-kit-docguard\/(extension\.yml|templates\/github-workflows\/(docguard-guard|docguard-autofix)\.yml|skills\/docguard-(fix|guard|review|score|sync)\/SKILL\.md)|\.agent\/skills\/docguard-(fix|guard|review|score|sync)\/SKILL\.md)$/;
|
|
19
|
+
|
|
20
|
+
const VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
21
|
+
|
|
22
|
+
function parseVersion(value) {
|
|
23
|
+
const match = VERSION_PATTERN.exec(value || '');
|
|
24
|
+
return match ? match.slice(1).map(Number) : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function nextAllowed(base, candidate) {
|
|
28
|
+
if (!base || !candidate || candidate[0] !== base[0]) return false;
|
|
29
|
+
const nextPatch = candidate[1] === base[1] && candidate[2] === base[2] + 1;
|
|
30
|
+
const nextMinor = candidate[1] === base[1] + 1 && candidate[2] === 0;
|
|
31
|
+
return nextPatch || nextMinor;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function parseJson(text, label, errors) {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(text);
|
|
37
|
+
} catch {
|
|
38
|
+
errors.push(`${label}: invalid JSON`);
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function extractVersions(files, errors) {
|
|
44
|
+
const pkg = parseJson(files.packageJson, 'package.json', errors);
|
|
45
|
+
const lock = parseJson(files.packageLock, 'package-lock.json', errors);
|
|
46
|
+
const server = parseJson(files.server, 'server.json', errors);
|
|
47
|
+
const python = /^version\s*=\s*["']([^"']+)["']/m.exec(files.pyproject || '')?.[1];
|
|
48
|
+
const extension = /^ version:\s*["']([^"']+)["']/m.exec(files.extension || '')?.[1];
|
|
49
|
+
return {
|
|
50
|
+
package: pkg.version,
|
|
51
|
+
lock: lock.version,
|
|
52
|
+
lockPackage: lock.packages?.['']?.version,
|
|
53
|
+
python,
|
|
54
|
+
server: server.version,
|
|
55
|
+
extension,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function evaluateReleaseCandidate(input) {
|
|
60
|
+
const errors = [];
|
|
61
|
+
const branchMatch = /^release\/v(\d+\.\d+\.\d+)$/.exec(input.headRef || '');
|
|
62
|
+
const titleMatch = /^release: v(\d+\.\d+\.\d+) — automated weekly batch$/.exec(input.title || '');
|
|
63
|
+
const branchVersion = branchMatch?.[1];
|
|
64
|
+
const titleVersion = titleMatch?.[1];
|
|
65
|
+
|
|
66
|
+
if (input.headRepo !== input.repository) errors.push('head repository: mismatch');
|
|
67
|
+
if (input.baseRef !== input.defaultBranch) errors.push('base branch: mismatch');
|
|
68
|
+
if (input.author !== 'github-actions[bot]') errors.push('author: must be github-actions[bot]');
|
|
69
|
+
if (!branchVersion) errors.push('head branch: invalid release branch');
|
|
70
|
+
if (!titleVersion) errors.push('title: invalid automated release title');
|
|
71
|
+
|
|
72
|
+
const unexpectedPaths = (input.paths || []).filter(path => !RELEASE_PATH_ALLOWLIST.test(path));
|
|
73
|
+
if (unexpectedPaths.length) errors.push(`paths: unexpected ${unexpectedPaths.join(', ')}`);
|
|
74
|
+
if (!(input.paths || []).includes('package.json')) errors.push('paths: package.json is required');
|
|
75
|
+
if (!(input.paths || []).includes('CHANGELOG.md')) errors.push('paths: CHANGELOG.md is required');
|
|
76
|
+
|
|
77
|
+
const versions = extractVersions(input.files || {}, errors);
|
|
78
|
+
const candidateVersion = versions.package;
|
|
79
|
+
for (const [surface, value] of Object.entries(versions)) {
|
|
80
|
+
if (!value) errors.push(`${surface}: missing version`);
|
|
81
|
+
else if (candidateVersion && value !== candidateVersion) errors.push(`${surface}: version mismatch`);
|
|
82
|
+
}
|
|
83
|
+
if (branchVersion && candidateVersion && branchVersion !== candidateVersion) errors.push('branch: version mismatch');
|
|
84
|
+
if (titleVersion && candidateVersion && titleVersion !== candidateVersion) errors.push('title: version mismatch');
|
|
85
|
+
if (!nextAllowed(parseVersion(input.baseVersion), parseVersion(candidateVersion))) {
|
|
86
|
+
errors.push('version: must be the next patch or next minor');
|
|
87
|
+
}
|
|
88
|
+
if (input.tagExists) errors.push('tag: release already exists');
|
|
89
|
+
|
|
90
|
+
return { ok: errors.length === 0, version: candidateVersion || branchVersion || null, errors };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function evaluateReleaseJobs(jobs) {
|
|
94
|
+
const errors = [];
|
|
95
|
+
for (const name of REQUIRED_RELEASE_JOBS) {
|
|
96
|
+
const matches = (jobs || []).filter(job => job.name === name);
|
|
97
|
+
if (matches.length !== 1) {
|
|
98
|
+
errors.push(`${name}: expected one job, found ${matches.length}`);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const [job] = matches;
|
|
102
|
+
if (job.status !== 'completed' || job.conclusion !== 'success') {
|
|
103
|
+
errors.push(`${name}: ${job.status || 'unknown'}/${job.conclusion || 'unknown'}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { ok: errors.length === 0, errors };
|
|
107
|
+
}
|
|
@@ -3,7 +3,7 @@ schema_version: "1.0"
|
|
|
3
3
|
extension:
|
|
4
4
|
id: "docguard"
|
|
5
5
|
name: "DocGuard — CDD Enforcement"
|
|
6
|
-
version: "0.40.
|
|
6
|
+
version: "0.40.2"
|
|
7
7
|
description: "Canonical-Driven Development enforcement as a true spec-kit extension. LLM-first design with automated validators, 5 AI behavior skills, spec-kit skill chaining, and workflow hooks. One pinned runtime dependency (@babel/parser); pure Node.js otherwise."
|
|
8
8
|
author: "Ricardo Accioly"
|
|
9
9
|
repository: "https://github.com/raccioly/docguard"
|
|
@@ -6,10 +6,10 @@ description: AI-driven documentation repair with structured research workflow, t
|
|
|
6
6
|
compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
|
|
7
7
|
metadata:
|
|
8
8
|
author: docguard
|
|
9
|
-
version: 0.40.
|
|
9
|
+
version: 0.40.2
|
|
10
10
|
source: extensions/spec-kit-docguard/skills/docguard-fix
|
|
11
11
|
---
|
|
12
|
-
<!-- docguard:version: 0.40.
|
|
12
|
+
<!-- docguard:version: 0.40.2 -->
|
|
13
13
|
|
|
14
14
|
# DocGuard Fix Skill
|
|
15
15
|
|
|
@@ -7,10 +7,10 @@ description: Run DocGuard guard validation against Canonical-Driven Development
|
|
|
7
7
|
compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
|
|
8
8
|
metadata:
|
|
9
9
|
author: docguard
|
|
10
|
-
version: 0.40.
|
|
10
|
+
version: 0.40.2
|
|
11
11
|
source: extensions/spec-kit-docguard/skills/docguard-guard
|
|
12
12
|
---
|
|
13
|
-
<!-- docguard:version: 0.40.
|
|
13
|
+
<!-- docguard:version: 0.40.2 -->
|
|
14
14
|
|
|
15
15
|
# DocGuard Guard Skill
|
|
16
16
|
|
|
@@ -6,10 +6,10 @@ description: Cross-document consistency analysis and quality assessment. Perform
|
|
|
6
6
|
compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
|
|
7
7
|
metadata:
|
|
8
8
|
author: docguard
|
|
9
|
-
version: 0.40.
|
|
9
|
+
version: 0.40.2
|
|
10
10
|
source: extensions/spec-kit-docguard/skills/docguard-review
|
|
11
11
|
---
|
|
12
|
-
<!-- docguard:version: 0.40.
|
|
12
|
+
<!-- docguard:version: 0.40.2 -->
|
|
13
13
|
|
|
14
14
|
# DocGuard Review Skill
|
|
15
15
|
|
|
@@ -6,10 +6,10 @@ description: CDD maturity assessment with category-aware improvement roadmap. Ru
|
|
|
6
6
|
compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
|
|
7
7
|
metadata:
|
|
8
8
|
author: docguard
|
|
9
|
-
version: 0.40.
|
|
9
|
+
version: 0.40.2
|
|
10
10
|
source: extensions/spec-kit-docguard/skills/docguard-score
|
|
11
11
|
---
|
|
12
|
-
<!-- docguard:version: 0.40.
|
|
12
|
+
<!-- docguard:version: 0.40.2 -->
|
|
13
13
|
|
|
14
14
|
# DocGuard Score Skill
|
|
15
15
|
|
|
@@ -4,10 +4,10 @@ description: Keep canonical documentation ALWAYS UP TO DATE. Refreshes code-trut
|
|
|
4
4
|
compatibility: Requires DocGuard CLI installed (npm i -g docguard-cli or npx docguard-cli)
|
|
5
5
|
metadata:
|
|
6
6
|
author: docguard
|
|
7
|
-
version: 0.40.
|
|
7
|
+
version: 0.40.2
|
|
8
8
|
source: extensions/spec-kit-docguard/skills/docguard-sync
|
|
9
9
|
---
|
|
10
|
-
<!-- docguard:version: 0.40.
|
|
10
|
+
<!-- docguard:version: 0.40.2 -->
|
|
11
11
|
|
|
12
12
|
# DocGuard Sync Skill
|
|
13
13
|
|
package/package.json
CHANGED