@devtrack-solution/codesdd 1.2.3 → 1.2.4

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 (213) hide show
  1. package/.sdd/skills/curated/devtrack-api/SKILL.md +98 -12
  2. package/.sdd/skills/curated/devtrack-api/agents/claude-code.yaml +10 -0
  3. package/.sdd/skills/curated/devtrack-api/agents/codex.yaml +10 -0
  4. package/.sdd/skills/curated/devtrack-api/agents/cursor.yaml +10 -0
  5. package/.sdd/skills/curated/devtrack-api/agents/gemini.yaml +10 -0
  6. package/.sdd/skills/curated/devtrack-api/agents/kimi.yaml +10 -0
  7. package/.sdd/skills/curated/devtrack-api/agents/openai.yaml +5 -3
  8. package/.sdd/skills/curated/devtrack-api/agents/opencode.yaml +12 -0
  9. package/.sdd/skills/curated/devtrack-api/references/application-presentation.md +61 -5
  10. package/.sdd/skills/curated/devtrack-api/references/consumer-sync-policy.md +15 -3
  11. package/.sdd/skills/curated/devtrack-api/references/contract-pack.yaml +1951 -0
  12. package/.sdd/skills/curated/devtrack-api/references/domain-modeling.md +16 -14
  13. package/.sdd/skills/curated/devtrack-api/references/field-validation-protocol.md +40 -0
  14. package/.sdd/skills/curated/devtrack-api/references/foundation-layout.md +19 -2
  15. package/.sdd/skills/curated/devtrack-api/references/generated-artifact-invalidation.md +97 -0
  16. package/.sdd/skills/curated/devtrack-api/references/implementation-checklist.md +30 -1
  17. package/.sdd/skills/curated/devtrack-api/references/portable-agent-contract.md +42 -0
  18. package/.sdd/skills/curated/devtrack-api/references/testing-validation.md +22 -1
  19. package/.sdd/skills/curated/devtrack-api/references/typeorm-infrastructure.md +9 -7
  20. package/README.md +280 -29
  21. package/dist/applications/sdd/index.d.ts +16 -0
  22. package/dist/applications/sdd/index.js +16 -0
  23. package/dist/cli/program.js +180 -11
  24. package/dist/commands/config.js +197 -10
  25. package/dist/commands/sdd/execution.js +408 -16
  26. package/dist/commands/sdd/plugin.js +5 -0
  27. package/dist/commands/sdd/shared.d.ts +1 -0
  28. package/dist/commands/sdd/shared.js +10 -0
  29. package/dist/commands/sdd.js +157 -7
  30. package/dist/core/cli/command-matrix.d.ts +18 -0
  31. package/dist/core/cli/command-matrix.js +157 -0
  32. package/dist/core/cli-command-quality.js +11 -0
  33. package/dist/core/completions/command-registry.js +45 -0
  34. package/dist/core/config-schema.d.ts +31 -1
  35. package/dist/core/config-schema.js +79 -5
  36. package/dist/core/config.d.ts +1 -0
  37. package/dist/core/config.js +11 -0
  38. package/dist/core/global-config.d.ts +29 -0
  39. package/dist/core/init.d.ts +2 -2
  40. package/dist/core/init.js +13 -14
  41. package/dist/core/sdd/agent-binding.d.ts +19 -19
  42. package/dist/core/sdd/agent-runtime-contract.d.ts +204 -0
  43. package/dist/core/sdd/agent-runtime-contract.js +200 -0
  44. package/dist/core/sdd/allocator-recovery.d.ts +14 -0
  45. package/dist/core/sdd/allocator-recovery.js +30 -0
  46. package/dist/core/sdd/allocator-security.d.ts +18 -0
  47. package/dist/core/sdd/allocator-security.js +36 -0
  48. package/dist/core/sdd/api-foundation-baseline.d.ts +111 -0
  49. package/dist/core/sdd/api-foundation-baseline.js +151 -0
  50. package/dist/core/sdd/api-foundation-parity.d.ts +114 -0
  51. package/dist/core/sdd/api-foundation-parity.js +131 -0
  52. package/dist/core/sdd/api-profile-catalog.d.ts +36 -0
  53. package/dist/core/sdd/api-profile-catalog.js +132 -0
  54. package/dist/core/sdd/api-profile-dry-run-projection.d.ts +93 -0
  55. package/dist/core/sdd/api-profile-dry-run-projection.js +370 -0
  56. package/dist/core/sdd/api-profile-recipes.d.ts +82 -0
  57. package/dist/core/sdd/api-profile-recipes.js +484 -0
  58. package/dist/core/sdd/artifact-id-allocator.d.ts +368 -0
  59. package/dist/core/sdd/artifact-id-allocator.js +510 -0
  60. package/dist/core/sdd/check.d.ts +52 -1
  61. package/dist/core/sdd/check.js +326 -11
  62. package/dist/core/sdd/coordination/coordination-adapters.d.ts +15 -8
  63. package/dist/core/sdd/coordination/coordination-adapters.js +43 -15
  64. package/dist/core/sdd/coordination/index.d.ts +1 -0
  65. package/dist/core/sdd/coordination/index.js +1 -0
  66. package/dist/core/sdd/coordination/redis-runtime.d.ts +131 -0
  67. package/dist/core/sdd/coordination/redis-runtime.js +698 -0
  68. package/dist/core/sdd/deepagent-contracts.d.ts +99 -5
  69. package/dist/core/sdd/deepagent-contracts.js +62 -0
  70. package/dist/core/sdd/deepagents/reversa-subagents.d.ts +3 -3
  71. package/dist/core/sdd/default-bootstrap-files.d.ts +2 -2
  72. package/dist/core/sdd/default-bootstrap-files.js +14 -10
  73. package/dist/core/sdd/default-skills.js +115 -9
  74. package/dist/core/sdd/devtrack-api-appliance.d.ts +42 -1
  75. package/dist/core/sdd/devtrack-api-appliance.js +159 -32
  76. package/dist/core/sdd/devtrack-api-architecture.d.ts +16 -0
  77. package/dist/core/sdd/devtrack-api-architecture.js +86 -0
  78. package/dist/core/sdd/docs-sync.js +24 -18
  79. package/dist/core/sdd/domain/capability-diff.d.ts +63 -0
  80. package/dist/core/sdd/domain/capability-diff.js +200 -0
  81. package/dist/core/sdd/domain/change-safety-guardrails.d.ts +74 -0
  82. package/dist/core/sdd/domain/change-safety-guardrails.js +333 -0
  83. package/dist/core/sdd/domain/semantic-intent-classifier.d.ts +29 -0
  84. package/dist/core/sdd/domain/semantic-intent-classifier.js +117 -0
  85. package/dist/core/sdd/enterprise-mutating-command-gate.d.ts +27 -0
  86. package/dist/core/sdd/enterprise-mutating-command-gate.js +104 -0
  87. package/dist/core/sdd/enterprise-provenance-gates.d.ts +20 -0
  88. package/dist/core/sdd/enterprise-provenance-gates.js +63 -0
  89. package/dist/core/sdd/enterprise-provisioning-policy.d.ts +26 -0
  90. package/dist/core/sdd/enterprise-provisioning-policy.js +104 -0
  91. package/dist/core/sdd/foundation-artifact-map-validator.d.ts +16 -0
  92. package/dist/core/sdd/foundation-artifact-map-validator.js +71 -0
  93. package/dist/core/sdd/foundation-layer-manifest.d.ts +24 -0
  94. package/dist/core/sdd/foundation-layer-manifest.js +117 -0
  95. package/dist/core/sdd/governance-schemas.d.ts +2 -2
  96. package/dist/core/sdd/governance-schemas.js +11 -2
  97. package/dist/core/sdd/intent-guard.d.ts +22 -0
  98. package/dist/core/sdd/intent-guard.js +67 -0
  99. package/dist/core/sdd/json-schema.js +13 -1
  100. package/dist/core/sdd/legacy-operations.js +169 -5
  101. package/dist/core/sdd/migrate-workspace.js +39 -0
  102. package/dist/core/sdd/package-security-gates.d.ts +21 -0
  103. package/dist/core/sdd/package-security-gates.js +121 -0
  104. package/dist/core/sdd/package-structure-gate.d.ts +85 -3
  105. package/dist/core/sdd/package-structure-gate.js +384 -11
  106. package/dist/core/sdd/parallel-feat-automation.d.ts +185 -7
  107. package/dist/core/sdd/parallel-feat-automation.js +212 -0
  108. package/dist/core/sdd/plugin-broker.d.ts +223 -4
  109. package/dist/core/sdd/plugin-broker.js +10 -0
  110. package/dist/core/sdd/plugin-cli.d.ts +30 -0
  111. package/dist/core/sdd/plugin-cli.js +70 -3
  112. package/dist/core/sdd/plugin-evidence.d.ts +73 -0
  113. package/dist/core/sdd/plugin-manifest.d.ts +69 -1
  114. package/dist/core/sdd/plugin-manifest.js +10 -0
  115. package/dist/core/sdd/plugin-policy-pack.d.ts +1 -1
  116. package/dist/core/sdd/plugin-policy.js +6 -1
  117. package/dist/core/sdd/plugin-registry.d.ts +138 -2
  118. package/dist/core/sdd/plugin-sdk-contract.d.ts +363 -0
  119. package/dist/core/sdd/plugin-sdk-contract.js +268 -0
  120. package/dist/core/sdd/plugin-skill-binding.d.ts +1 -1
  121. package/dist/core/sdd/quality-validation.d.ts +89 -16
  122. package/dist/core/sdd/release-readiness.d.ts +68 -0
  123. package/dist/core/sdd/release-readiness.js +767 -0
  124. package/dist/core/sdd/reversa-architecture-extractor.d.ts +13 -0
  125. package/dist/core/sdd/reversa-architecture-extractor.js +89 -0
  126. package/dist/core/sdd/reversa-artifact-writer.d.ts +18 -0
  127. package/dist/core/sdd/reversa-artifact-writer.js +40 -0
  128. package/dist/core/sdd/reversa-command-policy.d.ts +136 -0
  129. package/dist/core/sdd/reversa-command-policy.js +361 -0
  130. package/dist/core/sdd/reversa-data-extractor.d.ts +11 -0
  131. package/dist/core/sdd/reversa-data-extractor.js +73 -0
  132. package/dist/core/sdd/reversa-equivalence.d.ts +20 -0
  133. package/dist/core/sdd/reversa-equivalence.js +34 -0
  134. package/dist/core/sdd/reversa-evidence.d.ts +298 -0
  135. package/dist/core/sdd/reversa-evidence.js +118 -0
  136. package/dist/core/sdd/reversa-reconstruction.d.ts +29 -0
  137. package/dist/core/sdd/reversa-reconstruction.js +32 -0
  138. package/dist/core/sdd/reversa-rules-extractor.d.ts +12 -0
  139. package/dist/core/sdd/reversa-rules-extractor.js +86 -0
  140. package/dist/core/sdd/reversa-source-safety.d.ts +19 -0
  141. package/dist/core/sdd/reversa-source-safety.js +105 -0
  142. package/dist/core/sdd/reversa-surface-scout.d.ts +13 -0
  143. package/dist/core/sdd/reversa-surface-scout.js +85 -0
  144. package/dist/core/sdd/reversa-ux-mapper.d.ts +11 -0
  145. package/dist/core/sdd/reversa-ux-mapper.js +73 -0
  146. package/dist/core/sdd/runtime-boundary-contract.d.ts +45 -0
  147. package/dist/core/sdd/runtime-boundary-contract.js +90 -0
  148. package/dist/core/sdd/sdk-agent-plugin-quality-gates.d.ts +150 -0
  149. package/dist/core/sdd/sdk-agent-plugin-quality-gates.js +258 -0
  150. package/dist/core/sdd/services/agent-run.service.d.ts +38 -6
  151. package/dist/core/sdd/services/agent-run.service.js +73 -1
  152. package/dist/core/sdd/services/archive-quality-coherence.service.d.ts +17 -0
  153. package/dist/core/sdd/services/archive-quality-coherence.service.js +141 -0
  154. package/dist/core/sdd/services/capability-diff.service.d.ts +18 -0
  155. package/dist/core/sdd/services/capability-diff.service.js +26 -0
  156. package/dist/core/sdd/services/change-safety-preflight.service.d.ts +17 -0
  157. package/dist/core/sdd/services/change-safety-preflight.service.js +17 -0
  158. package/dist/core/sdd/services/context.service.d.ts +43 -340
  159. package/dist/core/sdd/services/context.service.js +323 -9
  160. package/dist/core/sdd/services/decide.service.js +1 -1
  161. package/dist/core/sdd/services/finalize.service.d.ts +27 -0
  162. package/dist/core/sdd/services/finalize.service.js +226 -18
  163. package/dist/core/sdd/services/frontend-impact.service.d.ts +1 -1
  164. package/dist/core/sdd/services/historical-quality-regression.service.d.ts +35 -0
  165. package/dist/core/sdd/services/historical-quality-regression.service.js +228 -0
  166. package/dist/core/sdd/services/ingest-deposito.service.js +1 -1
  167. package/dist/core/sdd/services/planning-execution-coherence.service.d.ts +45 -0
  168. package/dist/core/sdd/services/planning-execution-coherence.service.js +225 -0
  169. package/dist/core/sdd/services/semantic-intent-classifier.service.d.ts +6 -0
  170. package/dist/core/sdd/services/semantic-intent-classifier.service.js +7 -0
  171. package/dist/core/sdd/state.d.ts +1 -0
  172. package/dist/core/sdd/state.js +266 -34
  173. package/dist/core/sdd/store/sdd-stores.js +2 -2
  174. package/dist/core/sdd/structural-health.d.ts +13 -13
  175. package/dist/core/sdd/types.d.ts +30 -15
  176. package/dist/core/sdd/types.js +4 -0
  177. package/dist/core/sdd/views.js +17 -0
  178. package/dist/core/sdd/workspace-schemas.d.ts +428 -7
  179. package/dist/core/sdd/workspace-schemas.js +223 -70
  180. package/dist/core/shared/skill-generation.d.ts +2 -0
  181. package/dist/core/shared/skill-generation.js +19 -2
  182. package/dist/core/shared/tool-detection.d.ts +19 -0
  183. package/dist/core/shared/tool-detection.js +89 -0
  184. package/dist/domains/sdd/index.d.ts +6 -0
  185. package/dist/domains/sdd/index.js +6 -0
  186. package/dist/infrastructures/sdd/index.d.ts +7 -0
  187. package/dist/infrastructures/sdd/index.js +6 -0
  188. package/dist/presentations/cli/sdd/index.d.ts +3 -0
  189. package/dist/presentations/cli/sdd/index.js +3 -0
  190. package/dist/shared/sdd/index.d.ts +3 -0
  191. package/dist/shared/sdd/index.js +2 -0
  192. package/package.json +14 -10
  193. package/schemas/sdd/2-plan.schema.json +207 -2
  194. package/schemas/sdd/5-quality.schema.json +324 -25
  195. package/schemas/sdd/agent-runtime-command-plan.schema.json +212 -0
  196. package/schemas/sdd/agent-runtime-opencode-run-evidence.schema.json +270 -0
  197. package/schemas/sdd/codesdd-plugin.schema.json +171 -0
  198. package/schemas/sdd/deepagent-run-request.schema.json +316 -0
  199. package/schemas/sdd/parallel-feat-automation-plan.schema.json +89 -0
  200. package/schemas/sdd/parallel-feat-scheduler-request.schema.json +116 -0
  201. package/schemas/sdd/parallel-feat-scheduler-result.schema.json +404 -0
  202. package/schemas/sdd/plugin-artifact-manifest.schema.json +109 -0
  203. package/schemas/sdd/plugin-artifact-map.schema.json +223 -0
  204. package/schemas/sdd/plugin-evidence-manifest.schema.json +109 -0
  205. package/schemas/sdd/plugin-language-runtime.schema.json +103 -0
  206. package/schemas/sdd/plugin-package-governance.schema.json +74 -0
  207. package/schemas/sdd/plugin-registry.schema.json +171 -0
  208. package/schemas/sdd/plugin-runtime-invocation-plan.schema.json +109 -0
  209. package/schemas/sdd/quality-evidence-bundle.schema.json +109 -0
  210. package/schemas/sdd/reversa-evidence-bundle.schema.json +466 -0
  211. package/schemas/sdd/sdk-agent-plugin-quality-gate-input.schema.json +168 -0
  212. package/schemas/sdd/sdk-agent-plugin-quality-gate-report.schema.json +160 -0
  213. package/schemas/sdd/workspace-catalog.schema.json +5298 -1409
