@gobing-ai/knowledge-kit 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.
Files changed (72) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/index.js +114 -38
  3. package/package.json +1 -1
  4. package/plugins/generations/daily-article-gen/dist/index.js +24 -7
  5. package/plugins/generations/daily-article-gen/src/index.ts +36 -12
  6. package/plugins/generations/dailynews-gen/dist/index.js +19 -2
  7. package/plugins/generations/dailynews-gen/src/index.ts +7 -0
  8. package/plugins/generations/dailynews-gen/src/script-plan.ts +21 -3
  9. package/plugins/generations/episode-plan-gen/dist/index.js +55 -4
  10. package/plugins/generations/episode-plan-gen/src/index.ts +80 -2
  11. package/plugins/generations/image-gen/dist/index.js +122 -20
  12. package/plugins/generations/image-gen/src/bytes.ts +106 -18
  13. package/plugins/generations/image-gen/src/index.ts +46 -6
  14. package/plugins/generations/image-gen/src/job.ts +6 -0
  15. package/plugins/generations/image-gen/src/providers/minimax.ts +12 -4
  16. package/plugins/generations/image-gen/src/providers/types.ts +12 -1
  17. package/plugins/kk/plugin.json +1 -1
  18. package/plugins/kk/scripts/daily-voice-style.zh.md +5 -5
  19. package/plugins/kk/scripts/itc-stages.ts +21 -3
  20. package/plugins/kk/scripts/kk-workflow-stages.ts +199 -7
  21. package/plugins/kk/scripts/topic-boundary.json +3 -12
  22. package/plugins/kk/skills/content-judge/SKILL.md +30 -0
  23. package/plugins/kk/skills/content-judge/references/workflow-integration.md +9 -2
  24. package/plugins/kk/skills/publish/SKILL.md +1 -1
  25. package/plugins/kk/workflows/judge-gated-publish-example.yaml +18 -10
  26. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +39 -14
  27. package/plugins/kk/workflows/kk-itc.yaml +21 -8
  28. package/plugins/publishings/xhs-pub/dist/index.js +1 -1
  29. package/plugins/publishings/xhs-pub/src/automation-guard.ts +2 -2
  30. package/plugins/publishings/xhs-pub/src/index.ts +1 -1
  31. package/plugins/publishings/xhs-pub/src/profile-check.ts +2 -2
  32. package/plugins/sp/lib/env.ts +0 -46
  33. package/plugins/sp/lib/inline-run.generated.mjs +0 -1489
  34. package/plugins/sp/scripts/batch-preflight.mjs +0 -346
  35. package/plugins/sp/scripts/batch-preflight.ts +0 -459
  36. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +0 -615
  37. package/plugins/sp/scripts/daily-summary/daily-summary.ts +0 -846
  38. package/plugins/sp/scripts/daily-summary/logger.ts +0 -28
  39. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +0 -223
  40. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +0 -367
  41. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +0 -132
  42. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +0 -169
  43. package/plugins/sp/scripts/feature-dev-precheck.mjs +0 -171
  44. package/plugins/sp/scripts/feature-dev-precheck.ts +0 -238
  45. package/plugins/sp/scripts/feature-sync-bounded.mjs +0 -285
  46. package/plugins/sp/scripts/feature-sync-bounded.ts +0 -478
  47. package/plugins/sp/scripts/feature-verification-steps.ts +0 -275
  48. package/plugins/sp/scripts/history-anatomy-cache.mjs +0 -902
  49. package/plugins/sp/scripts/history-anatomy-cache.ts +0 -1028
  50. package/plugins/sp/scripts/idea-handoff.mjs +0 -22
  51. package/plugins/sp/scripts/idea-handoff.ts +0 -44
  52. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +0 -185
  53. package/plugins/sp/scripts/inline-run-setup.ts +0 -722
  54. package/plugins/sp/scripts/pr-reviewing.mjs +0 -769
  55. package/plugins/sp/scripts/pr-reviewing.ts +0 -925
  56. package/plugins/sp/scripts/quality-gate.mjs +0 -179
  57. package/plugins/sp/scripts/quality-gate.ts +0 -217
  58. package/plugins/sp/scripts/script-contract-check.ts +0 -319
  59. package/plugins/sp/scripts/stage-registry-adapter.ts +0 -1533
  60. package/plugins/sp/scripts/surface-drift-inventory.ts +0 -929
  61. package/plugins/sp/scripts/task-evidence-precheck.ts +0 -181
  62. package/plugins/sp/scripts/task-size-precheck.ts +0 -175
  63. package/plugins/sp/scripts/transition-shim-check.ts +0 -238
  64. package/plugins/sp/scripts/validate-commands.ts +0 -689
  65. package/plugins/sp/scripts/validate-flag-contracts.ts +0 -878
  66. package/plugins/sp/scripts/verify-answer-lint.ts +0 -530
  67. package/plugins/sp/scripts/workflow-step-profile.mjs +0 -316
  68. package/plugins/sp/scripts/workflow-step-profile.ts +0 -456
  69. package/plugins/sp/scripts/wrapup-drift-probe.mjs +0 -190
  70. package/plugins/sp/scripts/wrapup-drift-probe.ts +0 -258
  71. package/plugins/sp/scripts/wrapup-steps.mjs +0 -444
  72. package/plugins/sp/scripts/wrapup-steps.ts +0 -552
