spec-manager 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +94 -28
  3. package/dist/cli/change.d.ts.map +1 -1
  4. package/dist/cli/change.js +93 -4
  5. package/dist/cli/change.js.map +1 -1
  6. package/dist/cli/completion.d.ts +3 -0
  7. package/dist/cli/completion.d.ts.map +1 -0
  8. package/dist/cli/completion.js +30 -0
  9. package/dist/cli/completion.js.map +1 -0
  10. package/dist/cli/index.js +4 -0
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/cli/project.d.ts.map +1 -1
  13. package/dist/cli/project.js +71 -7
  14. package/dist/cli/project.js.map +1 -1
  15. package/dist/cli/spec.d.ts.map +1 -1
  16. package/dist/cli/spec.js +42 -14
  17. package/dist/cli/spec.js.map +1 -1
  18. package/dist/cli/task.d.ts.map +1 -1
  19. package/dist/cli/task.js +150 -42
  20. package/dist/cli/task.js.map +1 -1
  21. package/dist/cli/usability.d.ts.map +1 -1
  22. package/dist/cli/usability.js +32 -8
  23. package/dist/cli/usability.js.map +1 -1
  24. package/dist/cli/view.d.ts +3 -0
  25. package/dist/cli/view.d.ts.map +1 -0
  26. package/dist/cli/view.js +122 -0
  27. package/dist/cli/view.js.map +1 -0
  28. package/dist/core/agents.d.ts +23 -1
  29. package/dist/core/agents.d.ts.map +1 -1
  30. package/dist/core/agents.js +82 -2
  31. package/dist/core/agents.js.map +1 -1
  32. package/dist/core/archive.d.ts.map +1 -1
  33. package/dist/core/archive.js +74 -2
  34. package/dist/core/archive.js.map +1 -1
  35. package/dist/core/audit.d.ts +1 -0
  36. package/dist/core/audit.d.ts.map +1 -1
  37. package/dist/core/audit.js +60 -40
  38. package/dist/core/audit.js.map +1 -1
  39. package/dist/core/completion.d.ts +12 -0
  40. package/dist/core/completion.d.ts.map +1 -0
  41. package/dist/core/completion.js +136 -0
  42. package/dist/core/completion.js.map +1 -0
  43. package/dist/core/delta.d.ts +30 -1
  44. package/dist/core/delta.d.ts.map +1 -1
  45. package/dist/core/delta.js +141 -4
  46. package/dist/core/delta.js.map +1 -1
  47. package/dist/core/harness.d.ts +69 -0
  48. package/dist/core/harness.d.ts.map +1 -0
  49. package/dist/core/harness.js +278 -0
  50. package/dist/core/harness.js.map +1 -0
  51. package/dist/core/integrity-exemptions.d.ts +29 -0
  52. package/dist/core/integrity-exemptions.d.ts.map +1 -0
  53. package/dist/core/integrity-exemptions.js +100 -0
  54. package/dist/core/integrity-exemptions.js.map +1 -0
  55. package/dist/core/integrity.d.ts +12 -0
  56. package/dist/core/integrity.d.ts.map +1 -0
  57. package/dist/core/integrity.js +163 -0
  58. package/dist/core/integrity.js.map +1 -0
  59. package/dist/core/invariants.d.ts +5 -0
  60. package/dist/core/invariants.d.ts.map +1 -0
  61. package/dist/core/invariants.js +19 -0
  62. package/dist/core/invariants.js.map +1 -0
  63. package/dist/core/lifecycle.d.ts +37 -0
  64. package/dist/core/lifecycle.d.ts.map +1 -0
  65. package/dist/core/lifecycle.js +70 -0
  66. package/dist/core/lifecycle.js.map +1 -0
  67. package/dist/core/paths.d.ts +3 -0
  68. package/dist/core/paths.d.ts.map +1 -1
  69. package/dist/core/paths.js +19 -1
  70. package/dist/core/paths.js.map +1 -1
  71. package/dist/core/placeholder.d.ts +6 -0
  72. package/dist/core/placeholder.d.ts.map +1 -0
  73. package/dist/core/placeholder.js +12 -0
  74. package/dist/core/placeholder.js.map +1 -0
  75. package/dist/core/reconciliation.d.ts +25 -0
  76. package/dist/core/reconciliation.d.ts.map +1 -0
  77. package/dist/core/reconciliation.js +122 -0
  78. package/dist/core/reconciliation.js.map +1 -0
  79. package/dist/core/remediation.d.ts +41 -0
  80. package/dist/core/remediation.d.ts.map +1 -0
  81. package/dist/core/remediation.js +169 -0
  82. package/dist/core/remediation.js.map +1 -0
  83. package/dist/core/spec-io.d.ts +3 -5
  84. package/dist/core/spec-io.d.ts.map +1 -1
  85. package/dist/core/spec-io.js +26 -13
  86. package/dist/core/spec-io.js.map +1 -1
  87. package/dist/core/status.d.ts +6 -3
  88. package/dist/core/status.d.ts.map +1 -1
  89. package/dist/core/status.js +12 -4
  90. package/dist/core/status.js.map +1 -1
  91. package/dist/core/task.d.ts +26 -0
  92. package/dist/core/task.d.ts.map +1 -1
  93. package/dist/core/task.js +74 -46
  94. package/dist/core/task.js.map +1 -1
  95. package/dist/core/transaction.d.ts +10 -0
  96. package/dist/core/transaction.d.ts.map +1 -0
  97. package/dist/core/transaction.js +65 -0
  98. package/dist/core/transaction.js.map +1 -0
  99. package/dist/core/usability.d.ts +8 -2
  100. package/dist/core/usability.d.ts.map +1 -1
  101. package/dist/core/usability.js +203 -35
  102. package/dist/core/usability.js.map +1 -1
  103. package/dist/core/validate.d.ts +2 -0
  104. package/dist/core/validate.d.ts.map +1 -1
  105. package/dist/core/validate.js +29 -1
  106. package/dist/core/validate.js.map +1 -1
  107. package/dist/core/view.d.ts +35 -0
  108. package/dist/core/view.d.ts.map +1 -0
  109. package/dist/core/view.js +50 -0
  110. package/dist/core/view.js.map +1 -0
  111. package/dist/index.d.ts +7 -0
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +7 -0
  114. package/dist/index.js.map +1 -1
  115. package/dist/schemas/change.d.ts +20 -20
  116. package/dist/schemas/spec.d.ts +12 -12
  117. package/package.json +2 -1
  118. package/rules/flow-control.md +3 -3
  119. package/skill/SKILL.md +14 -2
  120. package/skill/subskills/impl.md +2 -2
  121. package/templates/L3-impl.md +2 -2
  122. package/templates/agent-plan.json +2 -1
  123. package/templates/agents/AGENTS.md +8 -6
  124. package/templates/agents/CLAUDE.md +7 -3
  125. package/templates/agents/CODEBUDDY.md +9 -7
  126. package/templates/agents/CURSOR.md +28 -0
  127. package/templates/agents/WINDSURF.md +28 -0
  128. package/templates/agents/codebuddy-skill/SKILL.md +12 -1
