@jstn-sdk/ma 0.1.12 → 0.14.0
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/.codex/agents/Architect.toml +1 -2
- package/.codex/agents/Auditor.toml +1 -2
- package/.codex/agents/Builder.toml +1 -2
- package/.codex/agents/Flow.toml +1 -2
- package/.codex/agents/Sage.toml +1 -2
- package/.codex/agents/Vibe.toml +1 -2
- package/.codex/hooks.json +24 -13
- package/.codex/prompts/enforcement.md +4 -0
- package/.codex/prompts/onboarding.md +6 -1
- package/.codex/prompts/release-rules.md +0 -0
- package/.codex/prompts/skill-contract.md +4 -0
- package/COVERAGE.md +211 -0
- package/DEMO.md +274 -0
- package/LICENSE +0 -0
- package/README.md +132 -656
- package/bin/ma.js +748 -55
- package/data/clone-data.ledger.json +41 -0
- package/data/clone-data.proof.json +50 -0
- package/data/clone-data.rvf +37 -0
- package/docs/README.md +10 -1
- package/docs/autonomous-tasks.md +46 -0
- package/docs/codex-integration.md +16 -0
- package/docs/getting-started.md +62 -22
- package/docs/mcp-setup.md +64 -0
- package/docs/qa/release-issue-gates-0.14.0.json +644 -0
- package/docs/qa/release-readiness-0.1.5.md +1 -1
- package/docs/qa/{release-readiness-0.1.12.md → release-readiness-0.14.0.md} +25 -9
- package/docs/quality.md +24 -0
- package/docs/reference/native-security-playbooks.md +6 -0
- package/docs/reference/native-source-selection.md +6 -0
- package/docs/release-spec.md +39 -10
- package/docs/skills.md +14 -1
- package/index.js +295 -2
- package/mcp/collections.json +23 -6
- package/mcp/fallback.json +0 -0
- package/mcp/local/code-intel.js +179 -41
- package/mcp/local/context.js +180 -0
- package/mcp/local/memory.js +17 -6
- package/mcp/local/quality.js +39 -0
- package/mcp/local/state.js +7 -3
- package/mcp/local/team-run.js +56 -4
- package/mcp/local-capabilities.json +9 -0
- package/mcp/servers.json +24 -0
- package/package.json +29 -4
- package/plugins/meta-architect/.app.json +1 -1
- package/plugins/meta-architect/.codex-plugin/plugin.json +1 -1
- package/plugins/meta-architect/.mcp.json +1 -1
- package/plugins/meta-architect/README.md +8 -1
- package/plugins/meta-architect/obsidian/main.js +534 -0
- package/plugins/meta-architect/obsidian/manifest.json +9 -0
- package/plugins/meta-architect/obsidian/styles.css +7 -0
- package/plugins/meta-architect/skills/arch/SKILL.md +2 -0
- package/plugins/meta-architect/skills/build/SKILL.md +3 -0
- package/plugins/meta-architect/skills/flow/SKILL.md +2 -0
- package/plugins/meta-architect/skills/sage/SKILL.md +2 -0
- package/plugins/meta-architect/skills/sage/references/source-selection.md +8 -0
- package/plugins/meta-architect/skills/vet/SKILL.md +2 -0
- package/plugins/meta-architect/skills/vet/references/security-playbooks.md +7 -0
- package/plugins/meta-architect/skills/vibe/SKILL.md +2 -0
- package/schemas/autonomous-task-queue.schema.json +56 -0
- package/schemas/handoff-packet.schema.json +36 -0
- package/schemas/setup-receipt.schema.json +28 -0
- package/schemas/skill-frontmatter.schema.json +20 -0
- package/schemas/support-bundle.schema.json +37 -0
- package/schemas/task-contract.schema.json +31 -0
- package/scripts/active-autonomy-hook.mjs +226 -0
- package/scripts/build-linux-packages.mjs +7 -3
- package/scripts/cleanup-test-fixtures.sh +55 -0
- package/scripts/context-hydration-hook.mjs +89 -0
- package/scripts/demo-smoke.js +285 -0
- package/scripts/doctor.js +27 -12
- package/scripts/install.sh +57 -0
- package/scripts/install.sh.sha256 +1 -0
- package/scripts/linux-package-smoke.mjs +2 -2
- package/scripts/package-size-check.mjs +26 -0
- package/scripts/plugin-sync.js +83 -17
- package/scripts/postinstall.js +17 -10
- package/scripts/prepack.js +9 -0
- package/scripts/ralph/prompt.md +35 -0
- package/scripts/release-sync.js +72 -7
- package/scripts/release-verify.js +260 -2
- package/scripts/setup-npmrc.js +48 -23
- package/scripts/skills-install.js +9 -2
- package/scripts/skills-manifest.js +2 -21
- package/scripts/skills-pack.js +2 -2
- package/scripts/skills-validate.js +5 -55
- package/skills/arch/SKILL.md +2 -0
- package/skills/build/SKILL.md +3 -0
- package/skills/flow/SKILL.md +2 -0
- package/skills/index.json +0 -0
- package/skills/sage/SKILL.md +2 -0
- package/skills/sage/references/source-selection.md +8 -0
- package/skills/vet/SKILL.md +2 -0
- package/skills/vet/references/security-playbooks.md +7 -0
- package/skills/vibe/SKILL.md +2 -0
- package/sprint/00-idea.md +0 -0
- package/sprint/01-architecture.md +0 -0
- package/sprint/02-oss-evidence.md +0 -0
- package/sprint/03-logic.md +0 -0
- package/sprint/04-security.md +0 -0
- package/sprint/05-dx-ux.md +0 -0
- package/sprint/06-build-plan.md +0 -0
- package/sprint/07-release.md +0 -0
- package/src/agents.js +279 -0
- package/src/bootstrap.js +268 -62
- package/src/build-gate.js +2 -2
- package/src/codex-app-server.js +291 -0
- package/src/decision-log.js +0 -0
- package/src/fs-utils.js +175 -4
- package/src/launcher.js +28 -21
- package/src/mcp-config.js +9 -1
- package/src/mcp-live-client.js +422 -3
- package/src/paths.js +10 -1
- package/src/policy.js +3 -3
- package/src/prelaunch.js +189 -0
- package/src/quality/ai-quality-orchestrator.js +328 -0
- package/src/release-issue-gates.js +252 -0
- package/src/release-operations.js +62 -0
- package/src/release-state.js +0 -0
- package/src/runtime/active-autonomy-core.js +208 -0
- package/src/runtime/agent-compat.js +31 -0
- package/src/runtime/alignment-sentinel.js +165 -0
- package/src/runtime/architect-review.js +326 -0
- package/src/runtime/autonomous-tasks.js +408 -0
- package/src/runtime/build-readiness.js +28 -4
- package/src/runtime/code-graph-rehearse.js +113 -0
- package/src/runtime/codeburn-core.js +112 -0
- package/src/runtime/context-authority.js +40 -0
- package/src/runtime/context-economy-core.js +316 -0
- package/src/runtime/continuity-graph.js +201 -0
- package/src/runtime/continuity-notes.js +71 -26
- package/src/runtime/core-source-ingest.js +379 -0
- package/src/runtime/detached-provider.js +142 -0
- package/src/runtime/doctor-report.js +18 -0
- package/src/runtime/environment-awareness-core.js +460 -0
- package/src/runtime/exposure-catalog.js +276 -0
- package/src/runtime/graphify-core.js +167 -0
- package/src/runtime/guidance-stack.js +9 -2
- package/src/runtime/handoff-packets.js +92 -0
- package/src/runtime/headroom-core.js +104 -0
- package/src/runtime/helper-orchestration-core.js +307 -0
- package/src/runtime/hook-profiles.js +20 -0
- package/src/runtime/learning-loop-core.js +344 -0
- package/src/runtime/live-agent-verification.js +122 -0
- package/src/runtime/maestro-events.js +18 -0
- package/src/runtime/maestro-manager.js +19 -0
- package/src/runtime/maestro-output.js +58 -0
- package/src/runtime/maestro-state.js +125 -0
- package/src/runtime/managed-markdown.js +29 -0
- package/src/runtime/mcp-authority.js +147 -0
- package/src/runtime/mcp-policy.js +192 -0
- package/src/runtime/obsidian-integration-core.js +1089 -0
- package/src/runtime/obsidian-plugin-bridge.js +1045 -0
- package/src/runtime/pi-maestro-core.js +89 -0
- package/src/runtime/preferences.js +79 -0
- package/src/runtime/project-context.js +636 -0
- package/src/runtime/prompt-strategy-core.js +230 -0
- package/src/runtime/quorum-review.js +90 -0
- package/src/runtime/ralph-execution-core.js +217 -0
- package/src/runtime/redaction-gateway.js +373 -0
- package/src/runtime/runtime-state.js +935 -2
- package/src/runtime/schema-migrations.js +162 -0
- package/src/runtime/semantic-recording-core.js +147 -0
- package/src/runtime/signal-hooks.js +28 -0
- package/src/runtime/skills-registry-export.js +754 -0
- package/src/runtime/task-contracts.js +83 -0
- package/src/runtime/universal-plugin-broker-core.js +898 -0
- package/src/runtime/workspace-intelligence-runtime.js +674 -0
- package/src/runtime/workspace-virtualizer.js +102 -0
- package/src/runtime-artifacts.js +225 -62
- package/src/setup-lifecycle.js +359 -0
- package/src/skill-frontmatter.js +78 -0
- package/src/skill-installer.js +226 -71
- package/src/skills.js +1166 -96
- package/src/state-sync.js +0 -0
- package/src/test-fixtures.js +543 -0
- package/src/tui/grid.js +67 -0
- package/src/tui/status-grid.js +23 -0
- package/support-bundle.json +114 -0
- package/templates/AGENTS.md +6 -2
- package/templates/catalog-manifest.json +0 -0
- package/templates/model-instructions/core.md +0 -0
- package/templates/model-instructions/release.md +0 -0
- package/templates/model-instructions/security.md +0 -0
- package/templates/quality/ai-quality-rules.yml +37 -0
- package/docs/assets/image/Screenshot(1).png +0 -0
- package/docs/assets/image/Screenshot(2).png +0 -0
- package/docs/assets/image/Screenshot(3).png +0 -0
- package/docs/assets/image/Screenshot(4).png +0 -0
- package/docs/assets/image/Screenshot(5).png +0 -0
- package/docs/assets/image/Screenshot(6).png +0 -0
- package/docs/assets/image/Screenshot(7).png +0 -0
- package/docs/assets/image/Screenshot(8).png +0 -0
- package/docs/assets/image/Screenshot(9).png +0 -0
- package/docs/assets/meta-architect-logo.png +0 -0
- package/docs/assets/meta-architect-logo.svg +0 -8
- package/docs/onboarding.md +0 -65
- package/docs/skills-publishing.md +0 -255
package/scripts/postinstall.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import fs from "node:fs/promises";
|
|
3
4
|
import process from "node:process";
|
|
4
|
-
import { installSkills, installSupportBundle } from "../src/skill-installer.js";
|
|
5
5
|
|
|
6
6
|
async function main() {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const dryRun = process.env.MA_POSTINSTALL_DRY_RUN === "1";
|
|
8
|
+
const skipSkills = process.env.MA_SKIP_SKILLS === "1";
|
|
9
|
+
const receiptPath = process.env.MA_POSTINSTALL_RECEIPT;
|
|
10
|
+
console.log(
|
|
11
|
+
`meta-architect: postinstall skills=${skipSkills ? "disabled" : "enabled"} dry-run=${dryRun ? "yes" : "no"}`,
|
|
12
|
+
);
|
|
13
|
+
if (dryRun || skipSkills || process.env.MA_SKIP_AUTO_INSTALL === "1") {
|
|
14
|
+
console.log("meta-architect: deferred host selection until first interactive launch");
|
|
9
15
|
return;
|
|
10
16
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
console.log("meta-architect: host selection deferred until first interactive launch");
|
|
18
|
+
if (receiptPath) {
|
|
19
|
+
await fs.writeFile(
|
|
20
|
+
receiptPath,
|
|
21
|
+
`${JSON.stringify({ schemaVersion: "0.1.0", deferred: true }, null, 2)}\n`,
|
|
22
|
+
);
|
|
23
|
+
console.log(`meta-architect: receipt ${receiptPath}`);
|
|
24
|
+
}
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
main().catch((error) => {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Meta-Architect Ralph Execution Core
|
|
2
|
+
|
|
3
|
+
You are executing a Meta-Architect story contract, not an independent release authority.
|
|
4
|
+
|
|
5
|
+
## Required Inputs
|
|
6
|
+
|
|
7
|
+
1. Read `.ma/plans/prd.json`.
|
|
8
|
+
2. Read `.ma/plans/progress.txt`.
|
|
9
|
+
3. Pick the highest-priority story where `passes` is `false`.
|
|
10
|
+
4. Execute exactly one bounded story per iteration.
|
|
11
|
+
|
|
12
|
+
## MA Quality Gates
|
|
13
|
+
|
|
14
|
+
Before marking a story passed, verify:
|
|
15
|
+
|
|
16
|
+
- `$arch` architecture constraints remain satisfied.
|
|
17
|
+
- `$sage` evidence and source claims remain valid.
|
|
18
|
+
- `$flow` logic/state invariants remain valid.
|
|
19
|
+
- `$vet` security blockers are absent or explicitly owned.
|
|
20
|
+
- `$vibe` DX/UX constraints remain acceptable.
|
|
21
|
+
- `$build` real-workspace checks pass for the changed slice.
|
|
22
|
+
|
|
23
|
+
## Authority Boundaries
|
|
24
|
+
|
|
25
|
+
- Do not mutate `.ma/release.json` or `.ma/decisions.json` directly.
|
|
26
|
+
- Return authoritative status through `$maestro`, `$build`, or the owning lane.
|
|
27
|
+
- Treat Obsidian/vault context as `vault_context`, never `build_evidence`.
|
|
28
|
+
- Treat virtual workspace output as context only, never production proof.
|
|
29
|
+
- Treat code-graph rehearsal as a read-only trajectory preview.
|
|
30
|
+
|
|
31
|
+
## Completion Contract
|
|
32
|
+
|
|
33
|
+
Update story `passes` only after fresh verification evidence exists.
|
|
34
|
+
Append progress to `.ma/plans/progress.txt`.
|
|
35
|
+
Record reusable learnings in scoped guidance without overwriting the base workspace contract.
|
package/scripts/release-sync.js
CHANGED
|
@@ -31,6 +31,8 @@ const WATCHED_FILES = new Set([
|
|
|
31
31
|
function parseArgs(argv) {
|
|
32
32
|
const args = {
|
|
33
33
|
bump: "",
|
|
34
|
+
version: "",
|
|
35
|
+
refreshFrom: "",
|
|
34
36
|
fromRef: "",
|
|
35
37
|
toRef: "",
|
|
36
38
|
githubOutput: "",
|
|
@@ -44,6 +46,16 @@ function parseArgs(argv) {
|
|
|
44
46
|
index += 1;
|
|
45
47
|
continue;
|
|
46
48
|
}
|
|
49
|
+
if (token === "--version") {
|
|
50
|
+
args.version = argv[index + 1] ?? "";
|
|
51
|
+
index += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (token === "--refresh-from") {
|
|
55
|
+
args.refreshFrom = argv[index + 1] ?? "";
|
|
56
|
+
index += 1;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
47
59
|
if (token === "--from-ref") {
|
|
48
60
|
args.fromRef = argv[index + 1] ?? "";
|
|
49
61
|
index += 1;
|
|
@@ -184,6 +196,12 @@ function updateCurrentSurfaceFile(file, oldVersion, nextVersion) {
|
|
|
184
196
|
writeText(file, content);
|
|
185
197
|
}
|
|
186
198
|
|
|
199
|
+
function syncReadmeReleaseSurface(_nextVersion) {
|
|
200
|
+
const readmePath = "README.md";
|
|
201
|
+
// The README uses a dynamic GitHub release badge; no version replacement is needed.
|
|
202
|
+
writeText(readmePath, readText(readmePath));
|
|
203
|
+
}
|
|
204
|
+
|
|
187
205
|
function syncPackageVersion(nextVersion) {
|
|
188
206
|
const pkg = readJson("package.json");
|
|
189
207
|
const lock = readJson("package-lock.json");
|
|
@@ -196,6 +214,14 @@ function syncPackageVersion(nextVersion) {
|
|
|
196
214
|
writeJson("package-lock.json", lock);
|
|
197
215
|
}
|
|
198
216
|
|
|
217
|
+
function syncSupportBundleVersion(nextVersion) {
|
|
218
|
+
const manifestPath = "support-bundle.json";
|
|
219
|
+
if (!fs.existsSync(manifestPath)) return;
|
|
220
|
+
const manifest = readJson(manifestPath);
|
|
221
|
+
manifest.bundleVersion = nextVersion;
|
|
222
|
+
writeJson(manifestPath, manifest);
|
|
223
|
+
}
|
|
224
|
+
|
|
199
225
|
function syncPluginVersions(nextVersion) {
|
|
200
226
|
for (const file of [
|
|
201
227
|
path.join("plugins", "meta-architect", ".app.json"),
|
|
@@ -215,9 +241,13 @@ function syncPluginVersions(nextVersion) {
|
|
|
215
241
|
function syncCurrentReleaseFiles(oldVersion, nextVersion) {
|
|
216
242
|
for (const file of [
|
|
217
243
|
"README.md",
|
|
244
|
+
"DEMO.md",
|
|
245
|
+
"COVERAGE.md",
|
|
218
246
|
"RELEASE.md",
|
|
219
247
|
path.join("docs", "README.md"),
|
|
220
248
|
path.join("docs", "getting-started.md"),
|
|
249
|
+
path.join("docs", "onboarding.md"),
|
|
250
|
+
path.join("docs", "skills.md"),
|
|
221
251
|
path.join("docs", "release-spec.md"),
|
|
222
252
|
path.join("plugins", "meta-architect", "README.md"),
|
|
223
253
|
]) {
|
|
@@ -228,16 +258,17 @@ function syncCurrentReleaseFiles(oldVersion, nextVersion) {
|
|
|
228
258
|
const nextQa = path.join("docs", "qa", `release-readiness-${nextVersion}.md`);
|
|
229
259
|
fs.renameSync(oldQa, nextQa);
|
|
230
260
|
updateCurrentSurfaceFile(nextQa, oldVersion, nextVersion);
|
|
261
|
+
|
|
262
|
+
const oldIssueGates = path.join("docs", "qa", `release-issue-gates-${oldVersion}.json`);
|
|
263
|
+
const nextIssueGates = path.join("docs", "qa", `release-issue-gates-${nextVersion}.json`);
|
|
264
|
+
if (fs.existsSync(oldIssueGates)) {
|
|
265
|
+
fs.renameSync(oldIssueGates, nextIssueGates);
|
|
266
|
+
updateCurrentSurfaceFile(nextIssueGates, oldVersion, nextVersion);
|
|
267
|
+
}
|
|
231
268
|
}
|
|
232
269
|
|
|
233
270
|
function syncSupportingCode(oldVersion, nextVersion) {
|
|
234
271
|
const replacements = [
|
|
235
|
-
{
|
|
236
|
-
file: path.join("src", "skills.js"),
|
|
237
|
-
search: `release-readiness-${oldVersion}.md`,
|
|
238
|
-
replacement: `release-readiness-${nextVersion}.md`,
|
|
239
|
-
label: "skills QA path",
|
|
240
|
-
},
|
|
241
272
|
{
|
|
242
273
|
file: path.join("test", "package-install-smoke.test.js"),
|
|
243
274
|
search: `jstn-sdk-ma-${oldVersion}.tgz`,
|
|
@@ -259,6 +290,9 @@ function syncSupportingCode(oldVersion, nextVersion) {
|
|
|
259
290
|
|
|
260
291
|
const mcpLiveClientFile = path.join("src", "mcp-live-client.js");
|
|
261
292
|
const mcpLiveClient = readText(mcpLiveClientFile);
|
|
293
|
+
if (/resolveMcpClientVersion\(packageMetadata\)/.test(mcpLiveClient)) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
262
296
|
if (!/version: "[0-9]+\.[0-9]+\.[0-9]+(?:-dev)?"/.test(mcpLiveClient)) {
|
|
263
297
|
throw new Error("Expected to find mcp live client version declaration");
|
|
264
298
|
}
|
|
@@ -271,6 +305,27 @@ function syncSupportingCode(oldVersion, nextVersion) {
|
|
|
271
305
|
);
|
|
272
306
|
}
|
|
273
307
|
|
|
308
|
+
function refreshCurrentReleaseFiles(oldVersion, currentVersion) {
|
|
309
|
+
for (const file of [
|
|
310
|
+
"README.md",
|
|
311
|
+
"DEMO.md",
|
|
312
|
+
"COVERAGE.md",
|
|
313
|
+
"RELEASE.md",
|
|
314
|
+
path.join("docs", "README.md"),
|
|
315
|
+
path.join("docs", "getting-started.md"),
|
|
316
|
+
path.join("docs", "onboarding.md"),
|
|
317
|
+
path.join("docs", "skills.md"),
|
|
318
|
+
path.join("docs", "release-spec.md"),
|
|
319
|
+
path.join("plugins", "meta-architect", "README.md"),
|
|
320
|
+
path.join("docs", "qa", `release-readiness-${currentVersion}.md`),
|
|
321
|
+
path.join("docs", "qa", `release-issue-gates-${currentVersion}.json`),
|
|
322
|
+
path.join("scripts", "install.sh"),
|
|
323
|
+
path.join("plugins", "meta-architect", "obsidian", "manifest.json"),
|
|
324
|
+
]) {
|
|
325
|
+
if (fs.existsSync(file)) updateCurrentSurfaceFile(file, oldVersion, currentVersion);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
274
329
|
function rewriteReleaseState(nextVersion, previousVersion) {
|
|
275
330
|
const releasePath = "RELEASE.md";
|
|
276
331
|
const qaPath = path.join("docs", "qa", `release-readiness-${nextVersion}.md`);
|
|
@@ -319,6 +374,13 @@ function main() {
|
|
|
319
374
|
const args = parseArgs(process.argv.slice(2));
|
|
320
375
|
const pkg = readJson("package.json");
|
|
321
376
|
const currentVersion = pkg.version;
|
|
377
|
+
if (args.refreshFrom) {
|
|
378
|
+
refreshCurrentReleaseFiles(args.refreshFrom, currentVersion);
|
|
379
|
+
console.log(
|
|
380
|
+
JSON.stringify({ updated: true, refreshed: true, version: currentVersion }, null, 2),
|
|
381
|
+
);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
322
384
|
const changedFiles = getChangedFiles(args);
|
|
323
385
|
const relevantChanges = args.force ? ["<forced>"] : changedFiles.filter(isWatchedPath);
|
|
324
386
|
|
|
@@ -342,12 +404,15 @@ function main() {
|
|
|
342
404
|
}
|
|
343
405
|
|
|
344
406
|
const bumpKind = args.bump || "patch";
|
|
345
|
-
const nextVersion = bumpVersion(currentVersion, bumpKind);
|
|
407
|
+
const nextVersion = args.version || bumpVersion(currentVersion, bumpKind);
|
|
408
|
+
parseVersion(nextVersion);
|
|
346
409
|
|
|
347
410
|
syncPackageVersion(nextVersion);
|
|
411
|
+
syncSupportBundleVersion(nextVersion);
|
|
348
412
|
syncPluginVersions(nextVersion);
|
|
349
413
|
prependChangelog(nextVersion);
|
|
350
414
|
syncCurrentReleaseFiles(currentVersion, nextVersion);
|
|
415
|
+
syncReadmeReleaseSurface(nextVersion);
|
|
351
416
|
syncSupportingCode(currentVersion, nextVersion);
|
|
352
417
|
rewriteReleaseState(nextVersion, currentVersion);
|
|
353
418
|
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
import crypto from "node:crypto";
|
|
3
5
|
import fs from "node:fs";
|
|
4
6
|
import path from "node:path";
|
|
5
7
|
import process from "node:process";
|
|
8
|
+
import { validateReleaseIssueGates } from "../src/release-issue-gates.js";
|
|
6
9
|
|
|
7
10
|
const CANONICAL_PACKAGE = "@jstn-sdk/ma";
|
|
8
11
|
const CANONICAL_INSTALL = "npm i -g @openai/codex@latest @jstn-sdk/ma@latest";
|
|
@@ -38,12 +41,19 @@ function parseVersion(version) {
|
|
|
38
41
|
return match.groups;
|
|
39
42
|
}
|
|
40
43
|
|
|
44
|
+
function latestCdnInstall() {
|
|
45
|
+
return "curl -fsSLo install.sh https://cdn.jsdelivr.net/gh/JustineDevs/meta-architect@latest/scripts/install.sh && curl -fsSLo install.sh.sha256 https://cdn.jsdelivr.net/gh/JustineDevs/meta-architect@latest/scripts/install.sh.sha256 && sed 's#scripts/install.sh#install.sh#' install.sh.sha256 | sha256sum -c - && sh install.sh";
|
|
46
|
+
}
|
|
47
|
+
|
|
41
48
|
function verifyInstallBlock(file) {
|
|
42
49
|
const content = readText(file);
|
|
43
|
-
|
|
50
|
+
const cdnInstall = latestCdnInstall();
|
|
51
|
+
if (!content.includes(CANONICAL_INSTALL) && !content.includes(cdnInstall)) {
|
|
44
52
|
return;
|
|
45
53
|
}
|
|
46
54
|
|
|
55
|
+
assert(content.includes(cdnInstall), `${file}: missing jsDelivr POSIX installer command`);
|
|
56
|
+
assert(content.includes(CANONICAL_INSTALL), `${file}: missing canonical npm install command`);
|
|
47
57
|
assert(content.includes(CANONICAL_LAUNCH), `${file}: missing canonical launch command`);
|
|
48
58
|
assert(content.includes(UNINSTALL_MA), `${file}: missing uninstall Meta-Architect command`);
|
|
49
59
|
assert(
|
|
@@ -52,6 +62,230 @@ function verifyInstallBlock(file) {
|
|
|
52
62
|
);
|
|
53
63
|
}
|
|
54
64
|
|
|
65
|
+
function verifyNpmIgnore() {
|
|
66
|
+
assert(fs.existsSync(".npmignore"), ".npmignore: missing production package ignore file");
|
|
67
|
+
const content = readText(".npmignore");
|
|
68
|
+
for (const requiredPattern of [
|
|
69
|
+
".ma/",
|
|
70
|
+
".omx/",
|
|
71
|
+
"node_modules/",
|
|
72
|
+
".npm-cache/",
|
|
73
|
+
"dist/",
|
|
74
|
+
"test/",
|
|
75
|
+
".github/",
|
|
76
|
+
"*.tgz",
|
|
77
|
+
]) {
|
|
78
|
+
assert(
|
|
79
|
+
content.includes(requiredPattern),
|
|
80
|
+
`.npmignore: missing required production ignore pattern ${requiredPattern}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function verifyDistPolicy() {
|
|
86
|
+
const tracked = execFileSync("git", ["ls-files", "dist/"], { encoding: "utf8" }).trim();
|
|
87
|
+
assert(!tracked, `dist/: generated release artifacts must not be tracked:\n${tracked}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function verifyInstallerIntegrity() {
|
|
91
|
+
const installer = readText("scripts/install.sh");
|
|
92
|
+
const checksum = readText("scripts/install.sh.sha256").trim().split(/\s+/)[0];
|
|
93
|
+
const actual = crypto.createHash("sha256").update(installer).digest("hex");
|
|
94
|
+
assert(checksum === actual, "scripts/install.sh.sha256: checksum does not match installer");
|
|
95
|
+
assert(
|
|
96
|
+
!installer.includes("raw.githubusercontent.com") && !installer.includes("jsdelivr"),
|
|
97
|
+
"scripts/install.sh: must not fetch mutable installer sources at runtime",
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function verifyDemoDoc({ version, gitTag }) {
|
|
102
|
+
const cdnInstall = latestCdnInstall();
|
|
103
|
+
assert(fs.existsSync("DEMO.md"), "DEMO.md: missing demo guide");
|
|
104
|
+
const content = readText("DEMO.md");
|
|
105
|
+
assert(content.includes(`Release line: \`${gitTag}\``), "DEMO.md: wrong release line");
|
|
106
|
+
assert(content.includes("Package: `@jstn-sdk/ma`"), "DEMO.md: missing package name");
|
|
107
|
+
assert(content.includes(cdnInstall), "DEMO.md: missing versioned installer");
|
|
108
|
+
assert(content.includes(CANONICAL_INSTALL), "DEMO.md: missing canonical npm install");
|
|
109
|
+
assert(content.includes(CANONICAL_LAUNCH), "DEMO.md: missing canonical launch");
|
|
110
|
+
assert(content.includes(UNINSTALL_MA), "DEMO.md: missing MA uninstall command");
|
|
111
|
+
assert(content.includes(UNINSTALL_BOTH), "DEMO.md: missing MA + Codex uninstall command");
|
|
112
|
+
assert(content.includes("npm run release:check"), "DEMO.md: missing full release demo command");
|
|
113
|
+
assert(
|
|
114
|
+
content.includes("Learning Loop Core") || content.includes("learning loop"),
|
|
115
|
+
"DEMO.md: missing learning loop coverage",
|
|
116
|
+
);
|
|
117
|
+
assert(content.includes("Obsidian"), "DEMO.md: missing Obsidian coverage");
|
|
118
|
+
assert(content.includes("Ralph"), "DEMO.md: missing Ralph execution coverage");
|
|
119
|
+
assert(content.includes("data/clone-data.proof.json"), "DEMO.md: missing clone-data proof");
|
|
120
|
+
assert(content.includes("COVERAGE.md"), "DEMO.md: missing coverage artifact");
|
|
121
|
+
assert(content.includes(`version line is \`${version}\``), "DEMO.md: missing current version");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function verifyCoverageDoc({ version, gitTag }) {
|
|
125
|
+
assert(fs.existsSync("COVERAGE.md"), "COVERAGE.md: missing coverage matrix");
|
|
126
|
+
const content = readText("COVERAGE.md");
|
|
127
|
+
assert(content.includes(`Target release: \`${gitTag}\``), "COVERAGE.md: wrong target release");
|
|
128
|
+
assert(
|
|
129
|
+
content.includes(`Package: \`@jstn-sdk/ma@${version}\``),
|
|
130
|
+
"COVERAGE.md: wrong package version",
|
|
131
|
+
);
|
|
132
|
+
assert(content.includes("Learning Loop Core"), "COVERAGE.md: missing learning-loop coverage");
|
|
133
|
+
assert(
|
|
134
|
+
content.includes("Helper Orchestration Core"),
|
|
135
|
+
"COVERAGE.md: missing helper orchestration coverage",
|
|
136
|
+
);
|
|
137
|
+
assert(
|
|
138
|
+
content.includes("Environment Awareness Core"),
|
|
139
|
+
"COVERAGE.md: missing environment awareness coverage",
|
|
140
|
+
);
|
|
141
|
+
assert(
|
|
142
|
+
content.includes("Universal Plugin Broker Core"),
|
|
143
|
+
"COVERAGE.md: missing universal plugin broker coverage",
|
|
144
|
+
);
|
|
145
|
+
assert(content.includes("Obsidian Integration Core"), "COVERAGE.md: missing Obsidian coverage");
|
|
146
|
+
assert(content.includes("Ralph Execution Core"), "COVERAGE.md: missing Ralph coverage");
|
|
147
|
+
assert(content.includes("36/36 passing"), "COVERAGE.md: missing current test count");
|
|
148
|
+
assert(
|
|
149
|
+
content.includes("This repository is not a toy demo."),
|
|
150
|
+
"COVERAGE.md: missing truth statement",
|
|
151
|
+
);
|
|
152
|
+
assert(!content.includes("@jstn-sdk/ma@0.1.0"), "COVERAGE.md: stale npm package version");
|
|
153
|
+
assert(!content.includes("v0.1.0 release bar"), "COVERAGE.md: stale release bar");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function verifyReadmeReleaseSurface({ gitTag }) {
|
|
157
|
+
const content = readText("README.md");
|
|
158
|
+
const demoImage = `<img src="https://raw.githubusercontent.com/JustineDevs/meta-architect/${gitTag}/docs/assets/DEMO_VIDEO.gif" alt="Meta-Architect demo video" width="800">`;
|
|
159
|
+
const logoImage = `<img src="https://raw.githubusercontent.com/JustineDevs/meta-architect/${gitTag}/docs/assets/meta-architect-logo.svg" alt="Meta-Architect: quality gates and evidence verification for AI coding agents" width="1024" height="240">`;
|
|
160
|
+
assert(content.includes("> [!NOTE]"), "README.md: missing product-positioning note admonition");
|
|
161
|
+
assert(
|
|
162
|
+
content.includes(
|
|
163
|
+
"> Meta-Architect is a workflow layer for teams that want architecture, evidence, review, and release discipline before build execution.",
|
|
164
|
+
),
|
|
165
|
+
"README.md: missing workflow-layer positioning note",
|
|
166
|
+
);
|
|
167
|
+
assert(
|
|
168
|
+
content.includes("> Meta-Architect does not replace your coding runtime."),
|
|
169
|
+
"README.md: missing runtime-wrapper boundary note",
|
|
170
|
+
);
|
|
171
|
+
assert(
|
|
172
|
+
content.includes(
|
|
173
|
+
"> It wraps that runtime with architecture, evidence, gate enforcement, and release-sensitive workflow control.",
|
|
174
|
+
),
|
|
175
|
+
"README.md: missing runtime-wrapper behavior note",
|
|
176
|
+
);
|
|
177
|
+
assert(content.includes(demoImage), "README.md: missing requested 800px demo GIF");
|
|
178
|
+
assert(
|
|
179
|
+
content.includes("<summary><strong>🔌 All 33 plugins & features</strong></summary>"),
|
|
180
|
+
"README.md: missing all 33 plugins/features toggle",
|
|
181
|
+
);
|
|
182
|
+
assert(
|
|
183
|
+
content.includes(
|
|
184
|
+
"https://img.shields.io/github/v/release/JustineDevs/meta-architect?display_name=tag&sort=semver",
|
|
185
|
+
),
|
|
186
|
+
"README.md: missing GitHub release badge",
|
|
187
|
+
);
|
|
188
|
+
assert(content.includes(logoImage), "README.md: release-pinned logo missing");
|
|
189
|
+
assert(
|
|
190
|
+
!content.includes("raw.githubusercontent.com/JustineDevs/meta-architect/main/"),
|
|
191
|
+
"README.md: stable docs must not reference mutable main",
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function verifyRealDemoKit() {
|
|
196
|
+
const runbook = readText(path.join("docs", "demo", "REAL_DEMO_RUNBOOK.md"));
|
|
197
|
+
const story = readText(path.join("docs", "demo", "DEMO_STORY.md"));
|
|
198
|
+
const checklist = readText(path.join("docs", "demo", "PROSPECT_CHECKLIST.md"));
|
|
199
|
+
assert(fs.existsSync(path.join("scripts", "demo-smoke.js")), "scripts/demo-smoke.js: missing");
|
|
200
|
+
assert(
|
|
201
|
+
runbook.includes("npm run demo:smoke"),
|
|
202
|
+
"REAL_DEMO_RUNBOOK.md: missing demo smoke command",
|
|
203
|
+
);
|
|
204
|
+
assert(runbook.includes("$maestro"), "REAL_DEMO_RUNBOOK.md: missing maestro scenario");
|
|
205
|
+
assert(
|
|
206
|
+
runbook.includes("vault_context"),
|
|
207
|
+
"REAL_DEMO_RUNBOOK.md: missing Obsidian context boundary",
|
|
208
|
+
);
|
|
209
|
+
assert(story.includes("Northstar Logistics"), "DEMO_STORY.md: missing realistic buyer story");
|
|
210
|
+
assert(story.includes("npm run release:verify"), "DEMO_STORY.md: missing release proof close");
|
|
211
|
+
assert(
|
|
212
|
+
checklist.includes("Remove `Demo Account`, `Test Company`, `Sample Co`"),
|
|
213
|
+
"PROSPECT_CHECKLIST.md: missing no-test-branding check",
|
|
214
|
+
);
|
|
215
|
+
for (const forbidden of ["Demo Account", "Test Company", "Sample Co"]) {
|
|
216
|
+
assert(
|
|
217
|
+
!runbook.includes(forbidden) && !story.includes(forbidden),
|
|
218
|
+
`demo docs: forbidden visible demo branding ${forbidden}`,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function verifyCanonicalSemanticSurfaces({ version, gitTag }) {
|
|
224
|
+
const usageWorkflow = readText(path.join("example", "usage-workflow.md"));
|
|
225
|
+
assert(
|
|
226
|
+
usageWorkflow.includes(`$maestro I want to harden Meta-Architect ${gitTag}`),
|
|
227
|
+
"example/usage-workflow.md: missing current $maestro release-hardening scenario",
|
|
228
|
+
);
|
|
229
|
+
for (const requiredTerm of ["Obsidian", "Ralph", "Caveman", "learning-loop"]) {
|
|
230
|
+
assert(
|
|
231
|
+
usageWorkflow.includes(requiredTerm),
|
|
232
|
+
`example/usage-workflow.md: missing ${requiredTerm} semantic-core term`,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
for (const staleTerm of [
|
|
236
|
+
"Build a demo",
|
|
237
|
+
"demo app",
|
|
238
|
+
"collaborative whiteboard",
|
|
239
|
+
"smart contract security review",
|
|
240
|
+
"Timeline: 4 weeks",
|
|
241
|
+
"Delivery plan for v0.1.0",
|
|
242
|
+
"@jstn-sdk/ma@0.1.0",
|
|
243
|
+
]) {
|
|
244
|
+
assert(
|
|
245
|
+
!usageWorkflow.includes(staleTerm),
|
|
246
|
+
`example/usage-workflow.md: stale current-facing term ${staleTerm}`,
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const mission = readText(path.join("missions", "collaborative-whiteboard", "mission.md"));
|
|
251
|
+
assert(
|
|
252
|
+
mission.includes("# Mission: Semantic Release Hardening"),
|
|
253
|
+
"missions/collaborative-whiteboard/mission.md: stale mission title",
|
|
254
|
+
);
|
|
255
|
+
assert(
|
|
256
|
+
mission.includes("Obsidian is core vault-context infrastructure"),
|
|
257
|
+
"missions/collaborative-whiteboard/mission.md: missing Obsidian core mission contract",
|
|
258
|
+
);
|
|
259
|
+
assert(
|
|
260
|
+
mission.includes("Ralph is the execution loop"),
|
|
261
|
+
"missions/collaborative-whiteboard/mission.md: missing Ralph core mission contract",
|
|
262
|
+
);
|
|
263
|
+
assert(
|
|
264
|
+
!mission.toLowerCase().includes("real-time collaborative whiteboard"),
|
|
265
|
+
"missions/collaborative-whiteboard/mission.md: stale whiteboard mission text",
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
const currentQa = readText(path.join("docs", "qa", `release-readiness-${version}.md`));
|
|
269
|
+
assert(
|
|
270
|
+
currentQa.includes(`Harden Meta-Architect ${gitTag} semantic core`),
|
|
271
|
+
`docs/qa/release-readiness-${version}.md: missing realistic semantic smoke idea`,
|
|
272
|
+
);
|
|
273
|
+
assert(
|
|
274
|
+
!currentQa.includes('ma idea "Build a demo app"'),
|
|
275
|
+
`docs/qa/release-readiness-${version}.md: stale demo-app helper path`,
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const archPrompt = readText(path.join("prompts", "architect.md"));
|
|
279
|
+
assert(
|
|
280
|
+
!archPrompt.includes("v0.1.0` skills library"),
|
|
281
|
+
"prompts/architect.md: stale v0.1.0 skills-library wording",
|
|
282
|
+
);
|
|
283
|
+
assert(
|
|
284
|
+
archPrompt.includes("current Meta-Architect skills library"),
|
|
285
|
+
"prompts/architect.md: missing current library wording",
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
55
289
|
function main() {
|
|
56
290
|
const pkg = readJson("package.json");
|
|
57
291
|
const lock = readJson("package-lock.json");
|
|
@@ -68,6 +302,17 @@ function main() {
|
|
|
68
302
|
pkg.publishConfig?.access === "public",
|
|
69
303
|
"package.json: publishConfig.access must be public",
|
|
70
304
|
);
|
|
305
|
+
assert(pkg.files?.includes("DEMO.md"), "package.json: files must include DEMO.md");
|
|
306
|
+
assert(pkg.files?.includes("COVERAGE.md"), "package.json: files must include COVERAGE.md");
|
|
307
|
+
|
|
308
|
+
verifyNpmIgnore();
|
|
309
|
+
verifyDistPolicy();
|
|
310
|
+
verifyInstallerIntegrity();
|
|
311
|
+
verifyDemoDoc({ version, gitTag });
|
|
312
|
+
verifyCoverageDoc({ version, gitTag });
|
|
313
|
+
verifyReadmeReleaseSurface({ gitTag });
|
|
314
|
+
verifyRealDemoKit();
|
|
315
|
+
verifyCanonicalSemanticSurfaces({ version, gitTag });
|
|
71
316
|
|
|
72
317
|
const changelog = readText("CHANGELOG.md");
|
|
73
318
|
assert(changelog.includes(`## ${gitTag}`), "CHANGELOG.md: missing current version heading");
|
|
@@ -95,6 +340,17 @@ function main() {
|
|
|
95
340
|
const qa = readText(qaPath);
|
|
96
341
|
assert(qa.includes(`# Release Readiness ${version}`), `${qaPath}: wrong title version`);
|
|
97
342
|
|
|
343
|
+
const issueGatesPath = path.join("docs", "qa", `release-issue-gates-${version}.json`);
|
|
344
|
+
assert(fs.existsSync(issueGatesPath), `Missing release issue gate file: ${issueGatesPath}`);
|
|
345
|
+
const issueGates = validateReleaseIssueGates(readJson(issueGatesPath), {
|
|
346
|
+
version,
|
|
347
|
+
requirePassed: true,
|
|
348
|
+
});
|
|
349
|
+
assert(
|
|
350
|
+
issueGates.valid,
|
|
351
|
+
`${issueGatesPath}: release issue gates are not production-passed\n- ${issueGates.errors.join("\n- ")}`,
|
|
352
|
+
);
|
|
353
|
+
|
|
98
354
|
const pluginApp = readJson(path.join("plugins", "meta-architect", ".app.json"));
|
|
99
355
|
const pluginMcp = readJson(path.join("plugins", "meta-architect", ".mcp.json"));
|
|
100
356
|
const pluginManifest = readJson(
|
|
@@ -109,12 +365,14 @@ function main() {
|
|
|
109
365
|
|
|
110
366
|
for (const file of [
|
|
111
367
|
"README.md",
|
|
368
|
+
"DEMO.md",
|
|
369
|
+
"COVERAGE.md",
|
|
112
370
|
path.join("docs", "getting-started.md"),
|
|
113
371
|
path.join("docs", "onboarding.md"),
|
|
114
372
|
path.join("docs", "skills.md"),
|
|
115
373
|
path.join("plugins", "meta-architect", "README.md"),
|
|
116
374
|
]) {
|
|
117
|
-
verifyInstallBlock(file);
|
|
375
|
+
verifyInstallBlock(file, gitTag);
|
|
118
376
|
}
|
|
119
377
|
|
|
120
378
|
const envTag =
|
package/scripts/setup-npmrc.js
CHANGED
|
@@ -1,39 +1,64 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
5
|
+
import os from "node:os";
|
|
4
6
|
import path from "node:path";
|
|
5
7
|
import process from "node:process";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
6
9
|
|
|
7
|
-
function
|
|
8
|
-
|
|
10
|
+
export async function createTemporaryNpmConfig({
|
|
11
|
+
token,
|
|
12
|
+
registry = "https://registry.npmjs.org/",
|
|
13
|
+
scope = "",
|
|
14
|
+
tempRoot = process.env.RUNNER_TEMP || os.tmpdir(),
|
|
15
|
+
} = {}) {
|
|
16
|
+
if (!token) return null;
|
|
17
|
+
const normalizedRegistry = registry.endsWith("/") ? registry : `${registry}/`;
|
|
18
|
+
const host = new URL(normalizedRegistry).host;
|
|
19
|
+
const configPath = path.join(tempRoot, `meta-architect-npmrc-${randomUUID()}`);
|
|
20
|
+
const content = [
|
|
21
|
+
`registry=${normalizedRegistry}`,
|
|
22
|
+
...(scope ? [`${scope}:registry=${normalizedRegistry}`] : []),
|
|
23
|
+
`//${host}/:_authToken=${token}`,
|
|
24
|
+
"",
|
|
25
|
+
].join("\n");
|
|
26
|
+
|
|
27
|
+
await fs.writeFile(configPath, content, { encoding: "utf8", mode: 0o600 });
|
|
28
|
+
await fs.chmod(configPath, 0o600);
|
|
29
|
+
return configPath;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function cleanupTemporaryNpmConfig(configPath) {
|
|
33
|
+
if (!configPath) return false;
|
|
34
|
+
await fs.rm(configPath, { force: true });
|
|
35
|
+
return true;
|
|
9
36
|
}
|
|
10
37
|
|
|
11
38
|
async function main() {
|
|
12
39
|
const token = process.env.NPM_TOKEN || process.env.NODE_AUTH_TOKEN;
|
|
13
40
|
if (!token) {
|
|
14
|
-
console.log("No npm token detected. Skipping
|
|
41
|
+
console.log("No npm token detected. Skipping temporary npm auth config.");
|
|
15
42
|
return;
|
|
16
43
|
}
|
|
17
44
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await fs.writeFile(npmrcPath, content, "utf8");
|
|
31
|
-
console.log(
|
|
32
|
-
`Wrote CI .npmrc for ${scope ? `scope ${scope}` : "the canonical unscoped package"}.`,
|
|
33
|
-
);
|
|
45
|
+
const configPath = await createTemporaryNpmConfig({
|
|
46
|
+
token,
|
|
47
|
+
registry: process.env.NPM_REGISTRY_URL || "https://registry.npmjs.org/",
|
|
48
|
+
scope: process.env.NPM_SCOPE || "",
|
|
49
|
+
});
|
|
50
|
+
if (process.env.GITHUB_ENV) {
|
|
51
|
+
await fs.appendFile(process.env.GITHUB_ENV, `NPM_CONFIG_USERCONFIG=${configPath}\n`);
|
|
52
|
+
}
|
|
53
|
+
console.log("Created temporary npm auth config outside the workspace.");
|
|
54
|
+
if (!process.env.GITHUB_ENV) {
|
|
55
|
+
console.log(`Use NPM_CONFIG_USERCONFIG=${configPath} for the current command.`);
|
|
56
|
+
}
|
|
34
57
|
}
|
|
35
58
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
59
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
60
|
+
main().catch((error) => {
|
|
61
|
+
console.error(error.message);
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import { installSkills } from "../src/skill-installer.js";
|
|
4
|
+
import { installSkills, rollbackInstalledAssets } from "../src/skill-installer.js";
|
|
5
5
|
|
|
6
6
|
function parseArgs(argv) {
|
|
7
|
-
const args = { path: null };
|
|
7
|
+
const args = { path: null, rollback: false };
|
|
8
8
|
for (let index = 0; index < argv.length; index += 1) {
|
|
9
9
|
const token = argv[index];
|
|
10
10
|
if (token === "--path") {
|
|
11
11
|
args.path = argv[index + 1];
|
|
12
12
|
index += 1;
|
|
13
13
|
}
|
|
14
|
+
if (token === "--rollback") args.rollback = true;
|
|
14
15
|
}
|
|
15
16
|
return args;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
async function main() {
|
|
19
20
|
const args = parseArgs(process.argv.slice(2));
|
|
21
|
+
if (args.rollback) {
|
|
22
|
+
console.log(
|
|
23
|
+
JSON.stringify(await rollbackInstalledAssets({ targetRoot: args.path ?? undefined })),
|
|
24
|
+
);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
20
27
|
const { installed } = await installSkills({ targetRoot: args.path ?? undefined });
|
|
21
28
|
for (const skill of installed) {
|
|
22
29
|
console.log(`installed ${skill.name} -> ${skill.dest}`);
|