@aipper/aiws 0.0.29 → 0.0.31
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/bin/aiws.js +2 -2
- package/dist/aiws-package.d.ts +4 -0
- package/dist/aiws-package.js +11 -0
- package/dist/aiws-package.js.map +1 -0
- package/dist/aiws-paths.d.ts +48 -0
- package/dist/aiws-paths.js +129 -0
- package/dist/aiws-paths.js.map +1 -0
- package/dist/backup.d.ts +27 -0
- package/dist/backup.js +125 -0
- package/dist/backup.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +773 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-prompts.d.ts +17 -0
- package/dist/codex-prompts.js +49 -0
- package/dist/codex-prompts.js.map +1 -0
- package/dist/codex-skills.d.ts +17 -0
- package/dist/codex-skills.js +75 -0
- package/dist/codex-skills.js.map +1 -0
- package/dist/commands/change-advice.d.ts +25 -0
- package/dist/commands/change-advice.js +197 -0
- package/dist/commands/change-advice.js.map +1 -0
- package/dist/commands/change-evidence-command.d.ts +29 -0
- package/dist/commands/change-evidence-command.js +213 -0
- package/dist/commands/change-evidence-command.js.map +1 -0
- package/dist/commands/change-evidence-entry.d.ts +16 -0
- package/dist/commands/change-evidence-entry.js +35 -0
- package/dist/commands/change-evidence-entry.js.map +1 -0
- package/dist/commands/change-evidence.d.ts +108 -0
- package/dist/commands/change-evidence.js +341 -0
- package/dist/commands/change-evidence.js.map +1 -0
- package/dist/commands/change-finish.d.ts +71 -0
- package/dist/commands/change-finish.js +387 -0
- package/dist/commands/change-finish.js.map +1 -0
- package/dist/commands/change-git-status.d.ts +22 -0
- package/dist/commands/change-git-status.js +50 -0
- package/dist/commands/change-git-status.js.map +1 -0
- package/dist/commands/change-lifecycle-entry.d.ts +29 -0
- package/{src → dist}/commands/change-lifecycle-entry.js +21 -28
- package/dist/commands/change-lifecycle-entry.js.map +1 -0
- package/dist/commands/change-lifecycle.d.ts +56 -0
- package/dist/commands/change-lifecycle.js +211 -0
- package/dist/commands/change-lifecycle.js.map +1 -0
- package/dist/commands/change-metrics-command.d.ts +12 -0
- package/dist/commands/change-metrics-command.js +110 -0
- package/dist/commands/change-metrics-command.js.map +1 -0
- package/dist/commands/change-next-command.d.ts +18 -0
- package/dist/commands/change-next-command.js +138 -0
- package/dist/commands/change-next-command.js.map +1 -0
- package/dist/commands/change-review-gates.d.ts +107 -0
- package/dist/commands/change-review-gates.js +329 -0
- package/dist/commands/change-review-gates.js.map +1 -0
- package/dist/commands/change-scope-gate.d.ts +21 -0
- package/dist/commands/change-scope-gate.js +32 -0
- package/dist/commands/change-scope-gate.js.map +1 -0
- package/dist/commands/change-start.d.ts +30 -0
- package/dist/commands/change-start.js +91 -0
- package/dist/commands/change-start.js.map +1 -0
- package/dist/commands/change-state-command.d.ts +3 -0
- package/dist/commands/change-state-command.js +32 -0
- package/dist/commands/change-state-command.js.map +1 -0
- package/dist/commands/change-status-command.d.ts +13 -0
- package/dist/commands/change-status-command.js +126 -0
- package/dist/commands/change-status-command.js.map +1 -0
- package/dist/commands/change-status-context.d.ts +58 -0
- package/dist/commands/change-status-context.js +166 -0
- package/dist/commands/change-status-context.js.map +1 -0
- package/dist/commands/change-task-stats.d.ts +24 -0
- package/dist/commands/change-task-stats.js +66 -0
- package/dist/commands/change-task-stats.js.map +1 -0
- package/dist/commands/change-validate-entry.d.ts +17 -0
- package/dist/commands/change-validate-entry.js +44 -0
- package/dist/commands/change-validate-entry.js.map +1 -0
- package/dist/commands/change-validate.d.ts +32 -0
- package/dist/commands/change-validate.js +128 -0
- package/dist/commands/change-validate.js.map +1 -0
- package/dist/commands/change.d.ts +322 -0
- package/dist/commands/change.js +1731 -0
- package/dist/commands/change.js.map +1 -0
- package/dist/commands/codex-install-prompts.d.ts +4 -0
- package/dist/commands/codex-install-prompts.js +68 -0
- package/dist/commands/codex-install-prompts.js.map +1 -0
- package/dist/commands/codex-install-skills.d.ts +4 -0
- package/dist/commands/codex-install-skills.js +74 -0
- package/dist/commands/codex-install-skills.js.map +1 -0
- package/dist/commands/codex-status-prompts.d.ts +4 -0
- package/dist/commands/codex-status-prompts.js +44 -0
- package/dist/commands/codex-status-prompts.js.map +1 -0
- package/dist/commands/codex-status-skills.d.ts +4 -0
- package/dist/commands/codex-status-skills.js +54 -0
- package/dist/commands/codex-status-skills.js.map +1 -0
- package/dist/commands/codex-uninstall-prompts.d.ts +4 -0
- package/dist/commands/codex-uninstall-prompts.js +51 -0
- package/dist/commands/codex-uninstall-prompts.js.map +1 -0
- package/dist/commands/codex-uninstall-skills.d.ts +4 -0
- package/dist/commands/codex-uninstall-skills.js +59 -0
- package/dist/commands/codex-uninstall-skills.js.map +1 -0
- package/dist/commands/dashboard.d.ts +222 -0
- package/dist/commands/dashboard.js +193 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/hooks-install.d.ts +4 -0
- package/dist/commands/hooks-install.js +90 -0
- package/dist/commands/hooks-install.js.map +1 -0
- package/dist/commands/hooks-status.d.ts +4 -0
- package/dist/commands/hooks-status.js +89 -0
- package/dist/commands/hooks-status.js.map +1 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +100 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/opencode-auto.d.ts +11 -0
- package/dist/commands/opencode-auto.js +158 -0
- package/dist/commands/opencode-auto.js.map +1 -0
- package/dist/commands/opencode-status.d.ts +4 -0
- package/dist/commands/opencode-status.js +75 -0
- package/dist/commands/opencode-status.js.map +1 -0
- package/dist/commands/opencode-supervise.d.ts +24 -0
- package/dist/commands/opencode-supervise.js +188 -0
- package/dist/commands/opencode-supervise.js.map +1 -0
- package/dist/commands/rollback.d.ts +4 -0
- package/dist/commands/rollback.js +12 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/update.d.ts +4 -0
- package/dist/commands/update.js +212 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +4 -0
- package/dist/commands/validate.js +222 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/ws-commit.d.ts +5 -0
- package/dist/commands/ws-commit.js +39 -0
- package/dist/commands/ws-commit.js.map +1 -0
- package/dist/commands/ws-deliver.d.ts +5 -0
- package/dist/commands/ws-deliver.js +59 -0
- package/dist/commands/ws-deliver.js.map +1 -0
- package/dist/commands/ws-finish.d.ts +5 -0
- package/dist/commands/ws-finish.js +142 -0
- package/dist/commands/ws-finish.js.map +1 -0
- package/dist/commands/ws-handoff.d.ts +5 -0
- package/dist/commands/ws-handoff.js +35 -0
- package/dist/commands/ws-handoff.js.map +1 -0
- package/dist/commands/ws-migrate.d.ts +5 -0
- package/dist/commands/ws-migrate.js +41 -0
- package/dist/commands/ws-migrate.js.map +1 -0
- package/dist/commands/ws-plan-verify.d.ts +5 -0
- package/dist/commands/ws-plan-verify.js +38 -0
- package/dist/commands/ws-plan-verify.js.map +1 -0
- package/dist/commands/ws-pull.d.ts +5 -0
- package/dist/commands/ws-pull.js +26 -0
- package/dist/commands/ws-pull.js.map +1 -0
- package/dist/commands/ws-push.d.ts +5 -0
- package/dist/commands/ws-push.js +68 -0
- package/dist/commands/ws-push.js.map +1 -0
- package/dist/commands/ws-submodule-setup.d.ts +5 -0
- package/dist/commands/ws-submodule-setup.js +55 -0
- package/dist/commands/ws-submodule-setup.js.map +1 -0
- package/dist/commands/ws-verify-before-complete.d.ts +5 -0
- package/dist/commands/ws-verify-before-complete.js +35 -0
- package/dist/commands/ws-verify-before-complete.js.map +1 -0
- package/dist/dashboard/app.d.ts +1 -0
- package/dist/dashboard/app.js +370 -0
- package/dist/dashboard/app.js.map +1 -0
- package/dist/delegation/cli.d.ts +6 -0
- package/dist/delegation/cli.js +14 -0
- package/dist/delegation/cli.js.map +1 -0
- package/dist/delegation/index.d.ts +35 -0
- package/dist/delegation/index.js +118 -0
- package/dist/delegation/index.js.map +1 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/exec.d.ts +9 -0
- package/dist/exec.js +22 -0
- package/dist/exec.js.map +1 -0
- package/dist/fs.d.ts +9 -0
- package/dist/fs.js +62 -0
- package/dist/fs.js.map +1 -0
- package/dist/governance.d.ts +10 -0
- package/dist/governance.js +135 -0
- package/dist/governance.js.map +1 -0
- package/dist/hash.d.ts +3 -0
- package/dist/hash.js +13 -0
- package/dist/hash.js.map +1 -0
- package/dist/hooks/deploy-claude.d.ts +13 -0
- package/dist/hooks/deploy-claude.js +67 -0
- package/dist/hooks/deploy-claude.js.map +1 -0
- package/dist/journal.d.ts +22 -0
- package/dist/journal.js +112 -0
- package/dist/journal.js.map +1 -0
- package/dist/json-schema-lite.d.ts +22 -0
- package/dist/json-schema-lite.js +148 -0
- package/dist/json-schema-lite.js.map +1 -0
- package/dist/managed-blocks.d.ts +24 -0
- package/dist/managed-blocks.js +84 -0
- package/dist/managed-blocks.js.map +1 -0
- package/dist/manifest.d.ts +24 -0
- package/dist/manifest.js +145 -0
- package/dist/manifest.js.map +1 -0
- package/dist/opencode-env.d.ts +62 -0
- package/dist/opencode-env.js +178 -0
- package/dist/opencode-env.js.map +1 -0
- package/dist/path-utils.d.ts +2 -0
- package/dist/path-utils.js +8 -0
- package/dist/path-utils.js.map +1 -0
- package/dist/spec.d.ts +17 -0
- package/dist/spec.js +174 -0
- package/dist/spec.js.map +1 -0
- package/dist/template.d.ts +20 -0
- package/dist/template.js +123 -0
- package/dist/template.js.map +1 -0
- package/dist/workspace.d.ts +4 -0
- package/dist/workspace.js +19 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +11 -3
- package/src/aiws-package.js +0 -15
- package/src/backup.js +0 -149
- package/src/cli.js +0 -760
- package/src/codex-prompts.js +0 -74
- package/src/codex-skills.js +0 -111
- package/src/commands/change-advice.js +0 -181
- package/src/commands/change-evidence-command.js +0 -242
- package/src/commands/change-evidence-entry.js +0 -40
- package/src/commands/change-evidence.js +0 -340
- package/src/commands/change-finish.js +0 -413
- package/src/commands/change-git-status.js +0 -53
- package/src/commands/change-lifecycle.js +0 -236
- package/src/commands/change-metrics-command.js +0 -110
- package/src/commands/change-next-command.js +0 -133
- package/src/commands/change-review-gates.js +0 -331
- package/src/commands/change-scope-gate.js +0 -34
- package/src/commands/change-start.js +0 -85
- package/src/commands/change-state-command.js +0 -40
- package/src/commands/change-status-command.js +0 -125
- package/src/commands/change-status-context.js +0 -173
- package/src/commands/change-task-stats.js +0 -64
- package/src/commands/change-validate-entry.js +0 -45
- package/src/commands/change-validate.js +0 -127
- package/src/commands/change.js +0 -1829
- package/src/commands/codex-install-prompts.js +0 -68
- package/src/commands/codex-install-skills.js +0 -74
- package/src/commands/codex-status-prompts.js +0 -55
- package/src/commands/codex-status-skills.js +0 -63
- package/src/commands/codex-uninstall-prompts.js +0 -55
- package/src/commands/codex-uninstall-skills.js +0 -62
- package/src/commands/dashboard.js +0 -205
- package/src/commands/hooks-install.js +0 -92
- package/src/commands/hooks-status.js +0 -95
- package/src/commands/init.js +0 -101
- package/src/commands/opencode-auto.js +0 -167
- package/src/commands/opencode-status.js +0 -103
- package/src/commands/opencode-supervise.js +0 -200
- package/src/commands/rollback.js +0 -13
- package/src/commands/update.js +0 -145
- package/src/commands/validate.js +0 -228
- package/src/commands/ws-commit.js +0 -44
- package/src/commands/ws-deliver.js +0 -67
- package/src/commands/ws-finish.js +0 -83
- package/src/commands/ws-handoff.js +0 -40
- package/src/commands/ws-migrate.js +0 -41
- package/src/commands/ws-plan-verify.js +0 -44
- package/src/commands/ws-pull.js +0 -30
- package/src/commands/ws-push.js +0 -71
- package/src/commands/ws-submodule-setup.js +0 -65
- package/src/commands/ws-verify-before-complete.js +0 -39
- package/src/dashboard/app.js +0 -371
- package/src/errors.js +0 -15
- package/src/exec.js +0 -34
- package/src/fs.js +0 -91
- package/src/governance.js +0 -159
- package/src/hash.js +0 -25
- package/src/json-schema-lite.js +0 -164
- package/src/managed-blocks.js +0 -131
- package/src/manifest.js +0 -177
- package/src/opencode-env.js +0 -208
- package/src/path-utils.js +0 -20
- package/src/spec.js +0 -195
- package/src/template.js +0 -187
- package/src/workspace.js +0 -23
- /package/{src → dist}/dashboard/index.html +0 -0
- /package/{src → dist}/dashboard/style.css +0 -0
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
2
|
-
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
-
import { UserError } from "../errors.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* aiws plan-verify — check plan completeness
|
|
7
|
-
* @param {{ cwd?: string }} opts
|
|
8
|
-
*/
|
|
9
|
-
export async function wsPlanVerifyCommand({ cwd = "." } = {}) {
|
|
10
|
-
const planDir = `${cwd}/plan`;
|
|
11
|
-
if (!existsSync(planDir)) {
|
|
12
|
-
throw new UserError("No plan/ directory found", { exitCode: 2 });
|
|
13
|
-
}
|
|
14
|
-
const plans = readdirSync(planDir).filter(f => f.endsWith(".md"));
|
|
15
|
-
if (plans.length === 0) {
|
|
16
|
-
throw new UserError("No plan files found in plan/", { exitCode: 2 });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const failures = [];
|
|
20
|
-
for (const planFile of plans) {
|
|
21
|
-
const content = readFileSync(`${planDir}/${planFile}`, "utf8");
|
|
22
|
-
const checks = [];
|
|
23
|
-
|
|
24
|
-
checks.push({ name: "Goal", pass: /^##?\s*Goal/im.test(content) });
|
|
25
|
-
checks.push({ name: "Non-goals", pass: /^##?\s*Non-goals/im.test(content) });
|
|
26
|
-
checks.push({ name: "Scope", pass: /^##?\s*(Scope|In Scope)/im.test(content) });
|
|
27
|
-
checks.push({ name: "Verify", pass: /^##?\s*Verify/im.test(content) });
|
|
28
|
-
checks.push({ name: "Risks", pass: /^##?\s*Risks/im.test(content) });
|
|
29
|
-
|
|
30
|
-
const failed = checks.filter(c => !c.pass);
|
|
31
|
-
if (failed.length > 0) {
|
|
32
|
-
failures.push({ file: planFile, missing: failed.map(c => c.name) });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (failures.length > 0) {
|
|
37
|
-
for (const f of failures) {
|
|
38
|
-
console.error(`error: ${f.file} missing sections: ${f.missing.join(", ")}`);
|
|
39
|
-
}
|
|
40
|
-
throw new UserError("Plan verification failed. Fix missing sections.", { exitCode: 1 });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.log("ok: plan verification passed");
|
|
44
|
-
}
|
package/src/commands/ws-pull.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { UserError } from "../errors.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* aiws pull — git pull --ff-only + submodule sync
|
|
7
|
-
* @param {{ cwd?: string }} opts
|
|
8
|
-
*/
|
|
9
|
-
export async function wsPullCommand({ cwd = "." } = {}) {
|
|
10
|
-
checkClean(cwd);
|
|
11
|
-
|
|
12
|
-
// git pull --ff-only
|
|
13
|
-
execSync("git pull --ff-only", { cwd, stdio: "inherit" });
|
|
14
|
-
|
|
15
|
-
// submodule sync if .gitmodules exists
|
|
16
|
-
if (existsSync(`${cwd}/.gitmodules`)) {
|
|
17
|
-
console.log("info: submodules detected, syncing...");
|
|
18
|
-
execSync("git submodule sync --recursive", { cwd, stdio: "inherit" });
|
|
19
|
-
execSync("git submodule update --init --recursive", { cwd, stdio: "inherit" });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
console.log("ok: pull complete");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function checkClean(cwd) {
|
|
26
|
-
const out = execSync("git status --porcelain", { cwd, encoding: "utf8" }).trim();
|
|
27
|
-
if (out) {
|
|
28
|
-
throw new UserError("Working tree is not clean. Commit or stash first.", { exitCode: 2 });
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/commands/ws-push.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
-
import { UserError } from "../errors.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* aiws push — submodule-aware push (submodules first, then superproject)
|
|
7
|
-
* @param {{ cwd?: string, remote?: string }} opts
|
|
8
|
-
*/
|
|
9
|
-
export async function wsPushCommand({ cwd = ".", remote = "origin" } = {}) {
|
|
10
|
-
checkClean(cwd);
|
|
11
|
-
|
|
12
|
-
if (existsSync(`${cwd}/.gitmodules`)) {
|
|
13
|
-
pushSubmodules(cwd, remote);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const branch = execSync("git branch --show-current", { cwd, encoding: "utf8" }).trim();
|
|
17
|
-
console.log(`info: pushing ${branch} to ${remote}...`);
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
execSync(`git push ${remote} ${branch}`, { cwd, stdio: "inherit" });
|
|
21
|
-
} catch {
|
|
22
|
-
throw new UserError("Push failed. Check for diverged branch.", { exitCode: 1 });
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
console.log("ok: push complete");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function pushSubmodules(cwd, remote) {
|
|
29
|
-
const targetFile = findSubmodulesTargets(cwd);
|
|
30
|
-
if (!targetFile) {
|
|
31
|
-
console.log("info: no submodules.targets found, skipping submodule push");
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const content = readFileSync(targetFile, "utf8");
|
|
36
|
-
for (const line of content.split("\n")) {
|
|
37
|
-
const trimmed = line.trim();
|
|
38
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
39
|
-
const [subPath, targetBranch, rmt = remote] = trimmed.split(/\s+/);
|
|
40
|
-
if (!subPath || !targetBranch) continue;
|
|
41
|
-
|
|
42
|
-
console.log(`info: pushing submodule ${subPath} (${targetBranch})...`);
|
|
43
|
-
try {
|
|
44
|
-
execSync(`git push ${rmt} ${targetBranch}`, { cwd: `${cwd}/${subPath}`, stdio: "inherit" });
|
|
45
|
-
} catch {
|
|
46
|
-
throw new UserError(`Failed to push submodule ${subPath}`, { exitCode: 1 });
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function findSubmodulesTargets(cwd) {
|
|
52
|
-
const paths = [
|
|
53
|
-
`${cwd}/changes/*/submodules.targets`,
|
|
54
|
-
];
|
|
55
|
-
// Find first match using shell expansion
|
|
56
|
-
try {
|
|
57
|
-
const out = execSync("ls changes/*/submodules.targets 2>/dev/null || true", { cwd, encoding: "utf8" }).trim();
|
|
58
|
-
if (out) {
|
|
59
|
-
const first = out.split("\n")[0];
|
|
60
|
-
if (first) return `${cwd}/${first}`;
|
|
61
|
-
}
|
|
62
|
-
} catch { /* ignore */ }
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function checkClean(cwd) {
|
|
67
|
-
const out = execSync("git status --porcelain", { cwd, encoding: "utf8" }).trim();
|
|
68
|
-
if (out) {
|
|
69
|
-
throw new UserError("Working tree is not clean. Commit or stash first.", { exitCode: 2 });
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { UserError } from "../errors.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* aiws submodule-setup — set .gitmodules branch for each submodule
|
|
7
|
-
* @param {{ cwd?: string, branch?: string }} opts
|
|
8
|
-
*/
|
|
9
|
-
export async function wsSubmoduleSetupCommand({ cwd = ".", branch = "main" } = {}) {
|
|
10
|
-
checkClean(cwd);
|
|
11
|
-
|
|
12
|
-
if (!existsSync(`${cwd}/.gitmodules`)) {
|
|
13
|
-
console.log("info: no .gitmodules found, nothing to configure");
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// List submodules
|
|
18
|
-
const out = execSync("git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$'", {
|
|
19
|
-
cwd, encoding: "utf8",
|
|
20
|
-
}).trim();
|
|
21
|
-
|
|
22
|
-
if (!out) {
|
|
23
|
-
console.log("info: no submodules in .gitmodules");
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const lines = out.split("\n");
|
|
28
|
-
for (const line of lines) {
|
|
29
|
-
const parts = line.trim().split(/\s+/);
|
|
30
|
-
if (parts.length < 2) continue;
|
|
31
|
-
const key = parts[0]; // submodule.<name>.path
|
|
32
|
-
const subPath = parts[1];
|
|
33
|
-
const name = key.replace(/^submodule\./, "").replace(/\.path$/, "");
|
|
34
|
-
|
|
35
|
-
// Check if branch already set
|
|
36
|
-
const existing = execSync(
|
|
37
|
-
`git config --file .gitmodules --get submodule.${name}.branch 2>/dev/null || true`,
|
|
38
|
-
{ cwd, encoding: "utf8" }
|
|
39
|
-
).trim();
|
|
40
|
-
|
|
41
|
-
if (existing) {
|
|
42
|
-
console.log(`info: ${subPath} branch already set: ${existing}`);
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Detect current branch
|
|
47
|
-
let detected = branch;
|
|
48
|
-
try {
|
|
49
|
-
const current = execSync(`git -C "${subPath}" branch --show-current 2>/dev/null || true`, { cwd, encoding: "utf8" }).trim();
|
|
50
|
-
if (current) detected = current;
|
|
51
|
-
} catch { /* use default */ }
|
|
52
|
-
|
|
53
|
-
console.log(`info: setting ${subPath} branch → ${detected}`);
|
|
54
|
-
execSync(`git submodule set-branch --branch ${detected} ${name}`, { cwd, stdio: "inherit" });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
console.log("ok: submodule branches configured. Review .gitmodules changes before committing.");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function checkClean(cwd) {
|
|
61
|
-
const out = execSync("git status --porcelain", { cwd, encoding: "utf8" }).trim();
|
|
62
|
-
if (out) {
|
|
63
|
-
throw new UserError("Working tree is not clean. Commit or stash first.", { exitCode: 2 });
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
-
import { UserError } from "../errors.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* aiws verify-bc — verify before complete (check review + validate)
|
|
6
|
-
* @param {{ cwd?: string }} opts
|
|
7
|
-
*/
|
|
8
|
-
export async function wsVerifyBeforeCompleteCommand({ cwd = "." } = {}) {
|
|
9
|
-
const missing = [];
|
|
10
|
-
|
|
11
|
-
// Check spec-review
|
|
12
|
-
const changesDir = `${cwd}/changes`;
|
|
13
|
-
if (existsSync(changesDir)) {
|
|
14
|
-
const changes = readdirSync(changesDir).filter(f => !f.startsWith(".") && f !== "templates" && f !== "archive");
|
|
15
|
-
const hasSpecReview = changes.some(c =>
|
|
16
|
-
existsSync(`${changesDir}/${c}/review/spec-review.md`)
|
|
17
|
-
);
|
|
18
|
-
const hasQualityReview = changes.some(c =>
|
|
19
|
-
existsSync(`${changesDir}/${c}/review/quality-review.md`)
|
|
20
|
-
);
|
|
21
|
-
if (!hasSpecReview) missing.push("spec-review.md");
|
|
22
|
-
if (!hasQualityReview) missing.push("quality-review.md");
|
|
23
|
-
} else {
|
|
24
|
-
missing.push("changes/ directory not found");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Check validate stamp
|
|
28
|
-
const stampDir = `${cwd}/.agentdocs/tmp/aiws-validate`;
|
|
29
|
-
const hasStamp = existsSync(stampDir) && readdirSync(stampDir).some(f => f.endsWith(".json"));
|
|
30
|
-
if (!hasStamp) {
|
|
31
|
-
console.log("warn: no validate stamp found. Run aiws validate . --stamp");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (missing.length > 0) {
|
|
35
|
-
throw new UserError(`Missing gates: ${missing.join(", ")}`, { exitCode: 1 });
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
console.log("ok: all gates passed");
|
|
39
|
-
}
|
package/src/dashboard/app.js
DELETED
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
async function fetchJson(url) {
|
|
2
|
-
const res = await fetch(url, { headers: { "Accept": "application/json" } });
|
|
3
|
-
const text = await res.text();
|
|
4
|
-
let data = null;
|
|
5
|
-
try {
|
|
6
|
-
data = JSON.parse(text);
|
|
7
|
-
} catch {
|
|
8
|
-
data = { ok: false, error: "invalid json", raw: text };
|
|
9
|
-
}
|
|
10
|
-
if (!res.ok) {
|
|
11
|
-
return { ok: false, status: res.status, ...data };
|
|
12
|
-
}
|
|
13
|
-
return data;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function escapeHtml(s) {
|
|
17
|
-
return String(s || "")
|
|
18
|
-
.replaceAll("&", "&")
|
|
19
|
-
.replaceAll("<", "<")
|
|
20
|
-
.replaceAll(">", ">")
|
|
21
|
-
.replaceAll("\"", """)
|
|
22
|
-
.replaceAll("'", "'");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function blockersBadge(n) {
|
|
26
|
-
const cls = n === 0 ? "good" : n <= 2 ? "warn" : "bad";
|
|
27
|
-
return `<span class="badge"><span class="dot ${cls}"></span>${n === 0 ? "none" : `${n} blockers`}</span>`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function driftBadge(n) {
|
|
31
|
-
const cls = n === 0 ? "good" : "warn";
|
|
32
|
-
return `<span class="badge"><span class="dot ${cls}"></span>${n === 0 ? "clean" : `${n} drift`}</span>`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function tasksBadge(done, total, unchecked) {
|
|
36
|
-
const cls = unchecked === 0 && total > 0 ? "good" : unchecked === 0 ? "warn" : "warn";
|
|
37
|
-
const label = total > 0 ? `${done}/${total} (unchecked=${unchecked})` : "no tasks";
|
|
38
|
-
return `<span class="badge"><span class="dot ${cls}"></span>${label}</span>`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function summarizeNextAdvice(advice) {
|
|
42
|
-
const a = advice && typeof advice === "object" ? advice : {};
|
|
43
|
-
const actions = Array.isArray(a.actions) ? a.actions : [];
|
|
44
|
-
const recommended = Array.isArray(a.recommended) ? a.recommended : [];
|
|
45
|
-
const prohibitions = Array.isArray(a.prohibitions) ? a.prohibitions : [];
|
|
46
|
-
return actions[0] || recommended[0] || prohibitions[0] || "";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function renderDetails(obj) {
|
|
50
|
-
return JSON.stringify(obj, null, 2);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function renderValidateGroups(groups) {
|
|
54
|
-
const order = [
|
|
55
|
-
["truth_drift", "Truth drift"],
|
|
56
|
-
["missing_files", "Missing files"],
|
|
57
|
-
["placeholders", "Placeholders / WS:TODO"],
|
|
58
|
-
["bindings", "Bindings"],
|
|
59
|
-
["scope_gate", "Scope gate"],
|
|
60
|
-
["finish_gate", "Finish gate"],
|
|
61
|
-
["plan_quality", "Plan quality"],
|
|
62
|
-
["other", "Other"],
|
|
63
|
-
];
|
|
64
|
-
const g = groups && typeof groups === "object" ? groups : {};
|
|
65
|
-
const lines = [];
|
|
66
|
-
for (const [key, label] of order) {
|
|
67
|
-
const it = g[key] || { errors: [], warnings: [] };
|
|
68
|
-
const errs = Array.isArray(it.errors) ? it.errors : [];
|
|
69
|
-
const warns = Array.isArray(it.warnings) ? it.warnings : [];
|
|
70
|
-
if (errs.length === 0 && warns.length === 0) continue;
|
|
71
|
-
lines.push(`${label}:`);
|
|
72
|
-
for (const e of errs) lines.push(` - error: ${e}`);
|
|
73
|
-
for (const w of warns) lines.push(` - warn: ${w}`);
|
|
74
|
-
lines.push("");
|
|
75
|
-
}
|
|
76
|
-
return lines.join("\n").trim();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async function runStrictValidate(changeId) {
|
|
80
|
-
return fetchJson(`/api/change/${encodeURIComponent(changeId)}/validate?strict=1`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function normalizeStageId(value) {
|
|
84
|
-
return String(value || "").trim();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function stageLabel(stageId) {
|
|
88
|
-
return normalizeStageId(stageId) || "(unknown)";
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function renderContractField(label, value) {
|
|
92
|
-
return `<div class="contract-field">
|
|
93
|
-
<div class="contract-field-label">${escapeHtml(label)}</div>
|
|
94
|
-
<div>${escapeHtml(value || "(none)")}</div>
|
|
95
|
-
</div>`;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function renderContractCard(title, contract) {
|
|
99
|
-
if (!contract) return "";
|
|
100
|
-
return `<div class="contract-card">
|
|
101
|
-
<div class="contract-title">${escapeHtml(title)}</div>
|
|
102
|
-
<div class="contract-stage"><code>${escapeHtml(contract.stage || "")}</code></div>
|
|
103
|
-
${renderContractField("目标", contract.goal)}
|
|
104
|
-
${renderContractField("必需输入", contract.requiredInputs)}
|
|
105
|
-
${renderContractField("必需输出", contract.requiredOutputs)}
|
|
106
|
-
${renderContractField("阻断条件", contract.blockers)}
|
|
107
|
-
${renderContractField("下一步", contract.next)}
|
|
108
|
-
</div>`;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function normalizeGateStatus(value) {
|
|
112
|
-
return String(value || "missing").trim() || "missing";
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function reviewGateText(reviewGates) {
|
|
116
|
-
const gates = reviewGates && typeof reviewGates === "object" ? reviewGates : {};
|
|
117
|
-
const spec = normalizeGateStatus(gates?.specReview?.status);
|
|
118
|
-
const quality = normalizeGateStatus(gates?.qualityReview?.status);
|
|
119
|
-
const validate = normalizeGateStatus(gates?.validateStamp?.status);
|
|
120
|
-
const preComplete = normalizeGateStatus(gates?.verifyBeforeComplete?.status);
|
|
121
|
-
return `review-gates: spec=${spec}, quality=${quality}, validate=${validate}, pre-complete=${preComplete}`;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function renderReviewGateBadges(reviewGates) {
|
|
125
|
-
const gates = reviewGates && typeof reviewGates === "object" ? reviewGates : {};
|
|
126
|
-
const items = [
|
|
127
|
-
["spec", gates?.specReview],
|
|
128
|
-
["quality", gates?.qualityReview],
|
|
129
|
-
["validate", gates?.validateStamp],
|
|
130
|
-
["pre-complete", gates?.verifyBeforeComplete],
|
|
131
|
-
];
|
|
132
|
-
return `<div class="governance-head">${items
|
|
133
|
-
.map(([label, gate]) => {
|
|
134
|
-
const ready = gate?.ready === true;
|
|
135
|
-
const status = normalizeGateStatus(gate?.status);
|
|
136
|
-
const cls = ready ? "good" : "warn";
|
|
137
|
-
return `<span class="badge"><span class="dot ${cls}"></span>${escapeHtml(`${label}=${status}`)}</span>`;
|
|
138
|
-
})
|
|
139
|
-
.join("")}</div>`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function scopeGateText(scopeGate) {
|
|
143
|
-
const gate = scopeGate && typeof scopeGate === "object" ? scopeGate : {};
|
|
144
|
-
const status = String(gate.status || "not_run").trim() || "not_run";
|
|
145
|
-
const details = [];
|
|
146
|
-
if (typeof gate.errors === "number") details.push(`errors=${gate.errors}`);
|
|
147
|
-
if (typeof gate.warnings === "number") details.push(`warnings=${gate.warnings}`);
|
|
148
|
-
if (gate.lastRunAt) details.push(`at=${gate.lastRunAt}`);
|
|
149
|
-
return `scope-gate: ${status}${details.length > 0 ? ` (${details.join(", ")})` : ""}`;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function renderScopeGateBadge(scopeGate) {
|
|
153
|
-
const gate = scopeGate && typeof scopeGate === "object" ? scopeGate : {};
|
|
154
|
-
const status = String(gate.status || "not_run").trim() || "not_run";
|
|
155
|
-
const ready = gate.ready === true;
|
|
156
|
-
const cls = ready ? "good" : status === "failed" ? "bad" : "warn";
|
|
157
|
-
return `<span class="badge"><span class="dot ${cls}"></span>${escapeHtml(`scope=${status}`)}</span>`;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function renderGovernanceSummary(selected, stageData) {
|
|
161
|
-
const governance = selected?.governance && typeof selected.governance === "object" ? selected.governance : {};
|
|
162
|
-
const currentStage = normalizeStageId(governance.currentStage);
|
|
163
|
-
const recommendedStage = normalizeStageId(governance.recommendedStage);
|
|
164
|
-
const phase = normalizeStageId(governance.phase || selected?.phase);
|
|
165
|
-
const contracts = Array.isArray(stageData?.stages) ? stageData.stages : [];
|
|
166
|
-
const byStage = new Map(contracts.map((contract) => [normalizeStageId(contract.stage), contract]));
|
|
167
|
-
const currentContract = byStage.get(currentStage) || null;
|
|
168
|
-
const recommendedContract = byStage.get(recommendedStage) || null;
|
|
169
|
-
|
|
170
|
-
const rail = contracts.length > 0
|
|
171
|
-
? `<div class="governance-rail">${contracts
|
|
172
|
-
.map((contract, index) => {
|
|
173
|
-
const stage = normalizeStageId(contract.stage);
|
|
174
|
-
const cls = [
|
|
175
|
-
"stage-chip",
|
|
176
|
-
stage === currentStage ? "active" : "",
|
|
177
|
-
stage === recommendedStage && stage !== currentStage ? "recommended" : "",
|
|
178
|
-
]
|
|
179
|
-
.filter(Boolean)
|
|
180
|
-
.join(" ");
|
|
181
|
-
const arrow = index < contracts.length - 1 ? `<span class="rail-arrow">→</span>` : "";
|
|
182
|
-
return `<span class="${cls}"><code>${escapeHtml(stageLabel(stage))}</code></span>${arrow}`;
|
|
183
|
-
})
|
|
184
|
-
.join("")}</div>`
|
|
185
|
-
: `<div class="muted">(workflow-stage-contracts unavailable)</div>`;
|
|
186
|
-
|
|
187
|
-
const cards = [];
|
|
188
|
-
if (currentContract) cards.push(renderContractCard(`Current Contract (${phase || "unknown"})`, currentContract));
|
|
189
|
-
if (recommendedContract && recommendedStage && recommendedStage !== currentStage) {
|
|
190
|
-
cards.push(renderContractCard("Next Contract", recommendedContract));
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return `<div class="governance-head">
|
|
194
|
-
<span class="badge"><span class="dot good"></span>phase=${escapeHtml(phase || "(unknown)")}</span>
|
|
195
|
-
<span class="badge"><span class="dot warn"></span>current=${escapeHtml(stageLabel(currentStage))}</span>
|
|
196
|
-
<span class="badge"><span class="dot good"></span>next=${escapeHtml(stageLabel(recommendedStage || currentStage))}</span>
|
|
197
|
-
</div>
|
|
198
|
-
${governance.rationale ? `<div class="muted">${escapeHtml(governance.rationale)}</div>` : ""}
|
|
199
|
-
${governance.warning ? `<div class="muted">warning: ${escapeHtml(governance.warning)}</div>` : ""}
|
|
200
|
-
${selected?.reviewGates ? renderReviewGateBadges(selected.reviewGates) : ""}
|
|
201
|
-
${selected?.scopeGate ? `<div class="governance-head">${renderScopeGateBadge(selected.scopeGate)}</div>` : ""}
|
|
202
|
-
${rail}
|
|
203
|
-
<div class="governance-grid">
|
|
204
|
-
${cards.join("") || `<div class="muted">No contract summary available.</div>`}
|
|
205
|
-
</div>`;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async function refresh() {
|
|
209
|
-
const summaryEl = document.getElementById("summary");
|
|
210
|
-
const bodyEl = document.getElementById("changes-body");
|
|
211
|
-
const detailsTitleEl = document.getElementById("details-title");
|
|
212
|
-
const detailsEl = document.getElementById("details");
|
|
213
|
-
const governanceEl = document.getElementById("governance-summary");
|
|
214
|
-
|
|
215
|
-
summaryEl.textContent = "Loading…";
|
|
216
|
-
bodyEl.innerHTML = "";
|
|
217
|
-
if (governanceEl) governanceEl.innerHTML = `<div class="muted">Loading workflow governance…</div>`;
|
|
218
|
-
|
|
219
|
-
const [data, stageData] = await Promise.all([fetchJson("/api/changes"), fetchJson("/api/workflow-stages")]);
|
|
220
|
-
if (!data || data.ok === false) {
|
|
221
|
-
summaryEl.textContent = "Failed";
|
|
222
|
-
detailsTitleEl.textContent = "Error";
|
|
223
|
-
detailsEl.textContent = renderDetails(data);
|
|
224
|
-
if (governanceEl) governanceEl.innerHTML = `<div class="muted">Failed to load governance summary.</div>`;
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const items = Array.isArray(data.changes) ? data.changes : [];
|
|
229
|
-
summaryEl.textContent = `${items.length} change(s)`;
|
|
230
|
-
|
|
231
|
-
bodyEl.innerHTML = items
|
|
232
|
-
.map((c) => {
|
|
233
|
-
const changeId = c.changeId || c.id || "";
|
|
234
|
-
const tasks = c.tasks || {};
|
|
235
|
-
const drift = Array.isArray(c.driftFiles) ? c.driftFiles.length : 0;
|
|
236
|
-
const blockers = Array.isArray(c.blockersStrict) ? c.blockersStrict.length : 0;
|
|
237
|
-
const bindings = c.bindings || {};
|
|
238
|
-
const planFile = bindings.planFile || "";
|
|
239
|
-
const evidencePaths = Array.isArray(bindings.evidencePaths) ? bindings.evidencePaths : [];
|
|
240
|
-
const collaboration = c.collaboration && typeof c.collaboration === "object" ? c.collaboration : {};
|
|
241
|
-
const nextHint = summarizeNextAdvice(c.nextAdvice);
|
|
242
|
-
const governance = c.governance && typeof c.governance === "object" ? c.governance : {};
|
|
243
|
-
const reviewGateLine = reviewGateText(c.reviewGates);
|
|
244
|
-
const scopeGateLine = scopeGateText(c.scopeGate);
|
|
245
|
-
const collabLabel = `analysis=${collaboration.analysis || 0}, patches=${collaboration.patches || 0}, review=${collaboration.review || 0}`;
|
|
246
|
-
const stageLine = `phase=${governance.phase || c.phase || "unknown"}, current=${governance.currentStage || "unknown"}, next=${governance.recommendedStage || governance.currentStage || "unknown"}`;
|
|
247
|
-
const rationaleLine = governance.rationale ? `<div class="muted">${escapeHtml(governance.rationale)}</div>` : "";
|
|
248
|
-
const warningLine = governance.warning ? `<div class="muted">warning: ${escapeHtml(governance.warning)}</div>` : "";
|
|
249
|
-
const pe = `${planFile ? `<div><code>${escapeHtml(planFile)}</code></div>` : `<div class="muted">(no Plan_File)</div>`}
|
|
250
|
-
<div class="muted">${evidencePaths.length} evidence path(s)</div>
|
|
251
|
-
<div class="muted">${escapeHtml(collabLabel)}</div>
|
|
252
|
-
<div class="muted">${escapeHtml(stageLine)}</div>
|
|
253
|
-
<div class="muted">${escapeHtml(reviewGateLine)}</div>
|
|
254
|
-
<div class="muted">${escapeHtml(scopeGateLine)}</div>
|
|
255
|
-
${rationaleLine}
|
|
256
|
-
${warningLine}
|
|
257
|
-
${nextHint ? `<div class="muted">${escapeHtml(nextHint)}</div>` : ""}`;
|
|
258
|
-
return `<tr data-change="${escapeHtml(changeId)}">
|
|
259
|
-
<td><a class="link" href="#" data-open="${escapeHtml(changeId)}">${escapeHtml(changeId)}</a></td>
|
|
260
|
-
<td>${tasksBadge(tasks.done || 0, tasks.total || 0, tasks.unchecked || 0)}</td>
|
|
261
|
-
<td>${driftBadge(drift)}</td>
|
|
262
|
-
<td>${blockersBadge(blockers)}</td>
|
|
263
|
-
<td>${pe}</td>
|
|
264
|
-
<td>
|
|
265
|
-
<button class="btn secondary" data-validate="${escapeHtml(changeId)}">Validate --strict</button>
|
|
266
|
-
</td>
|
|
267
|
-
</tr>`;
|
|
268
|
-
})
|
|
269
|
-
.join("");
|
|
270
|
-
|
|
271
|
-
bodyEl.querySelectorAll("[data-open]").forEach((a) => {
|
|
272
|
-
a.addEventListener("click", (ev) => {
|
|
273
|
-
ev.preventDefault();
|
|
274
|
-
const changeId = a.getAttribute("data-open") || "";
|
|
275
|
-
const selected = items.find((x) => (x.changeId || x.id) === changeId) || null;
|
|
276
|
-
detailsTitleEl.textContent = changeId ? `change: ${changeId}` : "Details";
|
|
277
|
-
if (!selected) {
|
|
278
|
-
detailsEl.textContent = renderDetails(selected);
|
|
279
|
-
if (governanceEl) governanceEl.innerHTML = `<div class="muted">No governance summary available.</div>`;
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
if (governanceEl) governanceEl.innerHTML = renderGovernanceSummary(selected, stageData);
|
|
283
|
-
const b = selected.bindings || {};
|
|
284
|
-
const governance = selected.governance && typeof selected.governance === "object" ? selected.governance : {};
|
|
285
|
-
const evid = Array.isArray(b.evidencePaths) ? b.evidencePaths : [];
|
|
286
|
-
const lines = [];
|
|
287
|
-
lines.push(`changeId: ${selected.changeId || ""}`);
|
|
288
|
-
if (selected.reqId) lines.push(`Req_ID: ${selected.reqId}`);
|
|
289
|
-
if (selected.probId) lines.push(`Problem_ID: ${selected.probId}`);
|
|
290
|
-
if (b.planFile) lines.push(`Plan_File: ${b.planFile}`);
|
|
291
|
-
if (b.contractRow) lines.push(`Contract_Row: ${b.contractRow}`);
|
|
292
|
-
if (evid.length > 0) {
|
|
293
|
-
lines.push("Evidence_Path:");
|
|
294
|
-
for (const p of evid) lines.push(`- ${p}`);
|
|
295
|
-
}
|
|
296
|
-
if (selected.collaboration && typeof selected.collaboration === "object") {
|
|
297
|
-
lines.push("Collaboration:");
|
|
298
|
-
lines.push(`- analysis: ${selected.collaboration.analysis || 0}`);
|
|
299
|
-
lines.push(`- patches: ${selected.collaboration.patches || 0}`);
|
|
300
|
-
lines.push(`- review: ${selected.collaboration.review || 0}`);
|
|
301
|
-
lines.push(`- evidence: ${selected.collaboration.evidence || 0}`);
|
|
302
|
-
}
|
|
303
|
-
if (selected.reviewGates && typeof selected.reviewGates === "object") {
|
|
304
|
-
lines.push("");
|
|
305
|
-
lines.push("Review gates:");
|
|
306
|
-
lines.push(`- ${reviewGateText(selected.reviewGates)}`);
|
|
307
|
-
for (const [label, gate] of [
|
|
308
|
-
["ws-spec-review", selected.reviewGates.specReview],
|
|
309
|
-
["ws-quality-review", selected.reviewGates.qualityReview],
|
|
310
|
-
["validate-stamp", selected.reviewGates.validateStamp],
|
|
311
|
-
["ws-verify-before-complete", selected.reviewGates.verifyBeforeComplete],
|
|
312
|
-
]) {
|
|
313
|
-
if (!gate || typeof gate !== "object") continue;
|
|
314
|
-
const foundPath = gate.foundPath ? ` path=${gate.foundPath}` : "";
|
|
315
|
-
lines.push(`- ${label}: ready=${gate.ready === true} status=${normalizeGateStatus(gate.status)}${foundPath}`);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
if (selected.scopeGate && typeof selected.scopeGate === "object") {
|
|
319
|
-
lines.push("");
|
|
320
|
-
lines.push("Scope gate:");
|
|
321
|
-
lines.push(`- ${scopeGateText(selected.scopeGate)}`);
|
|
322
|
-
}
|
|
323
|
-
if (selected.nextAdvice && typeof selected.nextAdvice === "object") {
|
|
324
|
-
const actions = Array.isArray(selected.nextAdvice.actions) ? selected.nextAdvice.actions : [];
|
|
325
|
-
const recommended = Array.isArray(selected.nextAdvice.recommended) ? selected.nextAdvice.recommended : [];
|
|
326
|
-
const prohibitions = Array.isArray(selected.nextAdvice.prohibitions) ? selected.nextAdvice.prohibitions : [];
|
|
327
|
-
if (actions.length > 0 || recommended.length > 0 || prohibitions.length > 0) {
|
|
328
|
-
lines.push("");
|
|
329
|
-
lines.push("Next:");
|
|
330
|
-
for (const x of actions) lines.push(`- action: ${x}`);
|
|
331
|
-
for (const x of recommended) lines.push(`- recommended: ${x}`);
|
|
332
|
-
for (const x of prohibitions) lines.push(`- do-not: ${x}`);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
if (governance.rationale) {
|
|
336
|
-
lines.push("");
|
|
337
|
-
lines.push(`Governance rationale: ${governance.rationale}`);
|
|
338
|
-
}
|
|
339
|
-
if (governance.warning) {
|
|
340
|
-
lines.push(`Governance warning: ${governance.warning}`);
|
|
341
|
-
}
|
|
342
|
-
if (Array.isArray(selected.blockersStrict) && selected.blockersStrict.length > 0) {
|
|
343
|
-
lines.push("");
|
|
344
|
-
lines.push("Blockers (strict):");
|
|
345
|
-
for (const x of selected.blockersStrict) lines.push(`- ${x}`);
|
|
346
|
-
}
|
|
347
|
-
lines.push("");
|
|
348
|
-
lines.push("Raw JSON:");
|
|
349
|
-
lines.push(renderDetails(selected));
|
|
350
|
-
detailsEl.textContent = lines.join("\n");
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
bodyEl.querySelectorAll("[data-validate]").forEach((btn) => {
|
|
355
|
-
btn.addEventListener("click", async () => {
|
|
356
|
-
const changeId = btn.getAttribute("data-validate") || "";
|
|
357
|
-
if (!changeId) return;
|
|
358
|
-
btn.disabled = true;
|
|
359
|
-
btn.textContent = "Running…";
|
|
360
|
-
detailsTitleEl.textContent = `validate --strict: ${changeId}`;
|
|
361
|
-
const res = await runStrictValidate(changeId);
|
|
362
|
-
const grouped = renderValidateGroups(res && res.groups ? res.groups : null);
|
|
363
|
-
detailsEl.textContent = grouped ? `${grouped}\n\nRaw JSON:\n${renderDetails(res)}` : renderDetails(res);
|
|
364
|
-
btn.disabled = false;
|
|
365
|
-
btn.textContent = "Validate --strict";
|
|
366
|
-
});
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
document.getElementById("refresh")?.addEventListener("click", refresh);
|
|
371
|
-
refresh();
|
package/src/errors.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export class UserError extends Error {
|
|
2
|
-
/**
|
|
3
|
-
* @param {string} message
|
|
4
|
-
* @param {{ exitCode?: number, details?: string }=} options
|
|
5
|
-
*/
|
|
6
|
-
constructor(message, options) {
|
|
7
|
-
super(message);
|
|
8
|
-
this.name = "UserError";
|
|
9
|
-
/** @type {number} */
|
|
10
|
-
this.exitCode = options?.exitCode ?? 2;
|
|
11
|
-
/** @type {string | undefined} */
|
|
12
|
-
this.details = options?.details;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
package/src/exec.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @param {string} command
|
|
5
|
-
* @param {string[]} args
|
|
6
|
-
* @param {{ cwd?: string }=} options
|
|
7
|
-
* @returns {Promise<{ code: number, stdout: string, stderr: string }>}
|
|
8
|
-
*/
|
|
9
|
-
export function runCommand(command, args, options) {
|
|
10
|
-
return new Promise((resolve, reject) => {
|
|
11
|
-
const child = spawn(command, args, {
|
|
12
|
-
cwd: options?.cwd,
|
|
13
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
/** @type {Buffer[]} */
|
|
17
|
-
const out = [];
|
|
18
|
-
/** @type {Buffer[]} */
|
|
19
|
-
const err = [];
|
|
20
|
-
|
|
21
|
-
child.stdout.on("data", (b) => out.push(Buffer.from(b)));
|
|
22
|
-
child.stderr.on("data", (b) => err.push(Buffer.from(b)));
|
|
23
|
-
|
|
24
|
-
child.on("error", (e) => reject(e));
|
|
25
|
-
child.on("close", (code) => {
|
|
26
|
-
resolve({
|
|
27
|
-
code: typeof code === "number" ? code : 1,
|
|
28
|
-
stdout: Buffer.concat(out).toString("utf8"),
|
|
29
|
-
stderr: Buffer.concat(err).toString("utf8"),
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|