@@ -0,0 +1,510 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ export const artifactIdAllocatorTypeSchema = z.enum(['INS', 'DEB', 'EPIC', 'FEAT', 'FGAP', 'TD']);
4
+ export const allocatorActorSchema = z.object({
5
+ agent_id: z.string().min(1),
6
+ agent_kind: z.string().min(1).optional(),
7
+ });
8
+ export const artifactIdReserveRequestSchema = z.object({
9
+ schema_version: z.literal(1),
10
+ project_id: z.string().min(1),
11
+ tenant_id: z.string().min(1).optional(),
12
+ artifact_type: artifactIdAllocatorTypeSchema,
13
+ title_canonical: z.string().min(1).optional(),
14
+ origin_ref: z.string().min(1).optional(),
15
+ requested_by: allocatorActorSchema,
16
+ client_request_id: z.string().min(1).optional(),
17
+ idempotency_key: z.string().min(16),
18
+ });
19
+ export const artifactIdReservationSchema = z.object({
20
+ schema_version: z.literal(1),
21
+ artifact_id: z.string().regex(/^(INS|DEB|EPIC|FEAT|FGAP|TD)-\d{4}$/),
22
+ artifact_type: artifactIdAllocatorTypeSchema,
23
+ sequence: z.number().int().positive(),
24
+ project_id: z.string().min(1),
25
+ tenant_id: z.string().min(1).optional(),
26
+ idempotency_key: z.string().min(16),
27
+ request_fingerprint: z.string().min(16),
28
+ revision: z.number().int().positive(),
29
+ reserved_at: z.string().datetime(),
30
+ });
31
+ export const artifactIdReserveResponseSchema = z.object({
32
+ schema_version: z.literal(1),
33
+ status: z.enum(['reserved', 'replayed']),
34
+ reservation: artifactIdReservationSchema,
35
+ });
36
+ export const artifactAllocatorLeaseRequestSchema = z.object({
37
+ schema_version: z.literal(1),
38
+ project_id: z.string().min(1),
39
+ tenant_id: z.string().min(1).optional(),
40
+ artifact_type: artifactIdAllocatorTypeSchema,
41
+ holder: allocatorActorSchema,
42
+ ttl_ms: z.number().int().positive(),
43
+ idempotency_key: z.string().min(16),
44
+ });
45
+ export const artifactAllocatorLeaseSchema = z.object({
46
+ schema_version: z.literal(1),
47
+ lease_id: z.string().min(16),
48
+ project_id: z.string().min(1),
49
+ tenant_id: z.string().min(1).optional(),
50
+ artifact_type: artifactIdAllocatorTypeSchema,
51
+ holder: allocatorActorSchema,
52
+ fencing_token: z.number().int().positive(),
53
+ idempotency_key: z.string().min(16),
54
+ request_fingerprint: z.string().min(16),
55
+ acquired_at: z.string().datetime(),
56
+ expires_at: z.string().datetime(),
57
+ });
58
+ export const artifactAllocatorLeaseResponseSchema = z.object({
59
+ schema_version: z.literal(1),
60
+ status: z.enum(['acquired', 'replayed']),
61
+ lease: artifactAllocatorLeaseSchema,
62
+ });
63
+ export const artifactAllocatorAuditEventSchema = z.object({
64
+ schema_version: z.literal(1),
65
+ event_id: z.string().min(16),
66
+ event_type: z.enum([
67
+ 'lease_acquired',
68
+ 'lease_replayed',
69
+ 'lease_conflict',
70
+ 'reservation_created',
71
+ 'reservation_replayed',
72
+ 'canonical_write_committed',
73
+ 'canonical_write_replayed',
74
+ 'canonical_write_rejected',
75
+ ]),
76
+ project_id: z.string().min(1),
77
+ tenant_id: z.string().min(1).optional(),
78
+ artifact_type: artifactIdAllocatorTypeSchema,
79
+ actor: allocatorActorSchema,
80
+ idempotency_key: z.string().min(16),
81
+ lease_id: z.string().min(16).optional(),
82
+ fencing_token: z.number().int().positive().optional(),
83
+ occurred_at: z.string().datetime(),
84
+ result: z.enum(['accepted', 'replayed', 'blocked']),
85
+ });
86
+ export const canonicalArtifactWriteRequestSchema = z.object({
87
+ schema_version: z.literal(1),
88
+ artifact_id: z.string().regex(/^(INS|DEB|EPIC|FEAT|FGAP|TD)-\d{4}$/),
89
+ project_id: z.string().min(1),
90
+ tenant_id: z.string().min(1).optional(),
91
+ actor: allocatorActorSchema,
92
+ lease_id: z.string().min(16),
93
+ fencing_token: z.number().int().positive(),
94
+ expected_revision: z.number().int().min(0),
95
+ idempotency_key: z.string().min(16),
96
+ });
97
+ export const canonicalArtifactWriteRecordSchema = z.object({
98
+ schema_version: z.literal(1),
99
+ artifact_id: z.string().regex(/^(INS|DEB|EPIC|FEAT|FGAP|TD)-\d{4}$/),
100
+ project_id: z.string().min(1),
101
+ tenant_id: z.string().min(1).optional(),
102
+ revision: z.number().int().positive(),
103
+ previous_revision: z.number().int().min(0),
104
+ lease_id: z.string().min(16),
105
+ fencing_token: z.number().int().positive(),
106
+ idempotency_key: z.string().min(16),
107
+ request_fingerprint: z.string().min(16),
108
+ committed_at: z.string().datetime(),
109
+ });
110
+ export const canonicalArtifactWriteResponseSchema = z.object({
111
+ schema_version: z.literal(1),
112
+ status: z.enum(['committed', 'replayed']),
113
+ write: canonicalArtifactWriteRecordSchema,
114
+ });
115
+ export const noncanonicalDraftSchema = z.object({
116
+ schema_version: z.literal(1),
117
+ draft_id: z.string().regex(/^draft_(INS|DEB|EPIC|FEAT|FGAP|TD)_[a-f0-9]{16}$/),
118
+ artifact_type: artifactIdAllocatorTypeSchema,
119
+ project_id: z.string().min(1),
120
+ tenant_id: z.string().min(1).optional(),
121
+ title_canonical: z.string().min(1),
122
+ created_by: allocatorActorSchema,
123
+ created_at: z.string().datetime(),
124
+ converted_artifact_id: z.string().regex(/^(INS|DEB|EPIC|FEAT|FGAP|TD)-\d{4}$/).optional(),
125
+ converted_at: z.string().datetime().optional(),
126
+ });
127
+ export const draftConversionResponseSchema = z.object({
128
+ schema_version: z.literal(1),
129
+ status: z.enum(['converted', 'replayed']),
130
+ draft: noncanonicalDraftSchema,
131
+ reservation: artifactIdReservationSchema,
132
+ });
133
+ export function createEmptyArtifactIdAllocatorState() {
134
+ return {
135
+ counters: {},
136
+ reservations: [],
137
+ leases: [],
138
+ audit_log: [],
139
+ next_fencing_token: 1,
140
+ canonical_revisions: {},
141
+ canonical_writes: [],
142
+ drafts: [],
143
+ };
144
+ }
145
+ export function buildArtifactIdAllocatorIdempotencyKey(input) {
146
+ return `alloc_${hashStableJson({
147
+ project_id: input.project_id,
148
+ tenant_id: input.tenant_id ?? null,
149
+ artifact_type: input.artifact_type,
150
+ title_canonical: input.title_canonical ?? null,
151
+ origin_ref: input.origin_ref ?? null,
152
+ requested_by: input.requested_by,
153
+ client_request_id: input.client_request_id ?? null,
154
+ })}`;
155
+ }
156
+ export function reserveArtifactId(state, requestInput, options = {}) {
157
+ const request = artifactIdReserveRequestSchema.parse(requestInput);
158
+ const requestFingerprint = buildReserveRequestFingerprint(request);
159
+ const existing = state.reservations.find((reservation) => reservation.idempotency_key === request.idempotency_key);
160
+ if (existing) {
161
+ if (existing.request_fingerprint !== requestFingerprint) {
162
+ throw new Error(`Allocator idempotency key conflict for ${request.idempotency_key}: request fingerprint does not match the existing reservation.`);
163
+ }
164
+ const response = artifactIdReserveResponseSchema.parse({
165
+ schema_version: 1,
166
+ status: 'replayed',
167
+ reservation: existing,
168
+ });
169
+ appendAuditEvent(state, {
170
+ event_type: 'reservation_replayed',
171
+ project_id: request.project_id,
172
+ tenant_id: request.tenant_id,
173
+ artifact_type: request.artifact_type,
174
+ actor: request.requested_by,
175
+ idempotency_key: request.idempotency_key,
176
+ occurred_at: options.now ?? new Date().toISOString(),
177
+ result: 'replayed',
178
+ });
179
+ return response;
180
+ }
181
+ const current = state.counters[request.artifact_type] ?? 0;
182
+ const sequence = current + 1;
183
+ const reservation = artifactIdReservationSchema.parse({
184
+ schema_version: 1,
185
+ artifact_id: `${request.artifact_type}-${String(sequence).padStart(4, '0')}`,
186
+ artifact_type: request.artifact_type,
187
+ sequence,
188
+ project_id: request.project_id,
189
+ tenant_id: request.tenant_id,
190
+ idempotency_key: request.idempotency_key,
191
+ request_fingerprint: requestFingerprint,
192
+ revision: 1,
193
+ reserved_at: options.now ?? new Date().toISOString(),
194
+ });
195
+ state.counters[request.artifact_type] = sequence;
196
+ state.reservations.push(reservation);
197
+ appendAuditEvent(state, {
198
+ event_type: 'reservation_created',
199
+ project_id: request.project_id,
200
+ tenant_id: request.tenant_id,
201
+ artifact_type: request.artifact_type,
202
+ actor: request.requested_by,
203
+ idempotency_key: request.idempotency_key,
204
+ occurred_at: reservation.reserved_at,
205
+ result: 'accepted',
206
+ });
207
+ return artifactIdReserveResponseSchema.parse({
208
+ schema_version: 1,
209
+ status: 'reserved',
210
+ reservation,
211
+ });
212
+ }
213
+ export function acquireArtifactAllocatorLease(state, requestInput, options = {}) {
214
+ const request = artifactAllocatorLeaseRequestSchema.parse(requestInput);
215
+ const now = options.now ?? new Date().toISOString();
216
+ const requestFingerprint = buildLeaseRequestFingerprint(request);
217
+ const existing = state.leases.find((lease) => lease.idempotency_key === request.idempotency_key);
218
+ if (existing) {
219
+ if (existing.request_fingerprint !== requestFingerprint) {
220
+ appendAuditEvent(state, {
221
+ event_type: 'lease_conflict',
222
+ project_id: request.project_id,
223
+ tenant_id: request.tenant_id,
224
+ artifact_type: request.artifact_type,
225
+ actor: request.holder,
226
+ idempotency_key: request.idempotency_key,
227
+ occurred_at: now,
228
+ result: 'blocked',
229
+ });
230
+ throw new Error(`Allocator lease idempotency key conflict for ${request.idempotency_key}: request fingerprint does not match the existing lease.`);
231
+ }
232
+ appendAuditEvent(state, {
233
+ event_type: 'lease_replayed',
234
+ project_id: request.project_id,
235
+ tenant_id: request.tenant_id,
236
+ artifact_type: request.artifact_type,
237
+ actor: request.holder,
238
+ idempotency_key: request.idempotency_key,
239
+ lease_id: existing.lease_id,
240
+ fencing_token: existing.fencing_token,
241
+ occurred_at: now,
242
+ result: 'replayed',
243
+ });
244
+ return artifactAllocatorLeaseResponseSchema.parse({
245
+ schema_version: 1,
246
+ status: 'replayed',
247
+ lease: existing,
248
+ });
249
+ }
250
+ const activeLease = state.leases.find((lease) => lease.project_id === request.project_id &&
251
+ lease.tenant_id === request.tenant_id &&
252
+ lease.artifact_type === request.artifact_type &&
253
+ isAllocatorLeaseActive(lease, now));
254
+ if (activeLease) {
255
+ appendAuditEvent(state, {
256
+ event_type: 'lease_conflict',
257
+ project_id: request.project_id,
258
+ tenant_id: request.tenant_id,
259
+ artifact_type: request.artifact_type,
260
+ actor: request.holder,
261
+ idempotency_key: request.idempotency_key,
262
+ lease_id: activeLease.lease_id,
263
+ fencing_token: activeLease.fencing_token,
264
+ occurred_at: now,
265
+ result: 'blocked',
266
+ });
267
+ throw new Error(`Active allocator lease already exists for ${request.project_id}/${request.artifact_type}.`);
268
+ }
269
+ const fencingToken = state.next_fencing_token;
270
+ state.next_fencing_token += 1;
271
+ const lease = artifactAllocatorLeaseSchema.parse({
272
+ schema_version: 1,
273
+ lease_id: `lease_${hashStableJson({ request, fencingToken }).slice(0, 24)}`,
274
+ project_id: request.project_id,
275
+ tenant_id: request.tenant_id,
276
+ artifact_type: request.artifact_type,
277
+ holder: request.holder,
278
+ fencing_token: fencingToken,
279
+ idempotency_key: request.idempotency_key,
280
+ request_fingerprint: requestFingerprint,
281
+ acquired_at: now,
282
+ expires_at: new Date(new Date(now).getTime() + request.ttl_ms).toISOString(),
283
+ });
284
+ state.leases.push(lease);
285
+ appendAuditEvent(state, {
286
+ event_type: 'lease_acquired',
287
+ project_id: request.project_id,
288
+ tenant_id: request.tenant_id,
289
+ artifact_type: request.artifact_type,
290
+ actor: request.holder,
291
+ idempotency_key: request.idempotency_key,
292
+ lease_id: lease.lease_id,
293
+ fencing_token: lease.fencing_token,
294
+ occurred_at: now,
295
+ result: 'accepted',
296
+ });
297
+ return artifactAllocatorLeaseResponseSchema.parse({
298
+ schema_version: 1,
299
+ status: 'acquired',
300
+ lease,
301
+ });
302
+ }
303
+ export function isAllocatorLeaseActive(lease, now) {
304
+ return new Date(lease.expires_at).getTime() > new Date(now).getTime();
305
+ }
306
+ export function validateAllocatorFencingToken(lease, input) {
307
+ if (!isAllocatorLeaseActive(lease, input.now)) {
308
+ return { valid: false, reason: 'expired' };
309
+ }
310
+ if (lease.fencing_token !== input.fencing_token) {
311
+ return { valid: false, reason: 'stale-token' };
312
+ }
313
+ return { valid: true, reason: 'valid' };
314
+ }
315
+ export function commitCanonicalArtifactWrite(state, requestInput, options = {}) {
316
+ const request = canonicalArtifactWriteRequestSchema.parse(requestInput);
317
+ const now = options.now ?? new Date().toISOString();
318
+ const requestFingerprint = buildCanonicalWriteRequestFingerprint(request);
319
+ const existing = state.canonical_writes.find((write) => write.idempotency_key === request.idempotency_key);
320
+ if (existing) {
321
+ if (existing.request_fingerprint !== requestFingerprint) {
322
+ appendAuditEvent(state, buildCanonicalWriteAudit(request, now, 'canonical_write_rejected', 'blocked'));
323
+ throw new Error(`Canonical write idempotency key conflict for ${request.idempotency_key}.`);
324
+ }
325
+ appendAuditEvent(state, buildCanonicalWriteAudit(request, now, 'canonical_write_replayed', 'replayed'));
326
+ return canonicalArtifactWriteResponseSchema.parse({
327
+ schema_version: 1,
328
+ status: 'replayed',
329
+ write: existing,
330
+ });
331
+ }
332
+ const lease = state.leases.find((candidate) => candidate.lease_id === request.lease_id);
333
+ if (!lease) {
334
+ appendAuditEvent(state, buildCanonicalWriteAudit(request, now, 'canonical_write_rejected', 'blocked'));
335
+ throw new Error(`Canonical write rejected: lease ${request.lease_id} was not found.`);
336
+ }
337
+ const artifactType = artifactIdAllocatorTypeSchema.parse(request.artifact_id.split('-')[0]);
338
+ if (lease.project_id !== request.project_id ||
339
+ lease.tenant_id !== request.tenant_id ||
340
+ lease.artifact_type !== artifactType) {
341
+ appendAuditEvent(state, buildCanonicalWriteAudit(request, now, 'canonical_write_rejected', 'blocked'));
342
+ throw new Error('Canonical write rejected: allocator lease scope does not match artifact write request.');
343
+ }
344
+ const fencing = validateAllocatorFencingToken(lease, {
345
+ fencing_token: request.fencing_token,
346
+ now,
347
+ });
348
+ if (!fencing.valid) {
349
+ appendAuditEvent(state, buildCanonicalWriteAudit(request, now, 'canonical_write_rejected', 'blocked'));
350
+ throw new Error(`Canonical write rejected: allocator fencing token is ${fencing.reason}.`);
351
+ }
352
+ const currentRevision = state.canonical_revisions[request.artifact_id] ?? 0;
353
+ if (currentRevision !== request.expected_revision) {
354
+ appendAuditEvent(state, buildCanonicalWriteAudit(request, now, 'canonical_write_rejected', 'blocked'));
355
+ throw new Error(`Canonical write rejected: expected revision ${request.expected_revision} does not match current revision ${currentRevision}.`);
356
+ }
357
+ const write = canonicalArtifactWriteRecordSchema.parse({
358
+ schema_version: 1,
359
+ artifact_id: request.artifact_id,
360
+ project_id: request.project_id,
361
+ tenant_id: request.tenant_id,
362
+ revision: currentRevision + 1,
363
+ previous_revision: currentRevision,
364
+ lease_id: request.lease_id,
365
+ fencing_token: request.fencing_token,
366
+ idempotency_key: request.idempotency_key,
367
+ request_fingerprint: requestFingerprint,
368
+ committed_at: now,
369
+ });
370
+ state.canonical_revisions[request.artifact_id] = write.revision;
371
+ state.canonical_writes.push(write);
372
+ appendAuditEvent(state, buildCanonicalWriteAudit(request, now, 'canonical_write_committed', 'accepted'));
373
+ return canonicalArtifactWriteResponseSchema.parse({
374
+ schema_version: 1,
375
+ status: 'committed',
376
+ write,
377
+ });
378
+ }
379
+ export function createNoncanonicalDraft(state, input, options = {}) {
380
+ const createdAt = options.now ?? new Date().toISOString();
381
+ const draft = noncanonicalDraftSchema.parse({
382
+ schema_version: 1,
383
+ draft_id: `draft_${input.artifact_type}_${hashStableJson({ input, createdAt }).slice(0, 16)}`,
384
+ artifact_type: input.artifact_type,
385
+ project_id: input.project_id,
386
+ tenant_id: input.tenant_id,
387
+ title_canonical: input.title_canonical,
388
+ created_by: input.created_by,
389
+ created_at: createdAt,
390
+ });
391
+ state.drafts.push(draft);
392
+ return draft;
393
+ }
394
+ export function convertDraftToCanonicalArtifact(state, input, options = {}) {
395
+ const draft = state.drafts.find((candidate) => candidate.draft_id === input.draft_id);
396
+ if (!draft) {
397
+ throw new Error(`Draft ${input.draft_id} was not found.`);
398
+ }
399
+ if (draft.converted_artifact_id) {
400
+ return draftConversionResponseSchema.parse({
401
+ schema_version: 1,
402
+ status: 'replayed',
403
+ draft,
404
+ reservation: input.reservation,
405
+ });
406
+ }
407
+ if (draft.artifact_type !== input.reservation.artifact_type ||
408
+ draft.project_id !== input.reservation.project_id ||
409
+ draft.tenant_id !== input.reservation.tenant_id) {
410
+ throw new Error('Draft conversion rejected: reservation does not match draft artifact type, project, or tenant.');
411
+ }
412
+ draft.converted_artifact_id = input.reservation.artifact_id;
413
+ draft.converted_at = options.now ?? new Date().toISOString();
414
+ appendAuditEvent(state, {
415
+ event_type: 'reservation_replayed',
416
+ project_id: draft.project_id,
417
+ tenant_id: draft.tenant_id,
418
+ artifact_type: draft.artifact_type,
419
+ actor: input.converted_by,
420
+ idempotency_key: input.reservation.idempotency_key,
421
+ occurred_at: draft.converted_at,
422
+ result: 'accepted',
423
+ });
424
+ return draftConversionResponseSchema.parse({
425
+ schema_version: 1,
426
+ status: 'converted',
427
+ draft,
428
+ reservation: input.reservation,
429
+ });
430
+ }
431
+ export function buildReserveRequestFingerprint(request) {
432
+ return hashStableJson({
433
+ schema_version: request.schema_version,
434
+ project_id: request.project_id,
435
+ tenant_id: request.tenant_id ?? null,
436
+ artifact_type: request.artifact_type,
437
+ title_canonical: request.title_canonical ?? null,
438
+ origin_ref: request.origin_ref ?? null,
439
+ requested_by: request.requested_by,
440
+ client_request_id: request.client_request_id ?? null,
441
+ });
442
+ }
443
+ export function buildArtifactAllocatorLeaseIdempotencyKey(input) {
444
+ return `lease_${hashStableJson({
445
+ project_id: input.project_id,
446
+ tenant_id: input.tenant_id ?? null,
447
+ artifact_type: input.artifact_type,
448
+ holder: input.holder,
449
+ ttl_ms: input.ttl_ms,
450
+ })}`;
451
+ }
452
+ export function buildLeaseRequestFingerprint(request) {
453
+ return hashStableJson({
454
+ schema_version: request.schema_version,
455
+ project_id: request.project_id,
456
+ tenant_id: request.tenant_id ?? null,
457
+ artifact_type: request.artifact_type,
458
+ holder: request.holder,
459
+ ttl_ms: request.ttl_ms,
460
+ });
461
+ }
462
+ export function buildCanonicalWriteRequestFingerprint(request) {
463
+ return hashStableJson({
464
+ schema_version: request.schema_version,
465
+ artifact_id: request.artifact_id,
466
+ project_id: request.project_id,
467
+ tenant_id: request.tenant_id ?? null,
468
+ actor: request.actor,
469
+ lease_id: request.lease_id,
470
+ fencing_token: request.fencing_token,
471
+ expected_revision: request.expected_revision,
472
+ });
473
+ }
474
+ function buildCanonicalWriteAudit(request, occurredAt, eventType, result) {
475
+ return {
476
+ event_type: eventType,
477
+ project_id: request.project_id,
478
+ tenant_id: request.tenant_id,
479
+ artifact_type: artifactIdAllocatorTypeSchema.parse(request.artifact_id.split('-')[0]),
480
+ actor: request.actor,
481
+ idempotency_key: request.idempotency_key,
482
+ lease_id: request.lease_id,
483
+ fencing_token: request.fencing_token,
484
+ occurred_at: occurredAt,
485
+ result,
486
+ };
487
+ }
488
+ function appendAuditEvent(state, input) {
489
+ state.audit_log.push(artifactAllocatorAuditEventSchema.parse({
490
+ schema_version: 1,
491
+ event_id: `audit_${hashStableJson({ input, index: state.audit_log.length }).slice(0, 24)}`,
492
+ ...input,
493
+ }));
494
+ }
495
+ function hashStableJson(value) {
496
+ return createHash('sha256').update(stableStringify(value)).digest('hex');
497
+ }
498
+ function stableStringify(value) {
499
+ if (Array.isArray(value)) {
500
+ return `[${value.map((entry) => stableStringify(entry)).join(',')}]`;
501
+ }
502
+ if (value && typeof value === 'object') {
503
+ return `{${Object.entries(value)
504
+ .sort(([left], [right]) => left.localeCompare(right))
505
+ .map(([key, entryValue]) => `${JSON.stringify(key)}:${stableStringify(entryValue)}`)
506
+ .join(',')}}`;
507
+ }
508
+ return JSON.stringify(value);
509
+ }
510
+ //# sourceMappingURL=artifact-id-allocator.js.map
@@ -1,9 +1,33 @@
1
- import { type BacklogItem, type DiscoveryRecord, type FrontendGapRecord, type TechDebtRecord } from './types.js';
1
+ import { type BacklogItem, type DiscoveryRecord, type FrontendGapRecord, type RepoMapRecord, type ServiceRecord, type TechDebtRecord } from './types.js';
2
2
  import { type SddStateSnapshot } from './state.js';
