@aipper/aiws 0.0.29 → 0.0.30
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
package/src/fs.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {string} p
|
|
6
|
-
*/
|
|
7
|
-
export async function pathExists(p) {
|
|
8
|
-
try {
|
|
9
|
-
await fs.access(p);
|
|
10
|
-
return true;
|
|
11
|
-
} catch {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @param {string} p
|
|
18
|
-
*/
|
|
19
|
-
export async function ensureDir(p) {
|
|
20
|
-
await fs.mkdir(p, { recursive: true });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @param {string} p
|
|
25
|
-
*/
|
|
26
|
-
export async function readText(p) {
|
|
27
|
-
return await fs.readFile(p, "utf8");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @param {string} p
|
|
32
|
-
* @param {string} content
|
|
33
|
-
*/
|
|
34
|
-
export async function writeText(p, content) {
|
|
35
|
-
await ensureDir(path.dirname(p));
|
|
36
|
-
await fs.writeFile(p, content, "utf8");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @param {string} src
|
|
41
|
-
* @param {string} dest
|
|
42
|
-
* @param {{ chmod?: number }=} options
|
|
43
|
-
*/
|
|
44
|
-
export async function copyFile(src, dest, options) {
|
|
45
|
-
await ensureDir(path.dirname(dest));
|
|
46
|
-
await fs.copyFile(src, dest);
|
|
47
|
-
if (typeof options?.chmod === "number") {
|
|
48
|
-
await fs.chmod(dest, options.chmod);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
const st = await fs.stat(src);
|
|
53
|
-
await fs.chmod(dest, st.mode & 0o777);
|
|
54
|
-
} catch {
|
|
55
|
-
// ignore chmod errors (e.g. on certain filesystems)
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Very small glob support for patterns ending with `/**`.
|
|
61
|
-
*
|
|
62
|
-
* @param {string} rootDir
|
|
63
|
-
* @param {string} prefixDir
|
|
64
|
-
* @returns {Promise<string[]>} paths relative to rootDir
|
|
65
|
-
*/
|
|
66
|
-
export async function listFilesRecursive(rootDir, prefixDir) {
|
|
67
|
-
/** @type {string[]} */
|
|
68
|
-
const out = [];
|
|
69
|
-
const start = path.join(rootDir, prefixDir);
|
|
70
|
-
if (!(await pathExists(start))) return out;
|
|
71
|
-
|
|
72
|
-
/** @type {Array<{ abs: string, rel: string }>} */
|
|
73
|
-
const stack = [{ abs: start, rel: prefixDir }];
|
|
74
|
-
while (stack.length > 0) {
|
|
75
|
-
const cur = stack.pop();
|
|
76
|
-
if (!cur) break;
|
|
77
|
-
const entries = await fs.readdir(cur.abs, { withFileTypes: true });
|
|
78
|
-
for (const ent of entries) {
|
|
79
|
-
const abs = path.join(cur.abs, ent.name);
|
|
80
|
-
const rel = path.posix.join(cur.rel.replaceAll(path.sep, "/"), ent.name);
|
|
81
|
-
if (ent.isDirectory()) {
|
|
82
|
-
stack.push({ abs, rel });
|
|
83
|
-
} else if (ent.isFile()) {
|
|
84
|
-
out.push(rel);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
out.sort();
|
|
89
|
-
return out;
|
|
90
|
-
}
|
|
91
|
-
|
package/src/governance.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { UserError } from "./errors.js";
|
|
2
|
-
import { loadWorkflowGovernanceRules } from "./spec.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {any} status
|
|
6
|
-
*/
|
|
7
|
-
export function effectiveReviewCount(status) {
|
|
8
|
-
return Number(status?.reviewSignals?.effectiveCount ?? status?.collaboration?.counts?.review ?? 0);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @param {any} status
|
|
13
|
-
* @param {any} [governance]
|
|
14
|
-
*/
|
|
15
|
-
function collectGovernanceSignals(status, governance) {
|
|
16
|
-
const git = status?.git && typeof status.git === "object" ? status.git : {};
|
|
17
|
-
const lifecycle = status?.lifecycle && typeof status.lifecycle === "object" ? status.lifecycle : {};
|
|
18
|
-
const repo = status?.repo && typeof status.repo === "object" ? status.repo : {};
|
|
19
|
-
const gov = governance && typeof governance === "object" ? governance : status?.governance && typeof status.governance === "object" ? status.governance : {};
|
|
20
|
-
const reviewGates = status?.reviewGates && typeof status.reviewGates === "object" ? status.reviewGates : {};
|
|
21
|
-
const reviewGateSummary = reviewGates?.summary && typeof reviewGates.summary === "object" ? reviewGates.summary : {};
|
|
22
|
-
const reviewEffectiveCount = effectiveReviewCount(status);
|
|
23
|
-
const specReviewReady = reviewGates?.specReview?.ready === true || (!reviewGates.specReview && reviewEffectiveCount > 0);
|
|
24
|
-
const qualityReviewReady = reviewGates?.qualityReview?.ready === true || (!reviewGates.qualityReview && reviewEffectiveCount > 0);
|
|
25
|
-
const verifyBeforeCompleteReady = reviewGates?.verifyBeforeComplete?.ready === true;
|
|
26
|
-
const validateStampReady = reviewGates?.validateStamp?.ready === true;
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
change_id: String(status?.changeId || ""),
|
|
30
|
-
blockers_strict_count: Array.isArray(status?.blockersStrict) ? status.blockersStrict.length : 0,
|
|
31
|
-
finish_resume_required: status?.terminatedReuse?.kind === "finished_unarchived",
|
|
32
|
-
tasks_unchecked: Number(status?.tasks?.unchecked || 0),
|
|
33
|
-
review_effective_count: reviewEffectiveCount,
|
|
34
|
-
evidence_persistent_count: Number(status?.evidence?.counts?.persistent || 0),
|
|
35
|
-
git_total: Number(git.total || 0),
|
|
36
|
-
git_staged: Number(git.staged || 0),
|
|
37
|
-
git_conflicted: Number(git.conflicted || 0),
|
|
38
|
-
lifecycle_evidence_runs: Number(lifecycle.evidenceRuns || 0),
|
|
39
|
-
finish_cleanup_pending_reason: String(lifecycle.finishCleanupPendingReason || ""),
|
|
40
|
-
finish_state: String(lifecycle.finishState || ""),
|
|
41
|
-
finish_state_reason: String(lifecycle.finishStateReason || ""),
|
|
42
|
-
repo_submodules: Number(repo.submodules || 0),
|
|
43
|
-
spec_review_ready: specReviewReady,
|
|
44
|
-
quality_review_ready: qualityReviewReady,
|
|
45
|
-
verify_before_complete_ready: verifyBeforeCompleteReady,
|
|
46
|
-
validate_stamp_ready: validateStampReady,
|
|
47
|
-
spec_review_status: String(reviewGates?.specReview?.status || (specReviewReady ? "ready" : "missing")),
|
|
48
|
-
quality_review_status: String(reviewGates?.qualityReview?.status || (qualityReviewReady ? "ready" : "missing")),
|
|
49
|
-
verify_before_complete_status: String(
|
|
50
|
-
reviewGates?.verifyBeforeComplete?.status || (verifyBeforeCompleteReady ? "ready" : "missing"),
|
|
51
|
-
),
|
|
52
|
-
validate_stamp_status: String(reviewGates?.validateStamp?.status || (validateStampReady ? "ready" : "missing")),
|
|
53
|
-
dual_review_missing_count: Number(reviewGateSummary?.dualReviewMissingCount || 0),
|
|
54
|
-
finish_gate_missing_count: Number(reviewGateSummary?.finishGateMissingCount || 0),
|
|
55
|
-
governance_current_stage: String(gov.currentStage || ""),
|
|
56
|
-
governance_recommended_stage: String(gov.recommendedStage || ""),
|
|
57
|
-
governance_rule_id: String(gov.ruleId || ""),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @param {string} template
|
|
63
|
-
* @param {Record<string, string | number | boolean>} signals
|
|
64
|
-
*/
|
|
65
|
-
function renderTemplate(template, signals) {
|
|
66
|
-
return String(template || "").replace(/\{([a-z0-9_]+)\}/gi, (_, key) => String(signals[key] ?? ""));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @param {unknown} actual
|
|
71
|
-
* @param {any} condition
|
|
72
|
-
*/
|
|
73
|
-
function matchesLeafCondition(actual, condition) {
|
|
74
|
-
if (Object.prototype.hasOwnProperty.call(condition, "eq") && actual !== condition.eq) return false;
|
|
75
|
-
if (Object.prototype.hasOwnProperty.call(condition, "ne") && actual === condition.ne) return false;
|
|
76
|
-
if (Object.prototype.hasOwnProperty.call(condition, "gt") && !(Number(actual) > Number(condition.gt))) return false;
|
|
77
|
-
if (Object.prototype.hasOwnProperty.call(condition, "gte") && !(Number(actual) >= Number(condition.gte))) return false;
|
|
78
|
-
if (Object.prototype.hasOwnProperty.call(condition, "lt") && !(Number(actual) < Number(condition.lt))) return false;
|
|
79
|
-
if (Object.prototype.hasOwnProperty.call(condition, "lte") && !(Number(actual) <= Number(condition.lte))) return false;
|
|
80
|
-
if (Array.isArray(condition?.in) && !condition.in.includes(actual)) return false;
|
|
81
|
-
if (Array.isArray(condition?.notIn) && condition.notIn.includes(actual)) return false;
|
|
82
|
-
if (condition?.truthy === true && !actual) return false;
|
|
83
|
-
if (condition?.falsy === true && !!actual) return false;
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @param {any} when
|
|
89
|
-
* @param {Record<string, string | number | boolean>} signals
|
|
90
|
-
*/
|
|
91
|
-
function matchesCondition(when, signals) {
|
|
92
|
-
if (!when || (typeof when === "object" && Object.keys(when).length === 0)) return true;
|
|
93
|
-
if (Array.isArray(when?.all)) return when.all.every((item) => matchesCondition(item, signals));
|
|
94
|
-
if (Array.isArray(when?.any)) return when.any.some((item) => matchesCondition(item, signals));
|
|
95
|
-
if (when?.not) return !matchesCondition(when.not, signals);
|
|
96
|
-
if (typeof when?.signal === "string") {
|
|
97
|
-
return matchesLeafCondition(signals[when.signal], when);
|
|
98
|
-
}
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* @param {string[]} lines
|
|
104
|
-
*/
|
|
105
|
-
function uniqueLines(lines) {
|
|
106
|
-
const seen = new Set();
|
|
107
|
-
/** @type {string[]} */
|
|
108
|
-
const out = [];
|
|
109
|
-
for (const raw of lines || []) {
|
|
110
|
-
const line = String(raw || "").trim();
|
|
111
|
-
if (!line || seen.has(line)) continue;
|
|
112
|
-
seen.add(line);
|
|
113
|
-
out.push(line);
|
|
114
|
-
}
|
|
115
|
-
return out;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @param {any} status
|
|
120
|
-
*/
|
|
121
|
-
export async function inferChangeGovernance(status) {
|
|
122
|
-
const spec = await loadWorkflowGovernanceRules();
|
|
123
|
-
const signals = collectGovernanceSignals(status);
|
|
124
|
-
const matched = spec.governanceRules.find((rule) => matchesCondition(rule?.when, signals));
|
|
125
|
-
if (!matched) {
|
|
126
|
-
throw new UserError("Failed to infer workflow governance from spec rules.", {
|
|
127
|
-
details: JSON.stringify({ source: spec.source, signals }, null, 2),
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
return {
|
|
131
|
-
phase: String(status?.phase || ""),
|
|
132
|
-
currentStage: String(matched.currentStage || ""),
|
|
133
|
-
recommendedStage: String(matched.recommendedStage || matched.currentStage || ""),
|
|
134
|
-
rationale: renderTemplate(String(matched.rationale || ""), signals),
|
|
135
|
-
ruleId: String(matched.id || ""),
|
|
136
|
-
source: spec.source,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {any} status
|
|
142
|
-
*/
|
|
143
|
-
export async function governanceGuidanceLines(status) {
|
|
144
|
-
const spec = await loadWorkflowGovernanceRules();
|
|
145
|
-
const governance = status?.governance && typeof status.governance === "object" ? status.governance : await inferChangeGovernance(status);
|
|
146
|
-
const signals = collectGovernanceSignals(status, governance);
|
|
147
|
-
/** @type {string[]} */
|
|
148
|
-
const lines = [];
|
|
149
|
-
|
|
150
|
-
for (const rule of spec.guidanceRules) {
|
|
151
|
-
if (!matchesCondition(rule?.when, signals)) continue;
|
|
152
|
-
const entries = Array.isArray(rule?.lines) ? rule.lines : [];
|
|
153
|
-
for (const entry of entries) lines.push(renderTemplate(String(entry || ""), signals));
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const deduped = uniqueLines(lines);
|
|
157
|
-
if (deduped.length > 0) return deduped;
|
|
158
|
-
return ["按阶段契约继续推进当前 change"];
|
|
159
|
-
}
|
package/src/hash.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import crypto from "node:crypto";
|
|
2
|
-
import { readText } from "./fs.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {string} s
|
|
6
|
-
*/
|
|
7
|
-
export function normalizeNewlines(s) {
|
|
8
|
-
return s.replaceAll("\r\n", "\n");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @param {string} text
|
|
13
|
-
*/
|
|
14
|
-
export function sha256Text(text) {
|
|
15
|
-
return crypto.createHash("sha256").update(text, "utf8").digest("hex");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param {string} filePath
|
|
20
|
-
*/
|
|
21
|
-
export async function sha256FileText(filePath) {
|
|
22
|
-
const content = normalizeNewlines(await readText(filePath));
|
|
23
|
-
return sha256Text(content);
|
|
24
|
-
}
|
|
25
|
-
|
package/src/json-schema-lite.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { UserError } from "./errors.js";
|
|
2
|
-
|
|
3
|
-
function isPlainObject(value) {
|
|
4
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function joinPath(base, segment) {
|
|
8
|
-
if (!base || base === "$") return `$${segment}`;
|
|
9
|
-
return `${base}${segment}`;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function resolvePointer(rootSchema, ref) {
|
|
13
|
-
if (typeof ref !== "string" || !ref.startsWith("#/")) {
|
|
14
|
-
throw new UserError("Unsupported schema $ref.", { details: String(ref || "") });
|
|
15
|
-
}
|
|
16
|
-
const parts = ref
|
|
17
|
-
.slice(2)
|
|
18
|
-
.split("/")
|
|
19
|
-
.map((part) => part.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
20
|
-
let cur = rootSchema;
|
|
21
|
-
for (const part of parts) {
|
|
22
|
-
if (!isPlainObject(cur) && !Array.isArray(cur)) return undefined;
|
|
23
|
-
cur = cur[part];
|
|
24
|
-
}
|
|
25
|
-
return cur;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function typeMatches(value, type) {
|
|
29
|
-
switch (type) {
|
|
30
|
-
case "object":
|
|
31
|
-
return isPlainObject(value);
|
|
32
|
-
case "array":
|
|
33
|
-
return Array.isArray(value);
|
|
34
|
-
case "string":
|
|
35
|
-
return typeof value === "string";
|
|
36
|
-
case "number":
|
|
37
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
38
|
-
case "integer":
|
|
39
|
-
return typeof value === "number" && Number.isInteger(value);
|
|
40
|
-
case "boolean":
|
|
41
|
-
return typeof value === "boolean";
|
|
42
|
-
case "null":
|
|
43
|
-
return value === null;
|
|
44
|
-
default:
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @param {any} value
|
|
51
|
-
* @param {any} schema
|
|
52
|
-
* @param {any} rootSchema
|
|
53
|
-
* @param {string} curPath
|
|
54
|
-
* @param {string[]} errors
|
|
55
|
-
*/
|
|
56
|
-
function validateNode(value, schema, rootSchema, curPath, errors) {
|
|
57
|
-
if (!isPlainObject(schema)) return;
|
|
58
|
-
|
|
59
|
-
if (schema.$ref) {
|
|
60
|
-
const target = resolvePointer(rootSchema, schema.$ref);
|
|
61
|
-
if (!target) {
|
|
62
|
-
errors.push(`${curPath}: unresolved $ref ${schema.$ref}`);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
validateNode(value, target, rootSchema, curPath, errors);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (Array.isArray(schema.anyOf) && schema.anyOf.length > 0) {
|
|
70
|
-
const matched = schema.anyOf.some((candidate) => {
|
|
71
|
-
const branchErrors = [];
|
|
72
|
-
validateNode(value, candidate, rootSchema, curPath, branchErrors);
|
|
73
|
-
return branchErrors.length === 0;
|
|
74
|
-
});
|
|
75
|
-
if (!matched) errors.push(`${curPath}: does not match anyOf`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (Array.isArray(schema.allOf) && schema.allOf.length > 0) {
|
|
79
|
-
for (const candidate of schema.allOf) validateNode(value, candidate, rootSchema, curPath, errors);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
|
|
83
|
-
let matches = 0;
|
|
84
|
-
for (const candidate of schema.oneOf) {
|
|
85
|
-
const branchErrors = [];
|
|
86
|
-
validateNode(value, candidate, rootSchema, curPath, branchErrors);
|
|
87
|
-
if (branchErrors.length === 0) matches += 1;
|
|
88
|
-
}
|
|
89
|
-
if (matches !== 1) errors.push(`${curPath}: does not match exactly one schema`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (schema.type && !typeMatches(value, schema.type)) {
|
|
93
|
-
errors.push(`${curPath}: expected ${schema.type}`);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (Object.prototype.hasOwnProperty.call(schema, "const") && value !== schema.const) {
|
|
98
|
-
errors.push(`${curPath}: expected const ${JSON.stringify(schema.const)}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
|
|
102
|
-
errors.push(`${curPath}: expected one of ${schema.enum.map((item) => JSON.stringify(item)).join(", ")}`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (typeof value === "string") {
|
|
106
|
-
if (typeof schema.minLength === "number" && value.length < schema.minLength) {
|
|
107
|
-
errors.push(`${curPath}: expected minLength ${schema.minLength}`);
|
|
108
|
-
}
|
|
109
|
-
if (typeof schema.pattern === "string") {
|
|
110
|
-
const re = new RegExp(schema.pattern);
|
|
111
|
-
if (!re.test(value)) errors.push(`${curPath}: does not match pattern ${schema.pattern}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (Array.isArray(value)) {
|
|
116
|
-
if (typeof schema.minItems === "number" && value.length < schema.minItems) {
|
|
117
|
-
errors.push(`${curPath}: expected minItems ${schema.minItems}`);
|
|
118
|
-
}
|
|
119
|
-
if (schema.items) {
|
|
120
|
-
value.forEach((item, index) => validateNode(item, schema.items, rootSchema, joinPath(curPath, `[${index}]`), errors));
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (isPlainObject(value)) {
|
|
125
|
-
const entries = Object.keys(value);
|
|
126
|
-
if (typeof schema.minProperties === "number" && entries.length < schema.minProperties) {
|
|
127
|
-
errors.push(`${curPath}: expected minProperties ${schema.minProperties}`);
|
|
128
|
-
}
|
|
129
|
-
if (typeof schema.maxProperties === "number" && entries.length > schema.maxProperties) {
|
|
130
|
-
errors.push(`${curPath}: expected maxProperties ${schema.maxProperties}`);
|
|
131
|
-
}
|
|
132
|
-
const properties = isPlainObject(schema.properties) ? schema.properties : {};
|
|
133
|
-
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
134
|
-
for (const key of required) {
|
|
135
|
-
if (!Object.prototype.hasOwnProperty.call(value, key)) errors.push(`${curPath}: missing required property ${key}`);
|
|
136
|
-
}
|
|
137
|
-
for (const [key, childSchema] of Object.entries(properties)) {
|
|
138
|
-
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
139
|
-
validateNode(value[key], childSchema, rootSchema, joinPath(curPath, `.${key}`), errors);
|
|
140
|
-
}
|
|
141
|
-
if (schema.additionalProperties === false) {
|
|
142
|
-
for (const key of entries) {
|
|
143
|
-
if (!Object.prototype.hasOwnProperty.call(properties, key)) {
|
|
144
|
-
errors.push(`${curPath}: unexpected property ${key}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @param {any} value
|
|
153
|
-
* @param {any} schema
|
|
154
|
-
* @param {{ source: string }} options
|
|
155
|
-
*/
|
|
156
|
-
export function validateJsonSchemaLite(value, schema, options) {
|
|
157
|
-
const errors = [];
|
|
158
|
-
validateNode(value, schema, schema, "$", errors);
|
|
159
|
-
if (errors.length > 0) {
|
|
160
|
-
throw new UserError("Spec doc schema validation failed.", {
|
|
161
|
-
details: [options?.source || "", ...errors].filter(Boolean).join("\n"),
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
package/src/managed-blocks.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { normalizeNewlines, sha256Text } from "./hash.js";
|
|
2
|
-
import { UserError } from "./errors.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {string} s
|
|
6
|
-
* @returns {string}
|
|
7
|
-
*/
|
|
8
|
-
function escapeRegExp(s) {
|
|
9
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param {string} text
|
|
14
|
-
* @param {string} blockId
|
|
15
|
-
* @returns {{ beginLineIndex: number, endLineIndex: number, innerText: string, beginLine: string, endLine: string } | null}
|
|
16
|
-
*/
|
|
17
|
-
export function findManagedBlock(text, blockId) {
|
|
18
|
-
const t = normalizeNewlines(text);
|
|
19
|
-
const lines = t.split("\n");
|
|
20
|
-
const beginRe = new RegExp(`AIWS_MANAGED_BEGIN:${escapeRegExp(blockId)}(?:\\s|$|-->)`);
|
|
21
|
-
const endRe = new RegExp(`AIWS_MANAGED_END:${escapeRegExp(blockId)}(?:\\s|$|-->)`);
|
|
22
|
-
|
|
23
|
-
let beginLineIndex = -1;
|
|
24
|
-
let endLineIndex = -1;
|
|
25
|
-
|
|
26
|
-
for (let i = 0; i < lines.length; i++) {
|
|
27
|
-
if (beginLineIndex === -1 && beginRe.test(lines[i] ?? "")) {
|
|
28
|
-
beginLineIndex = i;
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
if (beginLineIndex !== -1 && endRe.test(lines[i] ?? "")) {
|
|
32
|
-
endLineIndex = i;
|
|
33
|
-
break;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (beginLineIndex === -1 || endLineIndex === -1 || endLineIndex <= beginLineIndex) return null;
|
|
38
|
-
|
|
39
|
-
const innerLines = lines.slice(beginLineIndex + 1, endLineIndex);
|
|
40
|
-
let innerText = innerLines.join("\n");
|
|
41
|
-
if (innerLines.length > 0) innerText += "\n";
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
beginLineIndex,
|
|
45
|
-
endLineIndex,
|
|
46
|
-
innerText,
|
|
47
|
-
beginLine: lines[beginLineIndex] ?? "",
|
|
48
|
-
endLine: lines[endLineIndex] ?? "",
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Extract the canonical block chunk (begin+inner+end) from a template file.
|
|
54
|
-
*
|
|
55
|
-
* @param {string} templateText
|
|
56
|
-
* @param {string} blockId
|
|
57
|
-
* @returns {{ blockChunk: string, innerText: string }}
|
|
58
|
-
*/
|
|
59
|
-
export function extractTemplateBlock(templateText, blockId) {
|
|
60
|
-
const t = normalizeNewlines(templateText);
|
|
61
|
-
const block = findManagedBlock(t, blockId);
|
|
62
|
-
if (!block) {
|
|
63
|
-
throw new UserError(`Template is missing managed block: ${blockId}`, { exitCode: 1 });
|
|
64
|
-
}
|
|
65
|
-
const blockChunk = `${block.beginLine}\n${block.innerText}${block.endLine}\n`;
|
|
66
|
-
return { blockChunk, innerText: block.innerText };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @param {string} targetText
|
|
71
|
-
* @param {string} blockId
|
|
72
|
-
* @param {string} newInnerText normalized; may end with "\n"
|
|
73
|
-
* @param {{ insertIfMissing: boolean, templateBlockChunk?: string } } options
|
|
74
|
-
* @returns {{ nextText: string, changed: boolean, inserted: boolean }}
|
|
75
|
-
*/
|
|
76
|
-
export function upsertManagedBlock(targetText, blockId, newInnerText, options) {
|
|
77
|
-
const original = normalizeNewlines(targetText);
|
|
78
|
-
const block = findManagedBlock(original, blockId);
|
|
79
|
-
if (!block) {
|
|
80
|
-
if (!options.insertIfMissing) {
|
|
81
|
-
throw new UserError(`Missing managed block: ${blockId}`);
|
|
82
|
-
}
|
|
83
|
-
if (!options.templateBlockChunk) {
|
|
84
|
-
throw new UserError(`Cannot insert managed block without template chunk: ${blockId}`, { exitCode: 1 });
|
|
85
|
-
}
|
|
86
|
-
const nextText = insertBlockAtTop(original, options.templateBlockChunk);
|
|
87
|
-
return { nextText, changed: true, inserted: true };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const lines = original.split("\n");
|
|
91
|
-
const begin = lines.slice(0, block.beginLineIndex + 1);
|
|
92
|
-
const end = lines.slice(block.endLineIndex);
|
|
93
|
-
|
|
94
|
-
const innerLines = newInnerText.endsWith("\n") ? newInnerText.slice(0, -1).split("\n") : newInnerText.split("\n");
|
|
95
|
-
const rebuilt = [...begin, ...innerLines, ...end].join("\n");
|
|
96
|
-
|
|
97
|
-
return { nextText: rebuilt, changed: rebuilt !== original, inserted: false };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Insert block chunk near the top with minimal disruption:
|
|
102
|
-
* - If the file starts with a Markdown heading (`# ...`), insert after the first line.
|
|
103
|
-
* - Otherwise, insert at the very top.
|
|
104
|
-
*
|
|
105
|
-
* @param {string} text normalized
|
|
106
|
-
* @param {string} blockChunk normalized; should end with "\n"
|
|
107
|
-
*/
|
|
108
|
-
function insertBlockAtTop(text, blockChunk) {
|
|
109
|
-
const t = normalizeNewlines(text);
|
|
110
|
-
const chunk = normalizeNewlines(blockChunk).endsWith("\n") ? normalizeNewlines(blockChunk) : `${normalizeNewlines(blockChunk)}\n`;
|
|
111
|
-
|
|
112
|
-
const lines = t.split("\n");
|
|
113
|
-
if (lines.length > 0 && (lines[0] ?? "").startsWith("# ")) {
|
|
114
|
-
const after = lines.slice(1).join("\n");
|
|
115
|
-
const head = `${lines[0]}\n`;
|
|
116
|
-
return `${head}\n${chunk}\n${after}`.replace(/\n{3,}/g, "\n\n");
|
|
117
|
-
}
|
|
118
|
-
return `${chunk}\n${t}`.replace(/\n{3,}/g, "\n\n");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* @param {string} text
|
|
123
|
-
* @param {string} blockId
|
|
124
|
-
*/
|
|
125
|
-
export function hashManagedBlockInner(text, blockId) {
|
|
126
|
-
const block = findManagedBlock(text, blockId);
|
|
127
|
-
if (!block) {
|
|
128
|
-
throw new UserError(`Missing managed block: ${blockId}`);
|
|
129
|
-
}
|
|
130
|
-
return sha256Text(block.innerText);
|
|
131
|
-
}
|