@aipper/aiws 0.0.32 → 0.0.33

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-utils.js","sourceRoot":"","sources":["../../src/commands/change-utils.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,4 @@
1
- /**
2
- * @param {string} changeId
3
- */
4
- export declare function assertValidChangeId(changeId: string): void;
1
+ export { assertValidChangeId } from "./change-utils.js";
5
2
  export declare function computeChangeStatus(gitRoot: any, changeId: any): Promise<{
6
3
  governance: {
7
4
  warning: string;
@@ -1,4 +1,3 @@
1
- import crypto from "node:crypto";
2
1
  import path from "node:path";
3
2
  import fs from "node:fs/promises";
4
3
  import { runCommand } from "../exec.js";
@@ -27,18 +26,8 @@ import { renderChangeStatusOutput } from "./change-status-command.js";
27
26
  import { validateChangeArtifacts as validateChangeArtifactsModel } from "./change-validate.js";
28
27
  import { prepareNoSwitchBranch, switchOrCreateStartBranch, maybeRecordBaseBranch, } from "./change-start.js";
29
28
  import { hooksInstallCommand } from "./hooks-install.js";
30
- /**
31
- * @param {string} text
32
- */
33
- function countWsTodo(text) {
34
- return (text.match(/WS:TODO/g) || []).length;
35
- }
36
- /**
37
- * @param {string} text
38
- */
39
- function countPlaceholders(text) {
40
- return (text.match(/{{CHANGE_ID}}|{{TITLE}}|{{CREATED_AT}}/g) || []).length;
41
- }
29
+ import { assertValidChangeId, changeDirAbs, checkGitClean, countPlaceholders, countWsTodo, currentBranch, ensureTruthFiles, extractBulletsUnderHeading, extractId, hasHeadCommit, inferChangeIdFromBranch, isMeaningfulBullet, nowIsoUtc, nowStampUtc, nowUnixSeconds, parseArchivedChangeDirName, renderTemplate, resolveGitRoot, snapshotTruthFiles, snapshotTruthShaOnly, splitDeclaredValues, todayLocal, } from "./change-utils.js";
30
+ export { assertValidChangeId } from "./change-utils.js";
42
31
  /**
43
32
  * @param {string} changeDir
44
33
  * @param {string} rel
@@ -87,9 +76,6 @@ async function appendMetricsEvent(gitRoot, changeId, type, payload) {
87
76
  const changeDir = changeDirAbs(gitRoot, changeId);
88
77
  await appendMetricsEventAtDir(changeDir, changeId, type, payload);
89
78
  }
90
- /**
91
- * @param {string} gitRoot
92
- */
93
79
  async function resolveTemplateIdForRepo(gitRoot) {
94
80
  const manifestPath = path.join(gitRoot, ".aiws", "manifest.json");
95
81
  if (!(await pathExists(manifestPath)))
@@ -103,10 +89,6 @@ async function resolveTemplateIdForRepo(gitRoot) {
103
89
  return "workspace";
104
90
  }
105
91
  }
106
- /**
107
- * @param {string} gitRoot
108
- * @returns {Promise<{ templateDir: string, resolvedFrom: string }>}
109
- */
110
92
  async function resolveChangeTemplatesDir(gitRoot) {
111
93
  const candidates = [
112
94
  { dir: path.join(gitRoot, ".aiws", "changes", "templates"), label: `${gitRoot}/.aiws/changes/templates` },
@@ -127,17 +109,6 @@ async function resolveChangeTemplatesDir(gitRoot) {
127
109
  }
128
110
  return { templateDir: fallback, resolvedFrom: `@aipper/aiws-spec:${tpl.templateId}` };
129
111
  }
130
- /**
131
- * @param {string} templateText
132
- * @param {{ changeId: string, title: string, createdAt: string }} vars
133
- */
134
- function renderTemplate(templateText, vars) {
135
- return templateText.replaceAll("{{CHANGE_ID}}", vars.changeId).replaceAll("{{TITLE}}", vars.title).replaceAll("{{CREATED_AT}}", vars.createdAt);
136
- }
137
- /**
138
- * @param {string} gitRoot
139
- * @returns {Promise<{ path: string, args: string[] }>}
140
- */
141
112
  async function resolveWsChangeChecker(gitRoot) {
142
113
  const local = path.join(gitRoot, ".aiws", "tools", "ws_change_check.py");
143
114
  if (await pathExists(local))
@@ -150,10 +121,6 @@ async function resolveWsChangeChecker(gitRoot) {
150
121
  }
151
122
  return { path: fallback, args: [fallback] };
152
123
  }
153
- /**
154
- * @param {string} gitRoot
155
- * @param {string[]} args
156
- */
157
124
  async function runPython(gitRoot, args) {
158
125
  let res;
159
126
  try {
@@ -180,266 +147,6 @@ async function resolveChangeId(gitRoot, changeId, options) {
180
147
  }
181
148
  throw new UserError(`usage: aiws change ${options.command} <change-id> (or switch to branch change/<change-id>)`);
182
149
  }
183
- /**
184
- * @param {string} gitRoot
185
- * @param {string} changeId
186
- */
187
- function changeDirAbs(gitRoot, changeId) {
188
- return path.join(gitRoot, ".aiws", "changes", changeId);
189
- }
190
- const CHANGE_BRANCH_RE = /^(change|changes|ws|ws-change)\/([a-z0-9]+(?:-[a-z0-9]+)*)$/;
191
- const CHANGE_ID_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
192
- /**
193
- * @param {string} changeId
194
- */
195
- export function assertValidChangeId(changeId) {
196
- if (!changeId || !CHANGE_ID_RE.test(changeId)) {
197
- throw new UserError(`Invalid change id (use kebab-case): ${changeId}`);
198
- }
199
- }
200
- /**
201
- * @returns {string} e.g. 2026-01-28T14:00:26Z
202
- */
203
- function nowIsoUtc() {
204
- return new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
205
- }
206
- /**
207
- * @returns {number} unix seconds
208
- */
209
- function nowUnixSeconds() {
210
- return Math.floor(Date.now() / 1000);
211
- }
212
- /**
213
- * @returns {string} e.g. 20260128-140026Z
214
- */
215
- function nowStampUtc() {
216
- const d = new Date();
217
- const y = String(d.getUTCFullYear());
218
- const m = String(d.getUTCMonth() + 1).padStart(2, "0");
219
- const day = String(d.getUTCDate()).padStart(2, "0");
220
- const hh = String(d.getUTCHours()).padStart(2, "0");
221
- const mm = String(d.getUTCMinutes()).padStart(2, "0");
222
- const ss = String(d.getUTCSeconds()).padStart(2, "0");
223
- return `${y}${m}${day}-${hh}${mm}${ss}Z`;
224
- }
225
- /**
226
- * @returns {string} e.g. 2026-01-28 (local date)
227
- */
228
- function todayLocal() {
229
- const d = new Date();
230
- const y = String(d.getFullYear());
231
- const m = String(d.getMonth() + 1).padStart(2, "0");
232
- const day = String(d.getDate()).padStart(2, "0");
233
- return `${y}-${m}-${day}`;
234
- }
235
- /**
236
- * @param {string} absPath
237
- */
238
- async function resolveGitRoot(absPath) {
239
- let res;
240
- try {
241
- res = await runCommand("git", ["rev-parse", "--show-toplevel"], { cwd: absPath });
242
- }
243
- catch (e) {
244
- throw new UserError("git is required for aiws change commands.", { details: e instanceof Error ? e.message : String(e) });
245
- }
246
- if (res.code !== 0) {
247
- throw new UserError("Not a git repository.", { details: res.stderr || res.stdout });
248
- }
249
- const root = String(res.stdout || "").trim();
250
- if (!root)
251
- throw new UserError("Failed to resolve git repository root.");
252
- return root;
253
- }
254
- /**
255
- * @param {string} gitRoot
256
- * @returns {Promise<string>} branch or empty
257
- */
258
- async function currentBranch(gitRoot) {
259
- const res = await runCommand("git", ["symbolic-ref", "--quiet", "--short", "HEAD"], { cwd: gitRoot });
260
- if (res.code !== 0)
261
- return "";
262
- return String(res.stdout || "").trim();
263
- }
264
- /**
265
- * @param {string} gitRoot
266
- */
267
- async function hasHeadCommit(gitRoot) {
268
- return runCommand("git", ["rev-parse", "--verify", "HEAD"], { cwd: gitRoot }).then((r) => r.code === 0);
269
- }
270
- /**
271
- * @param {string} gitRoot
272
- * @returns {Promise<{ clean: true } | { clean: false, details: string }>}
273
- */
274
- async function checkGitClean(gitRoot) {
275
- const res = await runCommand("git", ["status", "--porcelain"], { cwd: gitRoot });
276
- const out = String(res.stdout || "").trim();
277
- if (!out)
278
- return { clean: true };
279
- const lines = out.split("\n");
280
- const truncated = lines.length > 20 ? `${lines.slice(0, 20).join("\n")}\n... (truncated)` : out;
281
- return { clean: false, details: truncated };
282
- }
283
- /**
284
- * @param {string} branch
285
- */
286
- function inferChangeIdFromBranch(branch) {
287
- const m = CHANGE_BRANCH_RE.exec(branch || "");
288
- return m?.[2] || "";
289
- }
290
- /**
291
- * @param {string} gitRoot
292
- */
293
- async function ensureTruthFiles(gitRoot) {
294
- const required = ["AI_PROJECT.md", "AI_WORKSPACE.md", "REQUIREMENTS.md"];
295
- const missing = [];
296
- for (const f of required) {
297
- if (!(await pathExists(path.join(gitRoot, f))))
298
- missing.push(f);
299
- }
300
- if (missing.length > 0) {
301
- throw new UserError("AI Workspace truth files missing.", {
302
- details: `Root: ${gitRoot}\nMissing:\n${missing.map((m) => `- ${m}`).join("\n")}\n\nHint: run \`aiws init .\` (new) or \`aiws update .\` (migrate).`,
303
- });
304
- }
305
- }
306
- /**
307
- * @param {string} filePath
308
- * @returns {Promise<string>}
309
- */
310
- async function sha256FileBytes(filePath) {
311
- const buf = await fs.readFile(filePath);
312
- return crypto.createHash("sha256").update(buf).digest("hex");
313
- }
314
- /**
315
- * @param {string} gitRoot
316
- * @returns {Promise<Record<string, {mtime: number, sha256: string}>>}
317
- */
318
- async function snapshotTruthFiles(gitRoot) {
319
- const truth = {};
320
- for (const rel of ["AI_PROJECT.md", "AI_WORKSPACE.md", "REQUIREMENTS.md"]) {
321
- const abs = path.join(gitRoot, rel);
322
- if (!(await pathExists(abs)))
323
- continue;
324
- const st = await fs.stat(abs);
325
- truth[rel] = { mtime: Math.floor(st.mtimeMs / 1000), sha256: await sha256FileBytes(abs) };
326
- }
327
- return truth;
328
- }
329
- /**
330
- * @param {string} gitRoot
331
- * @returns {Promise<Record<string, string | null>>}
332
- */
333
- async function snapshotTruthShaOnly(gitRoot) {
334
- const out = {};
335
- for (const rel of ["AI_PROJECT.md", "AI_WORKSPACE.md", "REQUIREMENTS.md"]) {
336
- const abs = path.join(gitRoot, rel);
337
- if (!(await pathExists(abs))) {
338
- out[rel] = null;
339
- continue;
340
- }
341
- try {
342
- out[rel] = await sha256FileBytes(abs);
343
- }
344
- catch {
345
- out[rel] = null;
346
- }
347
- }
348
- return out;
349
- }
350
- /**
351
- * @param {string} s
352
- */
353
- function escapeRegExp(s) {
354
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
355
- }
356
- /**
357
- * @param {string} label
358
- * @param {string} text
359
- */
360
- function extractId(label, text) {
361
- const re = new RegExp(`^.*${escapeRegExp(label)}.*?[:=][ \\t]*(.*)$`, "m");
362
- const m = re.exec(text);
363
- if (!m)
364
- return "";
365
- let v = String(m[1] || "").trim();
366
- v = v.replace(/<!--.*?-->/g, "").trim();
367
- v = v.replace(/^`+/, "").replace(/`+$/, "").trim();
368
- return v;
369
- }
370
- /**
371
- * @param {string} s
372
- */
373
- function splitDeclaredValues(s) {
374
- return String(s || "")
375
- .split(/[,;\n]+/g)
376
- .map((x) => x.trim().replace(/^`+/, "").replace(/`+$/, "").trim())
377
- .filter(Boolean);
378
- }
379
- /**
380
- * Extract bullet lines under a markdown "## ..." heading.
381
- *
382
- * @param {string} text
383
- * @param {RegExp} headingRe
384
- * @param {{ max?: number }} [options]
385
- * @returns {string[]} trimmed bullet lines like "- foo"
386
- */
387
- function extractBulletsUnderHeading(text, headingRe, options) {
388
- const max = typeof options?.max === "number" ? options.max : 5;
389
- const lines = String(text || "").split("\n");
390
- let inSection = false;
391
- /** @type {string[]} */
392
- const out = [];
393
- for (const raw of lines) {
394
- const line = String(raw || "");
395
- const trimmed = line.trim();
396
- if (!inSection) {
397
- if (headingRe.test(trimmed))
398
- inSection = true;
399
- continue;
400
- }
401
- if (/^##\s+/.test(trimmed))
402
- break;
403
- if (trimmed.startsWith("-")) {
404
- out.push(trimmed);
405
- if (out.length >= max)
406
- break;
407
- }
408
- }
409
- return out;
410
- }
411
- /**
412
- * @param {string} bulletLine
413
- */
414
- function isMeaningfulBullet(bulletLine) {
415
- const s = String(bulletLine || "").trim();
416
- if (!s.startsWith("-"))
417
- return false;
418
- if (s.includes("WS:TODO"))
419
- return false;
420
- if (s.includes("<!--"))
421
- return false;
422
- if (s === "-" || s === "- (none)" || s === "- (missing)")
423
- return false;
424
- return true;
425
- }
426
- /**
427
- * @param {string} entryName
428
- * @returns {{ datePrefix: string, changeId: string, stamp: string } | null}
429
- */
430
- function parseArchivedChangeDirName(entryName) {
431
- const m = /^(\d{4}-\d{2}-\d{2})-(.+?)(?:-(\d{8}-\d{6}Z))?$/.exec(String(entryName || ""));
432
- if (!m)
433
- return null;
434
- const changeId = m[2] || "";
435
- if (!CHANGE_ID_RE.test(changeId))
436
- return null;
437
- return {
438
- datePrefix: m[1] || "",
439
- changeId,
440
- stamp: m[3] || "",
441
- };
442
- }
443
150
  /**
444
151
  * Find an archived change by ID in the archive directory.
445
152
  * @param {string} archiveDir
@@ -876,6 +583,8 @@ export async function computeChangeStatus(gitRoot, changeId) {
876
583
  blockersStrict.push("tasks.md has no checkbox tasks ('- [ ]' or '- [x]')");
877
584
  if (driftFiles.length > 0)
878
585
  blockersStrict.push(`truth drift vs ${baselineLabel} baseline (run \`aiws change sync ${changeId}\`)`);
586
+ blockersStrict.push(...collectFinishGateErrors(changeId, reviewGates));
587
+ blockersStrict.push(...(await collectStrictValidatorErrors(gitRoot, changeId)).map((error) => `strict validate: ${error}`));
879
588
  const lifecycle = summarizeLifecycleSignals(metrics);
880
589
  const terminatedReuse = lifecycle.finishState === "done"
881
590
  ? {
@@ -928,7 +637,7 @@ export async function computeChangeStatus(gitRoot, changeId) {
928
637
  terminatedReuse,
929
638
  hints: {
930
639
  planVerify: planVerifyHint(changeId),
931
- dev: "质量门通过后再进入编码:simple/local 单点修复优先 `$ws-dev-lite`;否则 `$ws-dev`",
640
+ dev: "质量门通过后继续开发:simple/local 单点修复优先 `$ws-dev-lite`;否则 `$ws-dev`",
932
641
  },
933
642
  };
934
643
  const governance = await inferChangeGovernance(baseStatus);
@@ -940,6 +649,32 @@ export async function computeChangeStatus(gitRoot, changeId) {
940
649
  },
941
650
  };
942
651
  }
652
+ async function collectStrictValidatorErrors(gitRoot, changeId) {
653
+ try {
654
+ const result = await validateChangeArtifactsModel(gitRoot, changeId, {
655
+ strict: true,
656
+ allowTruthDrift: false,
657
+ checkEvidence: false,
658
+ checkScope: false,
659
+ }, {
660
+ assertValidChangeId,
661
+ collectFinishGateErrors,
662
+ computeChangeStatus: async () => ({ reviewGates: null }),
663
+ ensureTruthFiles,
664
+ pathExists,
665
+ readText,
666
+ resolveWsChangeChecker,
667
+ runCommand,
668
+ runPython,
669
+ UserError,
670
+ });
671
+ return Array.isArray(result.errors) ? result.errors : [];
672
+ }
673
+ catch (error) {
674
+ const message = error instanceof Error ? error.message : String(error);
675
+ return [`unavailable: ${message}`];
676
+ }
677
+ }
943
678
  export async function validateChangeArtifacts(gitRoot, changeId, options) {
944
679
  return validateChangeArtifactsModel(gitRoot, changeId, options, {
945
680
  assertValidChangeId,