archgen-skill 0.0.5 → 0.0.6
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 +12 -6
- package/bin/archgen.mjs +22 -5
- package/lib/block.js +1 -1
- package/lib/bootstrap.js +103 -0
- package/lib/doctor.js +45 -2
- package/lib/init.js +32 -3
- package/lib/install.js +20 -1
- package/lib/mcp-server.js +159 -0
- package/lib/migrations/001-stamp-provenance.mjs +3 -3
- package/lib/spawn-npm.js +54 -0
- package/lib/store.js +75 -5
- package/lib/uninstall-project.js +16 -3
- package/lib/version.js +11 -3
- package/package.json +3 -3
- package/vendor/skills/archgen/SKILL.md +363 -213
- package/vendor/skills/archgen/archgen.config.json +1 -1
- package/vendor/skills/archgen/references/code-standards.md +2 -2
- package/vendor/skills/archgen/assets/mcp-template.json +0 -42
- package/vendor/skills/archgen/assets/skill-registry.json +0 -24
- package/vendor/skills/archgen/references/artifact-templates.md +0 -406
- package/vendor/skills/archgen/references/interview.md +0 -275
- package/vendor/skills/archgen/references/mcp-and-skills.md +0 -117
- package/vendor/skills/archgen/references/orchestration.md +0 -292
- package/vendor/skills/archgen/references/platforms.md +0 -138
- package/vendor/skills/archgen/scripts/doc-index.mjs +0 -457
- package/vendor/skills/archgen/scripts/impact.mjs +0 -77
- package/vendor/skills/archgen/scripts/lib/graph.mjs +0 -222
- package/vendor/skills/archgen/scripts/lib/plan-coverage.mjs +0 -32
- package/vendor/skills/archgen/scripts/lib/scope.mjs +0 -65
- package/vendor/skills/archgen/scripts/lib/yaml.mjs +0 -492
- package/vendor/skills/archgen/scripts/next-tasks.mjs +0 -55
- package/vendor/skills/archgen/scripts/plan-graph.mjs +0 -329
- package/vendor/skills/archgen/scripts/set-status.mjs +0 -82
- package/vendor/skills/archgen/scripts/update-agents.mjs +0 -213
- package/vendor/skills/archgen/scripts/validate.mjs +0 -87
- package/vendor/skills/archgen/scripts/verify-plan.mjs +0 -70
package/lib/store.js
CHANGED
|
@@ -59,6 +59,55 @@ const GUARDED_RELPATHS = new Set(['.claude', '.agents', '.claude/skills', '.agen
|
|
|
59
59
|
*/
|
|
60
60
|
export const DEV_ONLY_RELPATHS = ['scripts/test'];
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Subtrees that the CURRENT packaged skill no longer ships.
|
|
64
|
+
*
|
|
65
|
+
* The skill used to ship a `scripts/` tree (11 scripts + a lib/ folder). It
|
|
66
|
+
* does any more — every capability moved into the archgen MCP server. An
|
|
67
|
+
* existing install still carries that tree, and it is dead weight: nothing
|
|
68
|
+
* reads it, and it makes the store hash as DIVERGED from the packaged skill.
|
|
69
|
+
*
|
|
70
|
+
* Pruning it is a MIGRATION, not a repair: the tree is ours (it shipped in a
|
|
71
|
+
* previous version), so removing it is safe. It is never removed from a store
|
|
72
|
+
* whose packaged skill still ships the same path — the check is always
|
|
73
|
+
* "packaged skill has no such directory".
|
|
74
|
+
*/
|
|
75
|
+
export const OBSOLETE_RELPATHS = ['scripts'];
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The subtrees the packaged skill no longer ships that are still present in
|
|
79
|
+
* an installed tree (report-only — nothing is touched).
|
|
80
|
+
*
|
|
81
|
+
* @param {string} absRoot the installed skill tree
|
|
82
|
+
* @param {string} packagedRoot the packaged (vendor) skill tree
|
|
83
|
+
* @returns {string[]} the relpaths that are obsolete
|
|
84
|
+
*/
|
|
85
|
+
export function findObsolete(absRoot, packagedRoot) {
|
|
86
|
+
const found = [];
|
|
87
|
+
for (const rel of OBSOLETE_RELPATHS) {
|
|
88
|
+
if (existsSync(join(packagedRoot, ...rel.split('/')))) continue; // still shipped — not obsolete
|
|
89
|
+
if (!existsSync(join(absRoot, ...rel.split('/')))) continue;
|
|
90
|
+
found.push(rel);
|
|
91
|
+
}
|
|
92
|
+
return found;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Remove the subtrees the packaged skill no longer ships.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} absRoot the installed skill tree
|
|
99
|
+
* @param {string} packagedRoot the packaged (vendor) skill tree
|
|
100
|
+
* @returns {string[]} the relpaths actually removed
|
|
101
|
+
*/
|
|
102
|
+
export function pruneObsolete(absRoot, packagedRoot) {
|
|
103
|
+
const removed = [];
|
|
104
|
+
for (const rel of findObsolete(absRoot, packagedRoot)) {
|
|
105
|
+
rmSync(join(absRoot, ...rel.split('/')), { recursive: true, force: true });
|
|
106
|
+
removed.push(rel);
|
|
107
|
+
}
|
|
108
|
+
return removed;
|
|
109
|
+
}
|
|
110
|
+
|
|
62
111
|
/** True when relpath `r` is (or lives inside) a dev-only excluded subtree. */
|
|
63
112
|
function isDevOnlyRelPath(r) {
|
|
64
113
|
for (const prefix of DEV_ONLY_RELPATHS) {
|
|
@@ -136,17 +185,38 @@ function byName(a, b) {
|
|
|
136
185
|
export function hashDir(dir, opts = {}) {
|
|
137
186
|
const ignore = new Set([VERSION_FILE, ...(opts.ignore ?? [])]);
|
|
138
187
|
const hash = createHash('sha256');
|
|
139
|
-
|
|
188
|
+
// A directory contributes its marker ONLY when its subtree contributes
|
|
189
|
+
// something. Without this, a directory holding nothing but excluded
|
|
190
|
+
// dev-only content hashed a 'd <rel>' marker on one side and nothing on the
|
|
191
|
+
// other — the two trees then read as divergent even though they are
|
|
192
|
+
// identical once the exclusions are applied.
|
|
193
|
+
//
|
|
194
|
+
// File contents are hashed as BYTES, never as strings: a lossy string
|
|
195
|
+
// round-trip would change the digest for any non-UTF-8 file.
|
|
196
|
+
const walk = (abs, rel) => {
|
|
140
197
|
const entries = readdirSync(abs, { withFileTypes: true }).sort((a, b) => byName(a.name, b.name));
|
|
198
|
+
const chunks = [];
|
|
141
199
|
for (const ent of entries) {
|
|
142
200
|
const r = rel ? rel + '/' + ent.name : ent.name;
|
|
143
201
|
if (ignore.has(r) || isDevOnlyRelPath(r)) continue;
|
|
144
202
|
const p = join(abs, ent.name);
|
|
145
|
-
if (ent.isSymbolicLink())
|
|
146
|
-
|
|
147
|
-
else
|
|
203
|
+
if (ent.isSymbolicLink()) {
|
|
204
|
+
chunks.push(Buffer.from('l ' + r + ' -> ' + readlinkSync(p) + '\n'));
|
|
205
|
+
} else if (ent.isDirectory()) {
|
|
206
|
+
const sub = walk(p, r);
|
|
207
|
+
if (sub.length > 0) {
|
|
208
|
+
chunks.push(Buffer.from('d ' + r + '\n'));
|
|
209
|
+
chunks.push(...sub);
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
chunks.push(Buffer.from('f ' + r + '\0'));
|
|
213
|
+
chunks.push(readFileSync(p));
|
|
214
|
+
chunks.push(Buffer.from('\n'));
|
|
215
|
+
}
|
|
148
216
|
}
|
|
149
|
-
|
|
217
|
+
return chunks;
|
|
218
|
+
};
|
|
219
|
+
for (const chunk of walk(dir, '')) hash.update(chunk);
|
|
150
220
|
return hash.digest('hex');
|
|
151
221
|
}
|
|
152
222
|
|
package/lib/uninstall-project.js
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
rmIfExists,
|
|
21
21
|
} from './store.js';
|
|
22
22
|
import { resolveSkillSource } from './init.js';
|
|
23
|
+
import { uninstallMcp } from './mcp-server.js';
|
|
23
24
|
|
|
24
25
|
function lstatSafe(p) {
|
|
25
26
|
try { return lstatSync(p); } catch { return null; }
|
|
@@ -33,7 +34,8 @@ function relJoin(rel) {
|
|
|
33
34
|
* @param {string} projectDir project root to clean
|
|
34
35
|
* @param {string} packageRoot dir containing this CLI package (vendor source)
|
|
35
36
|
* @returns {{root: string, linkRemoved: boolean, strippedBlocks: string[],
|
|
36
|
-
* storeRemoved: boolean, storeKept: boolean, manifestRemoved: boolean,
|
|
37
|
+
* storeRemoved: boolean, storeKept: boolean, manifestRemoved: boolean,
|
|
38
|
+
* mcpRemoved: string[], warnings: string[]}}
|
|
37
39
|
*/
|
|
38
40
|
export function uninstallProject(projectDir, packageRoot) {
|
|
39
41
|
const root = resolve(projectDir);
|
|
@@ -86,10 +88,21 @@ export function uninstallProject(projectDir, packageRoot) {
|
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
// 4.
|
|
91
|
+
// 4. MCP server entries — remove ONLY the archgen entries this install
|
|
92
|
+
// wrote (the MCP server keeps a manifest of exactly what it created, so
|
|
93
|
+
// unrelated servers in the same config are never touched).
|
|
94
|
+
let mcpRemoved = [];
|
|
95
|
+
const mcp = uninstallMcp({ projectRoot: root });
|
|
96
|
+
if (mcp.report?.removed?.length) {
|
|
97
|
+
mcpRemoved = mcp.report.removed;
|
|
98
|
+
} else if (mcp.detail) {
|
|
99
|
+
warnings.push(`archgen MCP entries not removed: ${mcp.detail}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 5. Manifest file — then prune .archgen only if nothing else remains
|
|
90
103
|
// (feature folders / backups keep it alive).
|
|
91
104
|
const manifestRemoved = rmIfExists(join(root, relJoin(MANIFEST_REL)));
|
|
92
105
|
if (manifestRemoved) pruneEmptyParents(root, dirname(MANIFEST_REL));
|
|
93
106
|
|
|
94
|
-
return { root, linkRemoved, strippedBlocks, storeRemoved, storeKept, manifestRemoved, warnings };
|
|
107
|
+
return { root, linkRemoved, strippedBlocks, storeRemoved, storeKept, manifestRemoved, mcpRemoved, warnings };
|
|
95
108
|
}
|
package/lib/version.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// version.js — semver compare + npm registry lookup (zero deps).
|
|
2
2
|
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { npmInvocation } from './spawn-npm.js';
|
|
3
4
|
|
|
4
5
|
export function parseSemver(v) {
|
|
5
6
|
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(String(v ?? '').trim());
|
|
@@ -17,7 +18,14 @@ export function compareSemver(a, b) {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export function fetchLatestVersion(pkg) {
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
|
|
21
|
+
// Registry-verified constant in every caller; refuse anything else outright.
|
|
22
|
+
if (!/^[a-z0-9@][a-z0-9._/-]*$/i.test(String(pkg ?? ''))) return null;
|
|
23
|
+
try {
|
|
24
|
+
const inv = npmInvocation(['view', String(pkg), 'version']);
|
|
25
|
+
const r = spawnSync(inv.command, inv.args, { encoding: 'utf8', timeout: 15000, shell: inv.shell });
|
|
26
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
27
|
+
return r.stdout.trim().split(/\r?\n/).pop() || null;
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
23
31
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "archgen-skill",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Architecture generation & autonomous task execution for coding agents - conversational requirements in, dependency-ordered tasks out, executed wave-by-wave with verifier gates. Works with Claude Code, OpenCode, Cursor, Codex, Gemini CLI and any agentskills.io harness.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"README.md"
|
|
15
15
|
],
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
17
|
+
"node": ">=20"
|
|
18
18
|
},
|
|
19
19
|
"keywords": [
|
|
20
20
|
"ai",
|
|
@@ -44,6 +44,6 @@
|
|
|
44
44
|
"sync:check": "node scripts/sync-config.mjs --check",
|
|
45
45
|
"sync": "node scripts/sync-config.mjs && node scripts/sync-vendor.mjs",
|
|
46
46
|
"prepublishOnly": "node scripts/sync-config.mjs && node scripts/sync-vendor.mjs",
|
|
47
|
-
"test": "node --test test/*.test.mjs"
|
|
47
|
+
"test": "ARCHGEN_CODEGRAPH=0 node --test test/*.test.mjs"
|
|
48
48
|
}
|
|
49
49
|
}
|