@@ -0,0 +1,100 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { writeAtomic } from './frontmatter.js';
3
+ export function emptyIntegrityExemptionRegistry() {
4
+ return { version: 1, exemptions: [] };
5
+ }
6
+ export function readIntegrityExemptions(paths) {
7
+ if (!existsSync(paths.integrityExemptionsFile)) {
8
+ return { registry: emptyIntegrityExemptionRegistry(), problems: [] };
9
+ }
10
+ let value;
11
+ try {
12
+ value = JSON.parse(readFileSync(paths.integrityExemptionsFile, 'utf8'));
13
+ }
14
+ catch (err) {
15
+ return invalidRegistry(`cannot parse integrity exemption registry: ${errorMessage(err)}`);
16
+ }
17
+ if (!isRecord(value) || value.version !== 1 || !Array.isArray(value.exemptions)) {
18
+ return invalidRegistry('integrity exemption registry must have version 1 and an exemptions array');
19
+ }
20
+ const exemptions = [];
21
+ const problems = [];
22
+ const ids = new Set();
23
+ const taskKeys = new Set();
24
+ for (const [index, item] of value.exemptions.entries()) {
25
+ if (!isIntegrityExemption(item)) {
26
+ problems.push({ sourceId: `exemption[${index}]`, message: `integrity exemption at index ${index} has invalid fields` });
27
+ continue;
28
+ }
29
+ const taskKey = exemptionTaskKey(item);
30
+ if (ids.has(item.id)) {
31
+ problems.push({ sourceId: item.id, message: `duplicate integrity exemption id: ${item.id}` });
32
+ continue;
33
+ }
34
+ if (taskKeys.has(taskKey)) {
35
+ problems.push({ sourceId: taskKey, message: `duplicate integrity exemption task key: ${taskKey}` });
36
+ continue;
37
+ }
38
+ ids.add(item.id);
39
+ taskKeys.add(taskKey);
40
+ exemptions.push(item);
41
+ }
42
+ return { registry: { version: 1, exemptions }, problems };
43
+ }
44
+ export function mergeIntegrityExemptions(registry, additions) {
45
+ const byId = new Map(registry.exemptions.map(exemption => [exemption.id, exemption]));
46
+ const byTask = new Map(registry.exemptions.map(exemption => [exemptionTaskKey(exemption), exemption]));
47
+ const merged = [...registry.exemptions];
48
+ for (const exemption of additions) {
49
+ if (!isIntegrityExemption(exemption)) {
50
+ throw new Error('INVALID_EXEMPTION: invalid fields');
51
+ }
52
+ const sameId = byId.get(exemption.id);
53
+ const sameTask = byTask.get(exemptionTaskKey(exemption));
54
+ if (sameId && JSON.stringify(sameId) !== JSON.stringify(exemption)) {
55
+ throw new Error(`EXEMPTION_CONFLICT: id ${exemption.id}`);
56
+ }
57
+ if (sameTask && sameTask.id !== exemption.id) {
58
+ throw new Error(`EXEMPTION_CONFLICT: task ${exemptionTaskKey(exemption)}`);
59
+ }
60
+ if (sameId || sameTask)
61
+ continue;
62
+ merged.push(exemption);
63
+ byId.set(exemption.id, exemption);
64
+ byTask.set(exemptionTaskKey(exemption), exemption);
65
+ }
66
+ return { version: 1, exemptions: merged };
67
+ }
68
+ export function writeIntegrityExemptions(paths, registry) {
69
+ writeAtomic(paths.integrityExemptionsFile, `${JSON.stringify(registry, null, 2)}\n`);
70
+ }
71
+ export function exemptionTaskKey(exemption) {
72
+ return `${exemption.specCode}:${exemption.taskId}`;
73
+ }
74
+ function invalidRegistry(message) {
75
+ return {
76
+ registry: emptyIntegrityExemptionRegistry(),
77
+ problems: [{ sourceId: 'integrity-exemptions', message }],
78
+ };
79
+ }
80
+ function isIntegrityExemption(value) {
81
+ if (!isRecord(value))
82
+ return false;
83
+ return value.kind === 'legacy-missing-verification'
84
+ && nonEmpty(value.id)
85
+ && nonEmpty(value.specCode)
86
+ && nonEmpty(value.taskId)
87
+ && nonEmpty(value.reason)
88
+ && nonEmpty(value.createdAt)
89
+ && nonEmpty(value.migrationId);
90
+ }
91
+ function isRecord(value) {
92
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
93
+ }
94
+ function nonEmpty(value) {
95
+ return typeof value === 'string' && value.trim().length > 0;
96
+ }
97
+ function errorMessage(err) {
98
+ return err instanceof Error ? err.message : String(err);
99
+ }
100
+ //# sourceMappingURL=integrity-exemptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity-exemptions.js","sourceRoot":"","sources":["../../src/core/integrity-exemptions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { ProjectPaths } from './paths.js';
2
+ export type IntegrityIssueKind = 'dangling-reference' | 'conflicting-active-task' | 'missing-verification' | 'missing-decision' | 'immutable-history-violation' | 'invalid-exemption' | 'stale-confirmed-parent';
3
+ export interface IntegrityIssue {
4
+ kind: IntegrityIssueKind;
5
+ sourceFile: string;
6
+ sourceId: string;
7
+ targetId?: string;
8
+ message: string;
9
+ remediation?: string;
10
+ }
11
+ export declare function inspectProjectIntegrity(paths: ProjectPaths): IntegrityIssue[];
12
+ //# sourceMappingURL=integrity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/core/integrity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C,MAAM,MAAM,kBAAkB,GAC1B,oBAAoB,GACpB,yBAAyB,GACzB,sBAAsB,GACtB,kBAAkB,GAClB,6BAA6B,GAC7B,mBAAmB,GACnB,wBAAwB,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,cAAc,EAAE,CAqI7E"}
@@ -0,0 +1,163 @@
1
+ import { listAllSpecs } from './spec-io.js';
2
+ import { listTasks } from './task.js';
3
+ import { listDecisions } from './decision.js';
4
+ import { listIncidents } from './incident.js';
5
+ import { listTaskLinkedChangeProposals } from './delta.js';
6
+ import { exemptionTaskKey, readIntegrityExemptions } from './integrity-exemptions.js';
7
+ const ACTIVE_TASK_STATUSES = new Set(['draft', 'running', 'waiting']);
8
+ export function inspectProjectIntegrity(paths) {
9
+ const issues = [];
10
+ const specs = listAllSpecs(paths);
11
+ const tasks = listTasks(paths);
12
+ const decisions = listDecisions(paths, { includeAll: true });
13
+ const incidents = listIncidents(paths);
14
+ const changes = listTaskLinkedChangeProposals(paths);
15
+ const exemptionResult = readIntegrityExemptions(paths);
16
+ const specCodes = new Set(specs.map(spec => spec.fm.code));
17
+ const taskKeys = new Set(tasks.map(task => `${task.specCode}:${task.id}`));
18
+ const decisionIds = new Set(decisions.map(decision => decision.id));
19
+ const taskByKey = new Map(tasks.map(task => [`${task.specCode}:${task.id}`, task]));
20
+ const validExemptionTaskKeys = new Set();
21
+ for (const problem of exemptionResult.problems) {
22
+ issues.push({
23
+ kind: 'invalid-exemption',
24
+ sourceFile: paths.integrityExemptionsFile,
25
+ sourceId: problem.sourceId,
26
+ message: problem.message,
27
+ remediation: 'Repair or remove the invalid integrity exemption entry.',
28
+ });
29
+ }
30
+ for (const exemption of exemptionResult.registry.exemptions) {
31
+ const key = exemptionTaskKey(exemption);
32
+ const task = taskByKey.get(key);
33
+ if (!task) {
34
+ issues.push(invalidExemption(paths, exemption.id, `integrity exemption references missing task ${key}`));
35
+ }
36
+ else if (task.status !== 'completed') {
37
+ issues.push(invalidExemption(paths, exemption.id, `integrity exemption references non-completed task ${key}`));
38
+ }
39
+ else if ((task.verifications ?? []).some(v => v.exitCode === 0)) {
40
+ issues.push(invalidExemption(paths, exemption.id, `integrity exemption references task with successful verification ${key}`));
41
+ }
42
+ else {
43
+ validExemptionTaskKeys.add(key);
44
+ }
45
+ }
46
+ for (const spec of specs) {
47
+ if (spec.fm.parentCode && !specCodes.has(spec.fm.parentCode)) {
48
+ issues.push(dangling(spec.filePath, spec.fm.code, spec.fm.parentCode, 'parentCode'));
49
+ }
50
+ for (const relation of spec.fm.relations ?? []) {
51
+ if (!specCodes.has(relation.target)) {
52
+ issues.push(dangling(spec.filePath, spec.fm.code, relation.target, `relation ${relation.type}`));
53
+ }
54
+ }
55
+ if (spec.fm.level === 'L1' && spec.fm.status === 'implemented' && !decisions.some(d => d.fm.docCode === spec.fm.code)) {
56
+ issues.push({
57
+ kind: 'missing-decision',
58
+ sourceFile: spec.filePath,
59
+ sourceId: spec.fm.code,
60
+ message: `implemented L1 ${spec.fm.code} has no decision card`,
61
+ remediation: `spec-manager decision create ${spec.fm.code} --topic ${spec.fm.topic} --what "..."`,
62
+ });
63
+ }
64
+ if ((spec.fm.level === 'L1' || spec.fm.level === 'L2') && spec.fm.status === 'confirmed') {
65
+ const children = specs.filter(child => child.fm.parentCode === spec.fm.code);
66
+ if (children.length > 0 && children.every(child => child.fm.status === 'implemented')) {
67
+ issues.push({
68
+ kind: 'stale-confirmed-parent',
69
+ sourceFile: spec.filePath,
70
+ sourceId: spec.fm.code,
71
+ message: `confirmed ${spec.fm.level} ${spec.fm.code} has only implemented direct children`,
72
+ remediation: 'spec-manager project reconcile --dry-run',
73
+ });
74
+ }
75
+ }
76
+ }
77
+ for (const task of tasks) {
78
+ if (!specCodes.has(task.specCode)) {
79
+ issues.push(dangling(taskFileHint(paths, task), task.id, task.specCode, 'task specCode'));
80
+ }
81
+ const taskKey = `${task.specCode}:${task.id}`;
82
+ if (task.status === 'completed' && !(task.verifications ?? []).some(v => v.exitCode === 0) && !validExemptionTaskKeys.has(taskKey)) {
83
+ issues.push({
84
+ kind: 'missing-verification',
85
+ sourceFile: taskFileHint(paths, task),
86
+ sourceId: `${task.specCode}:${task.id}`,
87
+ message: `completed task ${task.id} (${task.specCode}) has no successful verification`,
88
+ remediation: 'Create a follow-up task; completed task history is immutable.',
89
+ });
90
+ }
91
+ if ((task.status === 'completed' || task.status === 'failed') && (task.steps ?? []).some(step => step.status !== 'succeeded')) {
92
+ issues.push({
93
+ kind: 'immutable-history-violation',
94
+ sourceFile: taskFileHint(paths, task),
95
+ sourceId: `${task.specCode}:${task.id}`,
96
+ message: `terminal task ${task.id} contains non-succeeded steps`,
97
+ });
98
+ }
99
+ }
100
+ const activeBySpec = new Map();
101
+ for (const task of tasks.filter(task => ACTIVE_TASK_STATUSES.has(task.status))) {
102
+ activeBySpec.set(task.specCode, [...(activeBySpec.get(task.specCode) ?? []), task]);
103
+ }
104
+ for (const [specCode, active] of activeBySpec) {
105
+ if (active.length > 1) {
106
+ issues.push({
107
+ kind: 'conflicting-active-task',
108
+ sourceFile: taskFileHint(paths, active[0]),
109
+ sourceId: specCode,
110
+ message: `${specCode} has ${active.length} active tasks: ${active.map(task => task.id).join(', ')}`,
111
+ });
112
+ }
113
+ }
114
+ for (const decision of decisions) {
115
+ if (!specCodes.has(decision.fm.docCode)) {
116
+ issues.push(dangling(decision.filePath, decision.id, decision.fm.docCode, 'decision docCode'));
117
+ }
118
+ }
119
+ for (const incident of incidents) {
120
+ if (incident.fm.specCode && !specCodes.has(incident.fm.specCode)) {
121
+ issues.push(dangling(incident.filePath, incident.id, incident.fm.specCode, 'incident specCode'));
122
+ }
123
+ if (incident.fm.taskCode && incident.fm.specCode && !taskKeys.has(`${incident.fm.specCode}:${incident.fm.taskCode}`)) {
124
+ issues.push(dangling(incident.filePath, incident.id, incident.fm.taskCode, 'incident taskCode'));
125
+ }
126
+ for (const id of incident.fm.relatedDecisions ?? []) {
127
+ if (!decisionIds.has(id))
128
+ issues.push(dangling(incident.filePath, incident.id, id, 'incident relatedDecision'));
129
+ }
130
+ }
131
+ for (const change of changes) {
132
+ if (!specCodes.has(change.specCode)) {
133
+ issues.push(dangling(change.proposalFile, change.name, change.specCode, 'change specCode'));
134
+ }
135
+ if (!taskKeys.has(`${change.specCode}:${change.taskCode}`)) {
136
+ issues.push(dangling(change.proposalFile, change.name, change.taskCode, 'change taskCode'));
137
+ }
138
+ }
139
+ return issues;
140
+ }
141
+ function invalidExemption(paths, sourceId, message) {
142
+ return {
143
+ kind: 'invalid-exemption',
144
+ sourceFile: paths.integrityExemptionsFile,
145
+ sourceId,
146
+ message,
147
+ remediation: 'Repair or remove the invalid integrity exemption entry.',
148
+ };
149
+ }
150
+ function dangling(sourceFile, sourceId, targetId, field) {
151
+ return {
152
+ kind: 'dangling-reference',
153
+ sourceFile,
154
+ sourceId,
155
+ targetId,
156
+ message: `${sourceId} has dangling ${field}: ${targetId}`,
157
+ };
158
+ }
159
+ function taskFileHint(paths, task) {
160
+ const topic = listAllSpecs(paths).find(spec => spec.fm.code === task.specCode)?.fm.topic ?? '?';
161
+ return `${paths.specsDir}/${topic}/tasks/${task.specCode}-${task.id}.json`;
162
+ }
163
+ //# sourceMappingURL=integrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../src/core/integrity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { TaskRecord } from './task.js';
2
+ export declare function assertTaskMutable(task: TaskRecord, operation: string): void;
3
+ export declare function assertNoActiveTaskForSpec(tasks: TaskRecord[], specCode: string): void;
4
+ export declare function assertTaskHasSuccessfulVerification(task: TaskRecord): void;
5
+ //# sourceMappingURL=invariants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariants.d.ts","sourceRoot":"","sources":["../../src/core/invariants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAK5C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAI3E;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAKrF;AAED,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAI1E"}
@@ -0,0 +1,19 @@
1
+ const MUTABLE_TASK_STATUSES = new Set(['running']);
2
+ const ACTIVE_TASK_STATUSES = new Set(['draft', 'running', 'waiting']);
3
+ export function assertTaskMutable(task, operation) {
4
+ if (!MUTABLE_TASK_STATUSES.has(task.status)) {
5
+ throw new Error(`TASK_IMMUTABLE: cannot ${operation} task ${task.id} with status=${task.status}`);
6
+ }
7
+ }
8
+ export function assertNoActiveTaskForSpec(tasks, specCode) {
9
+ const active = tasks.find(task => task.specCode === specCode && ACTIVE_TASK_STATUSES.has(task.status));
10
+ if (active) {
11
+ throw new Error(`TASK_ALREADY_ACTIVE: ${specCode} already has ${active.id} status=${active.status}`);
12
+ }
13
+ }
14
+ export function assertTaskHasSuccessfulVerification(task) {
15
+ if (!(task.verifications ?? []).some(verification => verification.exitCode === 0)) {
16
+ throw new Error(`VERIFICATION_REQUIRED: task ${task.id} requires at least one successful verification`);
17
+ }
18
+ }
19
+ //# sourceMappingURL=invariants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariants.js","sourceRoot":"","sources":["../../src/core/invariants.ts"],"names":[],"mappings":"AAEA,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACnD,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAEtE,MAAM,UAAU,iBAAiB,CAAC,IAAgB,EAAE,SAAiB;IACnE,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,0BAA0B,SAAS,SAAS,IAAI,CAAC,EAAE,gBAAgB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACpG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAmB,EAAE,QAAgB;IAC7E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACvG,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,gBAAgB,MAAM,CAAC,EAAE,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACvG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mCAAmC,CAAC,IAAgB;IAClE,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QAClF,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,EAAE,gDAAgD,CAAC,CAAC;IAC1G,CAAC;AACH,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { AuditSink } from './audit-events.js';
2
+ import type { ProjectPaths } from './paths.js';
3
+ import type { ImplementationAuthority, SpecStatus } from './status.js';
4
+ import type { SpecLevel } from './validate.js';
5
+ export type { ImplementationAuthority } from './status.js';
6
+ export type ImplementationBlocker = 'missing-spec' | 'wrong-status' | 'no-children' | 'children-incomplete' | 'authority-not-allowed';
7
+ export interface ImplementationReadiness {
8
+ specCode: string;
9
+ level?: SpecLevel;
10
+ currentStatus?: SpecStatus;
11
+ expectedStatus: 'confirmed' | 'frozen';
12
+ ready: boolean;
13
+ alreadyImplemented: boolean;
14
+ blockers: ImplementationBlocker[];
15
+ }
16
+ export interface LifecycleCascadeResult {
17
+ cascadedSpecs: Array<{
18
+ code: string;
19
+ oldStatus: string;
20
+ newStatus: 'implemented';
21
+ level: SpecLevel;
22
+ }>;
23
+ skippedSpecs: Array<{
24
+ code: string;
25
+ status: string;
26
+ reason: string;
27
+ }>;
28
+ }
29
+ export interface CascadeImplementedHierarchyOptions {
30
+ paths: ProjectPaths;
31
+ startSpecCode: string;
32
+ authority: ImplementationAuthority;
33
+ auditSink?: AuditSink;
34
+ }
35
+ export declare function assessImplementationReadiness(paths: ProjectPaths, specCode: string, authority: ImplementationAuthority): ImplementationReadiness;
36
+ export declare function cascadeImplementedHierarchy(options: CascadeImplementedHierarchyOptions): LifecycleCascadeResult;
37
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,KAAK,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,YAAY,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAC7B,cAAc,GACd,cAAc,GACd,aAAa,GACb,qBAAqB,GACrB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,cAAc,EAAE,WAAW,GAAG,QAAQ,CAAC;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;IAC5B,QAAQ,EAAE,qBAAqB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,aAAa,CAAC;QACzB,KAAK,EAAE,SAAS,CAAC;KAClB,CAAC,CAAC;IACH,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,kCAAkC;IACjD,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,uBAAuB,CAAC;IACnC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,uBAAuB,GACjC,uBAAuB,CAwCzB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,kCAAkC,GAAG,sBAAsB,CAI/G"}
@@ -0,0 +1,70 @@
1
+ import { findSpecByCode, listAllSpecs, updateSpec } from './spec-io.js';
2
+ export function assessImplementationReadiness(paths, specCode, authority) {
3
+ const spec = findSpecByCode(paths, specCode);
4
+ const expectedStatus = spec?.fm.level === 'L3' ? 'frozen' : 'confirmed';
5
+ if (!spec) {
6
+ return { specCode, expectedStatus: 'confirmed', ready: false, alreadyImplemented: false, blockers: ['missing-spec'] };
7
+ }
8
+ if (spec.fm.status === 'implemented') {
9
+ return {
10
+ specCode,
11
+ level: spec.fm.level,
12
+ currentStatus: spec.fm.status,
13
+ expectedStatus,
14
+ ready: false,
15
+ alreadyImplemented: true,
16
+ blockers: [],
17
+ };
18
+ }
19
+ const blockers = [];
20
+ if (spec.fm.level === 'L3') {
21
+ if (authority !== 'task-complete')
22
+ blockers.push('authority-not-allowed');
23
+ if (spec.fm.status !== 'frozen')
24
+ blockers.push('wrong-status');
25
+ }
26
+ else if (spec.fm.level === 'L1' || spec.fm.level === 'L2') {
27
+ if (spec.fm.status !== 'confirmed')
28
+ blockers.push('wrong-status');
29
+ const children = listAllSpecs(paths).filter(child => child.fm.parentCode === specCode);
30
+ if (children.length === 0)
31
+ blockers.push('no-children');
32
+ else if (children.some(child => child.fm.status !== 'implemented'))
33
+ blockers.push('children-incomplete');
34
+ }
35
+ else {
36
+ blockers.push('authority-not-allowed');
37
+ }
38
+ return {
39
+ specCode,
40
+ level: spec.fm.level,
41
+ currentStatus: spec.fm.status,
42
+ expectedStatus,
43
+ ready: blockers.length === 0,
44
+ alreadyImplemented: false,
45
+ blockers,
46
+ };
47
+ }
48
+ export function cascadeImplementedHierarchy(options) {
49
+ const result = { cascadedSpecs: [], skippedSpecs: [] };
50
+ cascadeOne(options, options.startSpecCode, result);
51
+ return result;
52
+ }
53
+ function cascadeOne(options, specCode, result) {
54
+ const spec = findSpecByCode(options.paths, specCode);
55
+ const readiness = assessImplementationReadiness(options.paths, specCode, options.authority);
56
+ if (!spec || !readiness.ready) {
57
+ result.skippedSpecs.push({
58
+ code: specCode,
59
+ status: readiness.currentStatus ?? 'missing',
60
+ reason: readiness.alreadyImplemented ? 'already implemented' : readiness.blockers.join(', '),
61
+ });
62
+ return;
63
+ }
64
+ const oldStatus = spec.fm.status;
65
+ updateSpec(options.paths, specCode, { status: 'implemented', changeSummary: `cascade: ${options.authority}` }, { auditSink: options.auditSink, transitionAuthority: options.authority });
66
+ result.cascadedSpecs.push({ code: specCode, oldStatus, newStatus: 'implemented', level: spec.fm.level });
67
+ if (spec.fm.parentCode)
68
+ cascadeOne(options, spec.fm.parentCode, result);
69
+ }
70
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAwCxE,MAAM,UAAU,6BAA6B,CAC3C,KAAmB,EACnB,QAAgB,EAChB,SAAkC;IAElC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,IAAI,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;IACxE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;IACxH,CAAC;IACD,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QACrC,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK;YACpB,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM;YAC7B,cAAc;YACd,KAAK,EAAE,KAAK;YACZ,kBAAkB,EAAE,IAAI;YACxB,QAAQ,EAAE,EAAE;SACb,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC3B,IAAI,SAAS,KAAK,eAAe;YAAE,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC1E,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACjE,CAAC;SAAM,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC5D,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,WAAW;YAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC;QACvF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aACnD,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,KAAK,aAAa,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAC3G,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;QACL,QAAQ;QACR,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK;QACpB,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM;QAC7B,cAAc;QACd,KAAK,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC5B,kBAAkB,EAAE,KAAK;QACzB,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,OAA2C;IACrF,MAAM,MAAM,GAA2B,EAAE,aAAa,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC/E,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CACjB,OAA2C,EAC3C,QAAgB,EAChB,MAA8B;IAE9B,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,6BAA6B,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5F,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC;YACvB,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,SAAS,CAAC,aAAa,IAAI,SAAS;YAC5C,MAAM,EAAE,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7F,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IACjC,UAAU,CACR,OAAO,CAAC,KAAK,EACb,QAAQ,EACR,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,OAAO,CAAC,SAAS,EAAE,EAAE,EACzE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,mBAAmB,EAAE,OAAO,CAAC,SAAS,EAAE,CACzE,CAAC;IACF,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IAEzG,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU;QAAE,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAC1E,CAAC"}
@@ -9,6 +9,7 @@ export interface ProjectPaths {
9
9
  configDir: string;
10
10
  configFile: string;
11
11
  auditFile: string;
12
+ integrityExemptionsFile: string;
12
13
  incidentsDir: string;
13
14
  dictFile: string;
14
15
  specsDir: string;
@@ -31,6 +32,8 @@ export declare function getPaths(root?: string): ProjectPaths;
31
32
  export declare function specFilePath(paths: ProjectPaths, _parentFilePath: string | null, code: string, topic?: string, _date?: string): string;
32
33
  export declare function assertSafeTopic(topic: string): void;
33
34
  export declare function assertSafeSpecCode(code: string): void;
35
+ export declare function assertSafeChangeName(name: string): void;
36
+ export declare function resolveWithin(baseDir: string, ...segments: string[]): string;
34
37
  /**
35
38
  * 平铺布局下,元数据目录在 topic 级别:
36
39
  * specs/<topic>/decisions/、specs/<topic>/tasks/
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAYtE;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,QAAQ,CAAC,IAAI,GAAE,MAA6B,GAAG,YAAY,CAe1E;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAKR;AASD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIrD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,GAAG,MAAM,CAExF;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,EAAE,CAqBlE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,EAAE,CAoB/E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAU7E"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAYtE;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB,EAAE,MAAM,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,QAAQ,CAAC,IAAI,GAAE,MAA6B,GAAG,YAAY,CAgB1E;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAKR;AASD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIrD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIvD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAW5E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,GAAG,MAAM,CAExF;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,EAAE,CAqBlE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,EAAE,CAoB/E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAU7E"}
@@ -1,5 +1,5 @@
1
1
  import { existsSync, readdirSync, statSync } from 'node:fs';
2
- import { dirname, join, resolve } from 'node:path';
2
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
3
3
  import { SPEC_CODE_RE, TOPIC_RE } from './constants.js';
4
4
  /**
5
5
  * 解析项目根目录。
@@ -29,6 +29,7 @@ export function getPaths(root = resolveProjectRoot()) {
29
29
  configDir,
30
30
  configFile: join(configDir, 'config.yaml'),
31
31
  auditFile: join(configDir, 'audit.json'),
32
+ integrityExemptionsFile: join(configDir, 'integrity-exemptions.json'),
32
33
  incidentsDir: join(configDir, 'incidents'),
33
34
  dictFile: join(configDir, 'dict.yaml'),
34
35
  specsDir: join(root, 'specs'),
@@ -79,6 +80,23 @@ export function assertSafeSpecCode(code) {
79
80
  throw new Error(`spec code 非法: ${code}(必须匹配 ${SPEC_CODE_RE.source},且不能包含路径分隔符)`);
80
81
  }
81
82
  }
83
+ export function assertSafeChangeName(name) {
84
+ if (!/^[a-z0-9-]+$/.test(name)) {
85
+ throw new Error(`PATH_OUTSIDE_PROJECT: change name 非法: ${name}`);
86
+ }
87
+ }
88
+ export function resolveWithin(baseDir, ...segments) {
89
+ if (segments.some(segment => isAbsolute(segment))) {
90
+ throw new Error(`PATH_OUTSIDE_PROJECT: absolute path is not allowed`);
91
+ }
92
+ const base = resolve(baseDir);
93
+ const target = resolve(base, ...segments);
94
+ const rel = relative(base, target);
95
+ if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`) || isAbsolute(rel)) {
96
+ throw new Error(`PATH_OUTSIDE_PROJECT: ${target} is outside ${base}`);
97
+ }
98
+ return target;
99
+ }
82
100
  /**
83
101
  * 平铺布局下,元数据目录在 topic 级别:
84
102
  * specs/<topic>/decisions/、specs/<topic>/tasks/
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAExD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC9C,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAErC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QACvD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAeD,MAAM,UAAU,QAAQ,CAAC,OAAe,kBAAkB,EAAE;IAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC;IAClE,OAAO;QACL,IAAI;QACJ,SAAS;QACT,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC;QAC1C,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC;QACxC,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC;QAC1C,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC;QACtC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;QAC7B,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACjC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACjC,aAAa;KACd,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAmB,EACnB,eAA8B,EAC9B,IAAY,EACZ,KAAc,EACd,KAAc;IAEd,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,CAAC,GAAG,KAAK,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC9C,eAAe,CAAC,CAAC,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACxC,6CAA6C;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACtC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,QAAQ,CAAC,MAAM,cAAc,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,SAAS,YAAY,CAAC,MAAM,cAAc,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,YAAoB,EAAE,IAA2B;IAC9E,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC;AAsBD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAmB;IAC/C,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO,GAAG,CAAC;IAC5C,KAAK,MAAM,UAAU,IAAI,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9E,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACvD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAClE,IAAI,IAAI,CAAC,WAAW,EAAE;gBAAE,SAAS;YACjC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACzC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YACxC,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM;gBAAE,SAAS;YACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;YACjF,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,CAAC,IAAI,KAAK,GAAG,CAAC,QAAQ,KAAK,QAAQ,GAAG,CAAC,CAAC;YACjF,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAmB;IACxD,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO,GAAG,CAAC;IAC5C,KAAK,MAAM,UAAU,IAAI,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9E,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACvD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAClE,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YAC5F,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,aAAa,IAAI,CAAC,MAAM,CAAC,UAAU;gBAAE,SAAS;YAC/E,GAAG,CAAC,IAAI,CAAC;gBACP,KAAK,EAAE,UAAU,CAAC,IAAI;gBACtB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC;gBAC/B,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,IAAI,KAAK,CAAC;gBACvC,UAAU,EAAE,MAAM,CAAC,UAAU;aAC9B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACpD,IAAI,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,CAAC;IACD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACzC,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * R22: contentTemplate 是不是只剩 createSpec 写出的占位?
3
+ * 占位 = 文件里有 marker 行,且去掉 marker 后正文长度 < PLACEHOLDER_CONTENT_MAX。
4
+ */
5
+ export declare function isPlaceholderContent(content: string): boolean;
6
+ //# sourceMappingURL=placeholder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder.d.ts","sourceRoot":"","sources":["../../src/core/placeholder.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAI7D"}
@@ -0,0 +1,12 @@
1
+ import { PLACEHOLDER_CONTENT_MAX, PLACEHOLDER_MARKER } from './constants.js';
2
+ /**
3
+ * R22: contentTemplate 是不是只剩 createSpec 写出的占位?
4
+ * 占位 = 文件里有 marker 行,且去掉 marker 后正文长度 < PLACEHOLDER_CONTENT_MAX。
5
+ */
6
+ export function isPlaceholderContent(content) {
7
+ if (!content || !content.includes(PLACEHOLDER_MARKER))
8
+ return false;
9
+ const stripped = content.replace(PLACEHOLDER_MARKER, '').trim();
10
+ return stripped.length < PLACEHOLDER_CONTENT_MAX;
11
+ }
12
+ //# sourceMappingURL=placeholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../../src/core/placeholder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,OAAO,QAAQ,CAAC,MAAM,GAAG,uBAAuB,CAAC;AACnD,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { ProjectPaths } from './paths.js';
2
+ import { type CreateDecisionInput } from './decision.js';
3
+ export interface ReconciliationAction {
4
+ action: 'implement' | 'create' | 'skip';
5
+ target: string;
6
+ detail: string;
7
+ }
8
+ export interface ReconciliationConflict {
9
+ target: string;
10
+ message: string;
11
+ }
12
+ export interface LifecycleReconciliationPlan {
13
+ implementationActions: ReconciliationAction[];
14
+ decisionActions: ReconciliationAction[];
15
+ conflicts: ReconciliationConflict[];
16
+ }
17
+ export interface LifecycleReconciliationReport extends LifecycleReconciliationPlan {
18
+ applied: boolean;
19
+ }
20
+ export declare const LIFECYCLE_RECONCILIATION_TARGETS: readonly ["architecture-hardening-L2.1", "architecture-hardening-L1", "harness-coding-L2.1", "harness-coding-L1", "repository-remediation-L2.1", "repository-remediation-L1"];
21
+ export declare const LIFECYCLE_RECONCILIATION_STARTS: readonly ["architecture-hardening-L2.1", "harness-coding-L2.1", "repository-remediation-L2.1"];
22
+ export declare const LIFECYCLE_RECONCILIATION_DECISIONS: Omit<CreateDecisionInput, 'paths'>[];
23
+ export declare function planLifecycleReconciliation(paths: ProjectPaths): LifecycleReconciliationPlan;
24
+ export declare function applyLifecycleReconciliation(paths: ProjectPaths): LifecycleReconciliationReport;
25
+ //# sourceMappingURL=reconciliation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciliation.d.ts","sourceRoot":"","sources":["../../src/core/reconciliation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAiD,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAKxG,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC1C,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;IAC9C,eAAe,EAAE,oBAAoB,EAAE,CAAC;IACxC,SAAS,EAAE,sBAAsB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,6BAA8B,SAAQ,2BAA2B;IAChF,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,gCAAgC,+KAOnC,CAAC;AAEX,eAAO,MAAM,+BAA+B,gGAIlC,CAAC;AAEX,eAAO,MAAM,kCAAkC,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,EAmBlF,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,YAAY,GAAG,2BAA2B,CAkD5F;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,YAAY,GAAG,6BAA6B,CA4B/F"}