3
3
  export interface SddCheckOptions {
4
4
  render?: boolean;
5
5
  strict?: boolean;
6
6
  }
7
+ export interface FrontendGapHealthSummary {
8
+ total: number;
9
+ open: number;
10
+ planned: number;
11
+ in_progress: number;
12
+ resolved: number;
13
+ superseded: number;
14
+ unresolved: number;
15
+ }
16
+ export type SharedLockDomainSeverity = 'active' | 'mixed' | 'historical';
17
+ export interface SharedLockDomainHealth {
18
+ lock: string;
19
+ severity: SharedLockDomainSeverity;
20
+ owners: string[];
21
+ active_owners: string[];
22
+ historical_owners: string[];
23
+ }
24
+ export interface LockDomainHealthSummary {
25
+ shared_total: number;
26
+ active_conflicts: number;
27
+ mixed_history: number;
28
+ historical: number;
29
+ shared: SharedLockDomainHealth[];
30
+ }
7
31
  export interface SddCheckReport {
8
32
  valid: boolean;
9
33
  errors: string[];
@@ -13,8 +37,11 @@ export interface SddCheckReport {
13
37
  backlog: number;
14
38
  techDebt: number;
15
39
  finalizeQueue: number;
40
+ finalizeQueuePending: number;
41
+ finalizeQueueDone: number;
16
42
  frontendEnabled: boolean;
17
43
  frontendGaps: number;
44
+ frontendGapsSummary?: FrontendGapHealthSummary;
18
45
  frontendRoutes: number;
19
46
  progress_global: {
20
47
  done: number;
@@ -30,6 +57,7 @@ export interface SddCheckReport {
30
57
  ready_for_parallel: number;
31
58
  blocked: number;
32
59
  lock_conflicts: number;
60
+ lock_domain_health?: LockDomainHealthSummary;
33
61
  documentation_sync: boolean;
34
62
  core_views_stale: boolean;
35
63
  missing_architecture_fields: string[];
@@ -47,10 +75,33 @@ export interface SddCheckReport {
47
75
  };
48
76
  };
49
77
  }
78
+ export interface ServiceCatalogMaturityRow {
79
+ id: string;
80
+ level: number;
81
+ unmet: string[];
82
+ }
83
+ export interface ServiceCatalogMaturityAudit {
84
+ serviceCount: number;
85
+ byLevel: Record<number, number>;
86
+ below5: ServiceCatalogMaturityRow[];
87
+ }
50
88
  export declare function checkUniqueIds<T extends {
51
89
  id: string;
52
90
  }>(items: T[], scope: string, errors: string[]): void;
53
91
  export declare function hasForbiddenTitleToken(title: string): string | null;
92
+ export declare function summarizeFrontendGapHealth(gaps: FrontendGapRecord[]): FrontendGapHealthSummary;
93
+ export declare function summarizeLockDomainHealth(items: BacklogItem[]): LockDomainHealthSummary;
94
+ export declare function hasRepoMapReference(repoPath: string, repoMapPaths: string[]): boolean;
95
+ export declare function hasIntegrationContract(contractRef: string, knownContracts: Set<string>): boolean;
96
+ export declare function auditServiceCatalogMaturity(services: ServiceRecord[], backlogItems: BacklogItem[], repoMapItems: RepoMapRecord[], integrationContracts: string[]): ServiceCatalogMaturityAudit;
97
+ export declare function validateAdrConsistency(adrsDir: string, backlogItems: BacklogItem[], errors: string[], warnings: string[], isStrict: boolean): Promise<void>;
98
+ export declare function validateInsightMinimums(insightTitle: string, insightBody: string, errors: string[]): void;
99
+ export declare function validateEpicMinimums(epicBody: string, epicTitle: string, errors: string[]): void;
100
+ export declare function validateTransitionLogConsistency(transitionLogEvents: Array<{
101
+ entity_id: string;
102
+ to?: string;
103
+ action?: string;
104
+ }>, backlogItems: BacklogItem[], errors: string[], warnings: string[], isStrict: boolean): void;
54
105
  export declare function validateDiscoveryRecords(records: DiscoveryRecord[], errors: string[]): void;
55
106
  export declare function validateBacklog(items: BacklogItem[], errors: string[], warnings: string[]): void;
56
107
  export declare function validateReferentialIntegrity(snapshot: SddStateSnapshot, errors: string[], warnings: string[], isStrict: boolean): void;