@@ -1,444 +0,0 @@
1
- #!/usr/bin/env node
2
- // @bun
3
-
4
- // plugins/sp/scripts/wrapup-steps.ts
5
- import { spawnSync } from 'child_process';
6
- import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
7
- import { join } from 'path';
8
-
9
- // plugins/sp/lib/env.ts
10
- function getEnvVars() {
11
- return process.env;
12
- }
13
-
14
- // plugins/sp/scripts/wrapup-steps.ts
15
- function jqPick(...values) {
16
- for (const value of values) {
17
- if (value !== null && value !== undefined && value !== false) return value;
18
- }
19
- return values[values.length - 1];
20
- }
21
- function jqText(value) {
22
- return typeof value === 'string' ? value : JSON.stringify(value);
23
- }
24
- var WBS_PATTERN = /^[0-9]{4}$/;
25
- function spurCommand(spurBin) {
26
- const parts = (spurBin ?? 'spur')
27
- .trim()
28
- .split(/\s+/)
29
- .filter((p) => p.length > 0);
30
- return { cmd: parts[0] ?? 'spur', prefix: parts.slice(1) };
31
- }
32
- function spur(env, args, options = {}) {
33
- const { cmd, prefix } = spurCommand(env.spurBin);
34
- const result = spawnSync(cmd, [...prefix, ...args], {
35
- cwd: options.cwd,
36
- encoding: 'utf8',
37
- ...(options.stderr === 'inherit' ? { stdio: ['ignore', 'pipe', 'inherit'] } : {}),
38
- });
39
- if (result.error !== undefined) return { status: result.status ?? 1, stdout: '' };
40
- return { status: result.status ?? 1, stdout: result.stdout ?? '' };
41
- }
42
- function taskStatusOf(taskJson) {
43
- let parsed;
44
- try {
45
- parsed = JSON.parse(taskJson);
46
- } catch {
47
- return { resolved: null, present: false };
48
- }
49
- if (parsed === null || typeof parsed !== 'object') return { resolved: null, present: false };
50
- const frontmatter = parsed.frontmatter;
51
- const fmStatus = frontmatter !== null && typeof frontmatter === 'object' ? frontmatter.status : undefined;
52
- const status = parsed.status;
53
- if (fmStatus === null || fmStatus === undefined) {
54
- return { resolved: status ?? null, present: status !== undefined && status !== null };
55
- }
56
- return { resolved: fmStatus, present: true };
57
- }
58
- function statusDisplay(taskJson) {
59
- const { resolved } = taskStatusOf(taskJson);
60
- if (resolved === null || resolved === undefined || resolved === false) return 'unresolved';
61
- return jqText(resolved);
62
- }
63
- function resolveTasks(env, options = {}) {
64
- const cwd = options.cwd;
65
- const runId = env.__runId ?? '';
66
- if (runId.length === 0) {
67
- process.stderr.write(`task-resolve: __runId is empty \u2014 refusing the legacy fixed-path fallback
68
- `);
69
- return { status: 'FAIL', statusFile: '', tasksFile: '', exitCode: 1 };
70
- }
71
- mkdirSync(cwd ? join(cwd, '.spur', 'run') : join('.spur', 'run'), { recursive: true });
72
- const relTasksFile = join('.spur', 'run', `${runId}-wrapup-tasks.json`);
73
- const relReasonFile = join('.spur', 'run', `${runId}-route-reason.txt`);
74
- const relStatusFile = join('.spur', 'run', `${runId}-wrapup-resolve.status`);
75
- const abs = (p) => (cwd ? join(cwd, p) : p);
76
- const writeFail = (reason) => {
77
- writeFileSync(abs(relReasonFile), reason);
78
- writeFileSync(
79
- abs(relStatusFile),
80
- `FAIL
81
- `,
82
- );
83
- return { status: 'FAIL', statusFile: relStatusFile, tasksFile: relTasksFile, exitCode: 0 };
84
- };
85
- let parsedTasks;
86
- try {
87
- parsedTasks = JSON.parse(env.tasks ?? '');
88
- } catch {
89
- parsedTasks = undefined;
90
- }
91
- const validArray =
92
- Array.isArray(parsedTasks) && parsedTasks.every((w) => typeof w === 'string' && WBS_PATTERN.test(w));
93
- if (!validArray) {
94
- process.stderr.write(`task-resolve: tasks must be a JSON array of canonical four-digit WBS strings (whitespace is rejected, not trimmed)
95
- `);
96
- return writeFail('failed:tasks is not a JSON array of canonical four-digit WBS strings');
97
- }
98
- const deduped = [];
99
- for (const wbs of parsedTasks) {
100
- if (!deduped.includes(wbs)) deduped.push(wbs);
101
- }
102
- writeFileSync(
103
- abs(relTasksFile),
104
- `${JSON.stringify(deduped)}
105
- `,
106
- );
107
- let unresolved = false;
108
- for (const wbs of deduped) {
109
- const shown = spur(env, ['task', 'show', wbs, '--json'], { cwd });
110
- const status = shown.status === 0 ? statusDisplay(shown.stdout) : 'unresolved';
111
- if (status !== 'done' && status !== 'cancelled') {
112
- process.stderr.write(`task-resolve: task ${wbs} did not resolve to a completed status (status=${status})
113
- `);
114
- unresolved = true;
115
- }
116
- }
117
- if (unresolved) {
118
- return writeFail(`failed:unresolved or non-completed task (see ${relTasksFile})`);
119
- }
120
- writeFileSync(
121
- abs(relStatusFile),
122
- `PASS
123
- `,
124
- );
125
- return { status: 'PASS', statusFile: relStatusFile, tasksFile: relTasksFile, exitCode: 0 };
126
- }
127
- var ROUTE_REASON_TABLE = {
128
- fast: 'fast:evidence complete+consistent',
129
- '': 'safety:missing evidence (mode empty)',
130
- unknown: 'safety:unknown evidence quality',
131
- conflict: 'safety:conflicting evidence',
132
- safety: 'safety:operator-forced doc-sync',
133
- };
134
- function writeRouteReason(env, options = {}) {
135
- const cwd = options.cwd;
136
- const runId = env.__runId ?? '';
137
- if (runId.length === 0) {
138
- process.stderr.write(`task-resolve: __runId is empty \u2014 refusing to write a route reason
139
- `);
140
- return { reason: '', reasonFile: '', exitCode: 1 };
141
- }
142
- mkdirSync(cwd ? join(cwd, '.spur', 'run') : join('.spur', 'run'), { recursive: true });
143
- mkdirSync(cwd ? join(cwd, '.spur', 'memory') : join('.spur', 'memory'), { recursive: true });
144
- const relReasonFile = join('.spur', 'run', `${runId}-route-reason.txt`);
145
- const abs = (p) => (cwd ? join(cwd, p) : p);
146
- const statusFile = join('.spur', 'run', `${runId}-wrapup-resolve.status`);
147
- if (readFileSyncSafe(abs(statusFile))?.trim() === 'FAIL') {
148
- return { reason: '', reasonFile: relReasonFile, exitCode: 0 };
149
- }
150
- let taskCount = -1;
151
- try {
152
- const parsed = JSON.parse(readFileSync(abs(join('.spur', 'run', `${runId}-wrapup-tasks.json`)), 'utf8'));
153
- if (Array.isArray(parsed)) taskCount = parsed.length;
154
- } catch {}
155
- let probeClean = false;
156
- try {
157
- const probe = JSON.parse(readFileSync(abs(join('.spur', 'run', `${runId}-drift-probe.json`)), 'utf8'));
158
- probeClean = probe?.clean === true;
159
- } catch {}
160
- const mode = env.mode ?? '';
161
- let reason;
162
- if (taskCount === 0) {
163
- reason = 'skipped:empty task list';
164
- } else if (mode === 'fast' && probeClean) {
165
- reason = 'fast:drift-probe-clean';
166
- } else {
167
- reason = ROUTE_REASON_TABLE[mode] ?? `safety:unrecognized evidence (mode=${mode})`;
168
- }
169
- writeFileSync(
170
- abs(relReasonFile),
171
- `${reason}
172
- `,
173
- );
174
- appendFileSync(
175
- abs(join('.spur', 'memory', 'wrapup-routes.log')),
176
- `${runId} ${reason}
177
- `,
178
- );
179
- return { reason, reasonFile: relReasonFile, exitCode: 0 };
180
- }
181
- function readFileSyncSafe(path) {
182
- try {
183
- return readFileSync(path, 'utf8');
184
- } catch {
185
- return null;
186
- }
187
- }
188
- function runMetrics(env, options = {}) {
189
- const cwd = options.cwd;
190
- const runId = env.__runId ?? '';
191
- mkdirSync(cwd ? join(cwd, '.spur', 'run') : join('.spur', 'run'), { recursive: true });
192
- mkdirSync(cwd ? join(cwd, '.spur', 'memory') : join('.spur', 'memory'), { recursive: true });
193
- const relStatusFile = join('.spur', 'run', `${runId}-wrapup-metrics.status`);
194
- const relTasksFile = join('.spur', 'run', `${runId}-wrapup-tasks.json`);
195
- const relMetricsFile = join('.spur', 'memory', 'wrapup-metrics.jsonl');
196
- const abs = (p) => (cwd ? join(cwd, p) : p);
197
- const fail = () => {
198
- writeFileSync(
199
- abs(relStatusFile),
200
- `FAIL
201
- `,
202
- );
203
- return { status: 'FAIL', statusFile: relStatusFile };
204
- };
205
- let captured;
206
- try {
207
- captured = JSON.parse(readFileSync(abs(relTasksFile), 'utf8'));
208
- } catch {
209
- captured = undefined;
210
- }
211
- const validCapture = Array.isArray(captured) && captured.every((w) => typeof w === 'string' && WBS_PATTERN.test(w));
212
- if (!validCapture) {
213
- process.stderr.write(`metrics-record: run-scoped task capture missing, corrupted or non-canonical \u2014 refusing to record metrics
214
- `);
215
- return fail();
216
- }
217
- let metricsRc = 0;
218
- for (const wbs of captured) {
219
- const shown = spur(env, ['task', 'show', wbs, '--json'], { cwd });
220
- const lookup = shown.status === 0 ? taskStatusOf(shown.stdout) : { resolved: null, present: false };
221
- if (!lookup.present) {
222
- process.stderr.write(`metrics-record: task ${wbs} lookup failed or was malformed \u2014 recording FAIL instead of silently omitting its metrics row
223
- `);
224
- metricsRc = 1;
225
- continue;
226
- }
227
- const parsed = JSON.parse(shown.stdout);
228
- const frontmatter =
229
- parsed.frontmatter !== null && typeof parsed.frontmatter === 'object' ? parsed.frontmatter : {};
230
- const featureId = String(jqPick(frontmatter.feature_id, parsed.feature_id, ''));
231
- const status2 = String(jqPick(frontmatter.status, parsed.status, 'unknown'));
232
- let verdict = 'UNKNOWN';
233
- const verdictPath = join('.spur', 'run', `${wbs}-verdict.json`);
234
- if (existsSync(abs(verdictPath))) {
235
- try {
236
- const raw = jqPick(JSON.parse(readFileSync(abs(verdictPath), 'utf8')).verdict, 'UNKNOWN');
237
- const text = raw === 'UNKNOWN' ? 'UNKNOWN' : jqText(raw);
238
- if (text.length > 0) verdict = text;
239
- } catch {}
240
- }
241
- const timestamp = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
242
- const row = { wbs, feature_id: featureId, status: status2, verdict, timestamp };
243
- try {
244
- appendFileSync(
245
- abs(relMetricsFile),
246
- `${JSON.stringify(row)}
247
- `,
248
- );
249
- } catch {
250
- process.stderr.write(`metrics-record: metrics append failed for task ${wbs} \u2014 recording FAIL instead of claiming the row landed
251
- `);
252
- metricsRc = 1;
253
- }
254
- }
255
- const status = metricsRc === 0 ? 'PASS' : 'FAIL';
256
- writeFileSync(
257
- abs(relStatusFile),
258
- `${status}
259
- `,
260
- );
261
- return { status, statusFile: relStatusFile };
262
- }
263
- function classifySync(syncOutput, syncRc, feature, observed) {
264
- if (syncRc !== 0) {
265
- return { reason: `sync exited nonzero (rc=${syncRc})`, applied: 'unreadable', syncOk: false };
266
- }
267
- let parsed;
268
- try {
269
- parsed = JSON.parse(syncOutput);
270
- } catch {
271
- parsed = undefined;
272
- }
273
- const obj = parsed !== null && typeof parsed === 'object' ? parsed : undefined;
274
- const proposal = obj?.proposal !== null && typeof obj?.proposal === 'object' ? obj.proposal : undefined;
275
- const shapeOk =
276
- obj !== undefined &&
277
- proposal !== undefined &&
278
- typeof proposal.featureId === 'string' &&
279
- typeof proposal.from === 'string' &&
280
- typeof proposal.to === 'string' &&
281
- typeof obj.applied === 'boolean';
282
- if (!shapeOk) {
283
- return { reason: 'malformed or unreadable sync result', applied: 'unreadable', syncOk: false };
284
- }
285
- const applied = obj.applied === true ? 'true' : 'false';
286
- const pFrom = String(jqPick(proposal.from, ''));
287
- const pTo = String(jqPick(proposal.to, ''));
288
- if (String(jqPick(proposal.featureId, '')) !== feature) {
289
- return { reason: `sync proposal does not match feature ${feature}`, applied, syncOk: false };
290
- }
291
- if (proposal.gateBlocked === true) {
292
- return {
293
- reason: 'sync proposal is gate-blocked \u2014 a blocked sync is not a no-change success',
294
- applied,
295
- syncOk: false,
296
- };
297
- }
298
- if (proposal.requiresConfirm === true) {
299
- return { reason: 'sync proposal requires operator confirmation', applied, syncOk: false };
300
- }
301
- if (applied === 'true' && observed !== pTo) {
302
- return {
303
- reason: `applied sync did not land on the proposal target (observed=${observed}, to=${pTo})`,
304
- applied,
305
- syncOk: false,
306
- };
307
- }
308
- if (applied === 'false' && (pFrom !== pTo || observed !== pTo)) {
309
- return {
310
- reason: `sync applied nothing without a from==to observed no-op (from=${pFrom}, to=${pTo}, observed=${observed})`,
311
- applied,
312
- syncOk: false,
313
- };
314
- }
315
- return { reason: '', applied, syncOk: true };
316
- }
317
- function runFeatureTransition(env, options = {}) {
318
- const cwd = options.cwd;
319
- const runId = env.__runId ?? '';
320
- const feature = env.feature ?? '';
321
- mkdirSync(cwd ? join(cwd, '.spur', 'run') : join('.spur', 'run'), { recursive: true });
322
- const relStatusFile = join('.spur', 'run', `${runId}-wrapup-sync.status`);
323
- const abs = (p) => (cwd ? join(cwd, p) : p);
324
- if (feature.length === 0) {
325
- process.stderr.write(`feature-transition: vars.feature is empty \u2014 refusing no-op feature sync (mis-invocation, not a blocked sync)
326
- `);
327
- return { status: 'FAIL', statusFile: relStatusFile, exitCode: 1 };
328
- }
329
- let syncOutput = '';
330
- let syncRc = 1;
331
- const boundedTs = join('plugins', 'sp', 'scripts', 'feature-sync-bounded.ts');
332
- const boundedArgs = [feature, '--spur-bin', env.spurBin ?? 'spur', '--json'];
333
- if (existsSync(cwd ? join(cwd, boundedTs) : boundedTs)) {
334
- const result = spawnSync('bun', [boundedTs, ...boundedArgs], { cwd, encoding: 'utf8' });
335
- syncOutput = result.stdout ?? '';
336
- syncRc = result.status ?? 1;
337
- if (result.stderr !== null && result.stderr.length > 0) process.stderr.write(result.stderr);
338
- } else {
339
- const probe = spawnSync('superskill', ['script', 'path', 'sp', 'feature-sync-bounded.mjs'], {
340
- cwd,
341
- encoding: 'utf8',
342
- });
343
- const twin = probe.status === 0 ? (probe.stdout ?? '').trim() : '';
344
- if (twin.length > 0 && existsSync(twin)) {
345
- const result = spawnSync('node', [twin, ...boundedArgs], { cwd, encoding: 'utf8' });
346
- syncOutput = result.stdout ?? '';
347
- syncRc = result.status ?? 1;
348
- if (result.stderr !== null && result.stderr.length > 0) process.stderr.write(result.stderr);
349
- } else {
350
- const result = spur(env, ['feature', 'sync', feature, '--json'], { cwd, stderr: 'inherit' });
351
- syncOutput = result.stdout;
352
- syncRc = result.status;
353
- }
354
- }
355
- process.stdout.write(`${syncOutput}
356
- `);
357
- const shown = spur(env, ['feature', 'show', feature, '--json'], { cwd });
358
- let observed = '';
359
- if (shown.status === 0) {
360
- try {
361
- const parsed = JSON.parse(shown.stdout);
362
- const frontmatter =
363
- parsed.frontmatter !== null && typeof parsed.frontmatter === 'object' ? parsed.frontmatter : {};
364
- const picked = jqPick(parsed.status, frontmatter.status, '');
365
- observed = picked === '' ? '' : jqText(picked);
366
- } catch {
367
- observed = '';
368
- }
369
- }
370
- if (observed.length === 0) observed = 'unreadable';
371
- const classified = classifySync(syncOutput, syncRc, feature, observed);
372
- const { reason, applied } = classified;
373
- const syncOk = classified.syncOk;
374
- let gate = 'skipped';
375
- if (applied === 'true' || syncRc !== 0) {
376
- process.stdout.write(`feature-transition: sync applied or failed after a possible partial transition for ${feature} \u2014 running feature gate: ${env.featureGateCmd ?? ''}
377
- `);
378
- const gateResult = spawnSync('sh', ['-c', env.featureGateCmd ?? ''], { cwd, stdio: 'inherit' });
379
- if ((gateResult.status ?? 1) === 0) {
380
- gate = 'PASS';
381
- process.stdout.write(`feature-transition: feature gate PASS for feature ${feature}
382
- `);
383
- } else {
384
- gate = 'FAIL';
385
- process.stderr.write(`feature-transition: feature gate FAIL for feature ${feature} \u2014 inspect findings before reporting the transition complete
386
- `);
387
- }
388
- } else {
389
- process.stdout.write(`feature-transition: sync did not apply a transition (rc=${syncRc}, applied=${applied}) \u2014 feature gate skipped
390
- `);
391
- }
392
- let syncStatus;
393
- if (!syncOk || gate === 'FAIL') {
394
- syncStatus = 'FAIL';
395
- process.stderr.write(`feature-transition: required synchronization failed for ${feature} \u2014 ${reason}; gate=${gate}
396
- `);
397
- } else if (applied === 'false') {
398
- syncStatus = 'PASS';
399
- process.stdout.write(`feature-transition: feature sync verified for ${feature} (from==to observed at ${observed}, gate=${gate}) \u2014 explicit no-change
400
- `);
401
- } else {
402
- syncStatus = 'PASS';
403
- process.stdout.write(`feature-transition: feature sync verified for ${feature} (applied, observed=${observed}, gate=${gate})
404
- `);
405
- }
406
- writeFileSync(
407
- abs(relStatusFile),
408
- `${syncStatus}
409
- `,
410
- );
411
- return { status: syncStatus, statusFile: relStatusFile, exitCode: 0 };
412
- }
413
- var WRAPUP_STEPS_USAGE =
414
- 'usage: wrapup-steps.ts <resolve|route-reason|metrics|feature-transition> (env: __runId, tasks, mode, feature, featureGateCmd, spurBin)';
415
- function main(argv, env = getEnvVars(), options = {}) {
416
- const sub = argv[0];
417
- if (sub === 'resolve') return resolveTasks(env, options).exitCode;
418
- if (sub === 'route-reason') return writeRouteReason(env, options).exitCode;
419
- if (sub === 'metrics') {
420
- runMetrics(env, options);
421
- return 0;
422
- }
423
- if (sub === 'feature-transition') return runFeatureTransition(env, options).exitCode;
424
- process.stderr.write(`${WRAPUP_STEPS_USAGE}
425
- `);
426
- return 2;
427
- }
428
- {
429
- process.exit(main(process.argv.slice(2)));
430
- }
431
-
432
- export {
433
- classifySync,
434
- jqPick,
435
- main,
436
- resolveTasks,
437
- runFeatureTransition,
438
- runMetrics,
439
- spurCommand,
440
- taskStatusOf,
441
- WBS_PATTERN,
442
- WRAPUP_STEPS_USAGE,
443
- writeRouteReason,
444
- };