@devtrack-solution/codesdd 1.2.4-rc3 → 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.
- package/.sdd/skills/curated/devtrack-api/SKILL.md +91 -12
- package/.sdd/skills/curated/devtrack-api/agents/claude-code.yaml +2 -0
- package/.sdd/skills/curated/devtrack-api/agents/codex.yaml +2 -0
- package/.sdd/skills/curated/devtrack-api/agents/cursor.yaml +2 -0
- package/.sdd/skills/curated/devtrack-api/agents/gemini.yaml +2 -0
- package/.sdd/skills/curated/devtrack-api/agents/kimi.yaml +2 -0
- package/.sdd/skills/curated/devtrack-api/agents/openai.yaml +3 -3
- package/.sdd/skills/curated/devtrack-api/agents/opencode.yaml +2 -0
- package/.sdd/skills/curated/devtrack-api/references/application-presentation.md +59 -3
- package/.sdd/skills/curated/devtrack-api/references/consumer-sync-policy.md +15 -3
- package/.sdd/skills/curated/devtrack-api/references/contract-pack.yaml +1898 -2
- package/.sdd/skills/curated/devtrack-api/references/domain-modeling.md +3 -1
- package/.sdd/skills/curated/devtrack-api/references/field-validation-protocol.md +40 -0
- package/.sdd/skills/curated/devtrack-api/references/foundation-layout.md +20 -2
- package/.sdd/skills/curated/devtrack-api/references/generated-artifact-invalidation.md +97 -0
- package/.sdd/skills/curated/devtrack-api/references/implementation-checklist.md +30 -1
- package/.sdd/skills/curated/devtrack-api/references/portable-agent-contract.md +4 -3
- package/.sdd/skills/curated/devtrack-api/references/testing-validation.md +22 -1
- package/.sdd/skills/curated/devtrack-api/references/typeorm-infrastructure.md +9 -5
- package/README.md +122 -25
- package/dist/cli/program.js +180 -11
- package/dist/commands/config.js +27 -1
- package/dist/commands/sdd/execution.js +64 -2
- package/dist/commands/sdd.js +119 -4
- package/dist/core/cli/command-matrix.d.ts +18 -0
- package/dist/core/cli/command-matrix.js +148 -0
- package/dist/core/cli-command-quality.js +2 -0
- package/dist/core/config-schema.d.ts +14 -1
- package/dist/core/config-schema.js +32 -1
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.js +11 -0
- package/dist/core/global-config.d.ts +13 -0
- package/dist/core/init.d.ts +2 -2
- package/dist/core/init.js +13 -14
- package/dist/core/sdd/agent-binding.d.ts +9 -9
- package/dist/core/sdd/agent-runtime-contract.d.ts +4 -4
- package/dist/core/sdd/allocator-recovery.d.ts +14 -0
- package/dist/core/sdd/allocator-recovery.js +30 -0
- package/dist/core/sdd/allocator-security.d.ts +18 -0
- package/dist/core/sdd/allocator-security.js +36 -0
- package/dist/core/sdd/api-foundation-baseline.d.ts +111 -0
- package/dist/core/sdd/api-foundation-baseline.js +151 -0
- package/dist/core/sdd/api-foundation-parity.d.ts +114 -0
- package/dist/core/sdd/api-foundation-parity.js +131 -0
- package/dist/core/sdd/api-profile-catalog.d.ts +36 -0
- package/dist/core/sdd/api-profile-catalog.js +132 -0
- package/dist/core/sdd/api-profile-dry-run-projection.d.ts +93 -0
- package/dist/core/sdd/api-profile-dry-run-projection.js +370 -0
- package/dist/core/sdd/api-profile-recipes.d.ts +82 -0
- package/dist/core/sdd/api-profile-recipes.js +484 -0
- package/dist/core/sdd/artifact-id-allocator.d.ts +368 -0
- package/dist/core/sdd/artifact-id-allocator.js +510 -0
- package/dist/core/sdd/check.d.ts +50 -1
- package/dist/core/sdd/check.js +286 -9
- package/dist/core/sdd/deepagent-contracts.d.ts +4 -4
- package/dist/core/sdd/deepagents/reversa-subagents.d.ts +3 -3
- package/dist/core/sdd/default-bootstrap-files.d.ts +1 -1
- package/dist/core/sdd/default-bootstrap-files.js +0 -2
- package/dist/core/sdd/default-skills.js +7 -5
- package/dist/core/sdd/devtrack-api-appliance.d.ts +34 -0
- package/dist/core/sdd/devtrack-api-appliance.js +138 -34
- package/dist/core/sdd/devtrack-api-architecture.d.ts +16 -0
- package/dist/core/sdd/devtrack-api-architecture.js +86 -0
- package/dist/core/sdd/docs-sync.js +3 -3
- package/dist/core/sdd/enterprise-mutating-command-gate.d.ts +27 -0
- package/dist/core/sdd/enterprise-mutating-command-gate.js +104 -0
- package/dist/core/sdd/enterprise-provenance-gates.d.ts +20 -0
- package/dist/core/sdd/enterprise-provenance-gates.js +63 -0
- package/dist/core/sdd/enterprise-provisioning-policy.d.ts +26 -0
- package/dist/core/sdd/enterprise-provisioning-policy.js +104 -0
- package/dist/core/sdd/governance-schemas.d.ts +2 -2
- package/dist/core/sdd/governance-schemas.js +11 -2
- package/dist/core/sdd/json-schema.js +4 -0
- package/dist/core/sdd/legacy-operations.js +93 -4
- package/dist/core/sdd/package-security-gates.js +2 -0
- package/dist/core/sdd/package-structure-gate.d.ts +85 -3
- package/dist/core/sdd/package-structure-gate.js +386 -8
- package/dist/core/sdd/parallel-feat-automation.d.ts +6 -6
- package/dist/core/sdd/plugin-policy.js +6 -1
- package/dist/core/sdd/plugin-registry.d.ts +3 -3
- package/dist/core/sdd/quality-validation.d.ts +5 -5
- package/dist/core/sdd/release-readiness.d.ts +49 -0
- package/dist/core/sdd/release-readiness.js +303 -8
- package/dist/core/sdd/reversa-architecture-extractor.d.ts +13 -0
- package/dist/core/sdd/reversa-architecture-extractor.js +89 -0
- package/dist/core/sdd/reversa-artifact-writer.d.ts +18 -0
- package/dist/core/sdd/reversa-artifact-writer.js +40 -0
- package/dist/core/sdd/reversa-command-policy.d.ts +136 -0
- package/dist/core/sdd/reversa-command-policy.js +361 -0
- package/dist/core/sdd/reversa-data-extractor.d.ts +11 -0
- package/dist/core/sdd/reversa-data-extractor.js +73 -0
- package/dist/core/sdd/reversa-equivalence.d.ts +20 -0
- package/dist/core/sdd/reversa-equivalence.js +34 -0
- package/dist/core/sdd/reversa-evidence.d.ts +298 -0
- package/dist/core/sdd/reversa-evidence.js +118 -0
- package/dist/core/sdd/reversa-reconstruction.d.ts +29 -0
- package/dist/core/sdd/reversa-reconstruction.js +32 -0
- package/dist/core/sdd/reversa-rules-extractor.d.ts +12 -0
- package/dist/core/sdd/reversa-rules-extractor.js +86 -0
- package/dist/core/sdd/reversa-source-safety.d.ts +19 -0
- package/dist/core/sdd/reversa-source-safety.js +105 -0
- package/dist/core/sdd/reversa-surface-scout.d.ts +13 -0
- package/dist/core/sdd/reversa-surface-scout.js +85 -0
- package/dist/core/sdd/reversa-ux-mapper.d.ts +11 -0
- package/dist/core/sdd/reversa-ux-mapper.js +73 -0
- package/dist/core/sdd/sdk-agent-plugin-quality-gates.d.ts +1 -1
- package/dist/core/sdd/services/archive-quality-coherence.service.d.ts +17 -0
- package/dist/core/sdd/services/archive-quality-coherence.service.js +141 -0
- package/dist/core/sdd/services/decide.service.js +1 -1
- package/dist/core/sdd/services/finalize.service.d.ts +2 -0
- package/dist/core/sdd/services/finalize.service.js +48 -2
- package/dist/core/sdd/services/historical-quality-regression.service.d.ts +35 -0
- package/dist/core/sdd/services/historical-quality-regression.service.js +228 -0
- package/dist/core/sdd/services/ingest-deposito.service.js +1 -1
- package/dist/core/sdd/services/planning-execution-coherence.service.d.ts +45 -0
- package/dist/core/sdd/services/planning-execution-coherence.service.js +225 -0
- package/dist/core/sdd/state.js +15 -5
- package/dist/core/sdd/types.d.ts +3 -3
- package/dist/core/sdd/workspace-schemas.d.ts +45 -4
- package/dist/core/sdd/workspace-schemas.js +27 -6
- package/dist/core/shared/skill-generation.d.ts +2 -0
- package/dist/core/shared/skill-generation.js +19 -2
- package/dist/core/shared/tool-detection.d.ts +19 -0
- package/dist/core/shared/tool-detection.js +89 -0
- package/package.json +6 -5
- package/schemas/sdd/5-quality.schema.json +43 -0
- package/schemas/sdd/reversa-evidence-bundle.schema.json +466 -0
- package/schemas/sdd/workspace-catalog.schema.json +511 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { existsSync, promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
import { parseWorkspaceYamlDocument } from '../workspace-schemas.js';
|
|
5
|
+
const PLACEHOLDER_PATTERNS = [
|
|
6
|
+
/\(fill in/i,
|
|
7
|
+
/\(placeholder/i,
|
|
8
|
+
/\btodo\b/i,
|
|
9
|
+
/\btbd\b/i,
|
|
10
|
+
/\bpending\b/i,
|
|
11
|
+
/\bmust implement\b/i,
|
|
12
|
+
/\bto be executed\b/i,
|
|
13
|
+
/\bplanned\b/i,
|
|
14
|
+
/\bwill be\b/i,
|
|
15
|
+
/\bto do\b/i,
|
|
16
|
+
];
|
|
17
|
+
const DEFAULT_RECENT_WINDOW_SIZE = 25;
|
|
18
|
+
const DEFAULT_GRANDFATHER_MAX_FEAT = 451;
|
|
19
|
+
function featNumericId(featureId) {
|
|
20
|
+
const match = featureId.match(/^FEAT-(\d{4,})$/);
|
|
21
|
+
if (!match)
|
|
22
|
+
return null;
|
|
23
|
+
return Number.parseInt(match[1] || '', 10);
|
|
24
|
+
}
|
|
25
|
+
function hasPlaceholderSignal(text) {
|
|
26
|
+
return PLACEHOLDER_PATTERNS.some((pattern) => pattern.test(text));
|
|
27
|
+
}
|
|
28
|
+
function hasPlaceholderEvidence(document) {
|
|
29
|
+
const evidenceTexts = [
|
|
30
|
+
...document.evidence_log.flatMap((entry) => [entry.kind, entry.result, entry.artifact ?? '']),
|
|
31
|
+
...document.acceptance_matrix.flatMap((entry) => [entry.criterion, entry.evidence]),
|
|
32
|
+
];
|
|
33
|
+
return evidenceTexts.some((text) => text && hasPlaceholderSignal(text));
|
|
34
|
+
}
|
|
35
|
+
function sortFeaturesByRecency(featureIds) {
|
|
36
|
+
return [...featureIds].sort((left, right) => {
|
|
37
|
+
const leftNum = featNumericId(left);
|
|
38
|
+
const rightNum = featNumericId(right);
|
|
39
|
+
if (leftNum !== null && rightNum !== null && leftNum !== rightNum) {
|
|
40
|
+
return rightNum - leftNum;
|
|
41
|
+
}
|
|
42
|
+
if (leftNum !== null && rightNum === null)
|
|
43
|
+
return -1;
|
|
44
|
+
if (leftNum === null && rightNum !== null)
|
|
45
|
+
return 1;
|
|
46
|
+
return right.localeCompare(left);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async function loadBacklogEvidence(backlogPath) {
|
|
50
|
+
const map = new Map();
|
|
51
|
+
if (!existsSync(backlogPath))
|
|
52
|
+
return map;
|
|
53
|
+
const raw = await fs.readFile(backlogPath, 'utf-8').catch(() => '');
|
|
54
|
+
if (!raw.trim())
|
|
55
|
+
return map;
|
|
56
|
+
const parsed = parseYaml(raw);
|
|
57
|
+
for (const item of parsed.items ?? []) {
|
|
58
|
+
const id = typeof item.id === 'string' ? item.id : '';
|
|
59
|
+
if (!id.startsWith('FEAT-'))
|
|
60
|
+
continue;
|
|
61
|
+
map.set(id, {
|
|
62
|
+
id,
|
|
63
|
+
status: typeof item.status === 'string' ? item.status : undefined,
|
|
64
|
+
frontend_impact_status: typeof item.frontend_impact_status === 'string' ? item.frontend_impact_status : undefined,
|
|
65
|
+
done_at: typeof item.done_at === 'string' ? item.done_at : undefined,
|
|
66
|
+
archived_at: typeof item.archived_at === 'string' ? item.archived_at : undefined,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return map;
|
|
70
|
+
}
|
|
71
|
+
export class HistoricalQualityRegressionService {
|
|
72
|
+
async execute(projectRoot, options = {}) {
|
|
73
|
+
const mode = options.mode ?? 'recent-window';
|
|
74
|
+
const recentWindowSize = options.recentWindowSize ?? DEFAULT_RECENT_WINDOW_SIZE;
|
|
75
|
+
const grandfatherMaxFeat = options.grandfatherMaxFeat ?? DEFAULT_GRANDFATHER_MAX_FEAT;
|
|
76
|
+
const archivedDir = path.join(projectRoot, '.sdd', 'archived');
|
|
77
|
+
const backlogPath = path.join(projectRoot, '.sdd', 'state', 'backlog.yaml');
|
|
78
|
+
const adrsDir = path.join(projectRoot, '.sdd', 'core', 'adrs');
|
|
79
|
+
const backlogByFeature = await loadBacklogEvidence(backlogPath);
|
|
80
|
+
if (!existsSync(archivedDir)) {
|
|
81
|
+
return {
|
|
82
|
+
generated_at: new Date().toISOString(),
|
|
83
|
+
mode,
|
|
84
|
+
recent_window_size: mode === 'recent-window' ? recentWindowSize : null,
|
|
85
|
+
scanned: 0,
|
|
86
|
+
considered: 0,
|
|
87
|
+
analyzed: 0,
|
|
88
|
+
grandfathered: 0,
|
|
89
|
+
issue_count: 0,
|
|
90
|
+
grandfathering: {
|
|
91
|
+
enabled: true,
|
|
92
|
+
max_feat_id: grandfatherMaxFeat,
|
|
93
|
+
policy: `Skip blocking regression checks for archived FEAT ids <= FEAT-${String(grandfatherMaxFeat).padStart(4, '0')}.`,
|
|
94
|
+
},
|
|
95
|
+
issues: [],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const entries = await fs.readdir(archivedDir, { withFileTypes: true });
|
|
99
|
+
const scannedFeatures = entries
|
|
100
|
+
.filter((entry) => entry.isDirectory() && entry.name.startsWith('FEAT-'))
|
|
101
|
+
.map((entry) => entry.name);
|
|
102
|
+
const orderedFeatures = sortFeaturesByRecency(scannedFeatures);
|
|
103
|
+
const consideredFeatures = mode === 'recent-window' ? orderedFeatures.slice(0, Math.max(1, recentWindowSize)) : orderedFeatures;
|
|
104
|
+
let analyzed = 0;
|
|
105
|
+
let grandfathered = 0;
|
|
106
|
+
const issues = [];
|
|
107
|
+
for (const featureId of consideredFeatures) {
|
|
108
|
+
const numericId = featNumericId(featureId);
|
|
109
|
+
if (numericId !== null && numericId <= grandfatherMaxFeat) {
|
|
110
|
+
grandfathered += 1;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const backlog = backlogByFeature.get(featureId);
|
|
114
|
+
const qualityPath = path.join(archivedDir, featureId, '5-quality.yaml');
|
|
115
|
+
const adrPath = path.join(adrsDir, `ADR-${featureId}.md`);
|
|
116
|
+
if (!backlog) {
|
|
117
|
+
issues.push({
|
|
118
|
+
feature_id: featureId,
|
|
119
|
+
code: 'STATE_CORE_DIVERGENCE',
|
|
120
|
+
message: `${featureId} is archived but missing from .sdd/state/backlog.yaml.`,
|
|
121
|
+
backlog_path: backlogPath,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (backlog && backlog.status && !['DONE', 'ARCHIVED'].includes(backlog.status)) {
|
|
125
|
+
issues.push({
|
|
126
|
+
feature_id: featureId,
|
|
127
|
+
code: 'STATE_CORE_DIVERGENCE',
|
|
128
|
+
message: `${featureId} is archived on disk but backlog status is ${backlog.status}.`,
|
|
129
|
+
backlog_path: backlogPath,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (backlog && (backlog.frontend_impact_status ?? 'unknown') === 'unknown') {
|
|
133
|
+
issues.push({
|
|
134
|
+
feature_id: featureId,
|
|
135
|
+
code: 'FRONTEND_IMPACT_UNKNOWN',
|
|
136
|
+
message: `${featureId} has frontend_impact_status=unknown in backlog state.`,
|
|
137
|
+
backlog_path: backlogPath,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (backlog && !backlog.done_at) {
|
|
141
|
+
issues.push({
|
|
142
|
+
feature_id: featureId,
|
|
143
|
+
code: 'MISSING_DONE_AT',
|
|
144
|
+
message: `${featureId} is archived without done_at in backlog state.`,
|
|
145
|
+
backlog_path: backlogPath,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (backlog && !backlog.archived_at) {
|
|
149
|
+
issues.push({
|
|
150
|
+
feature_id: featureId,
|
|
151
|
+
code: 'MISSING_ARCHIVED_AT',
|
|
152
|
+
message: `${featureId} is archived without archived_at in backlog state.`,
|
|
153
|
+
backlog_path: backlogPath,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
if (!existsSync(adrPath)) {
|
|
157
|
+
issues.push({
|
|
158
|
+
feature_id: featureId,
|
|
159
|
+
code: 'MISSING_ADR',
|
|
160
|
+
message: `${featureId} is missing required ADR file at .sdd/core/adrs/ADR-${featureId}.md.`,
|
|
161
|
+
adr_path: adrPath,
|
|
162
|
+
});
|
|
163
|
+
issues.push({
|
|
164
|
+
feature_id: featureId,
|
|
165
|
+
code: 'STATE_CORE_DIVERGENCE',
|
|
166
|
+
message: `${featureId} has no ADR in .sdd/core/adrs while archived state exists.`,
|
|
167
|
+
adr_path: adrPath,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (!existsSync(qualityPath)) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const rawQuality = await fs.readFile(qualityPath, 'utf-8').catch(() => '');
|
|
174
|
+
if (!rawQuality.trim()) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
let quality;
|
|
178
|
+
try {
|
|
179
|
+
quality = parseWorkspaceYamlDocument('5-quality.yaml', rawQuality);
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
analyzed += 1;
|
|
185
|
+
if (quality.acceptance_matrix.some((entry) => entry.status === 'not_met')) {
|
|
186
|
+
issues.push({
|
|
187
|
+
feature_id: featureId,
|
|
188
|
+
code: 'ACCEPTANCE_NOT_MET',
|
|
189
|
+
message: `${featureId} contains acceptance_matrix.status=not_met in archived quality evidence.`,
|
|
190
|
+
quality_path: qualityPath,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (quality.requirement_validation_evidence_risk_matrix.some((entry) => entry.risk_status === 'open')) {
|
|
194
|
+
issues.push({
|
|
195
|
+
feature_id: featureId,
|
|
196
|
+
code: 'OPEN_RISK',
|
|
197
|
+
message: `${featureId} contains requirement risk_status=open in archived quality evidence.`,
|
|
198
|
+
quality_path: qualityPath,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (hasPlaceholderEvidence(quality)) {
|
|
202
|
+
issues.push({
|
|
203
|
+
feature_id: featureId,
|
|
204
|
+
code: 'PLACEHOLDER_EVIDENCE',
|
|
205
|
+
message: `${featureId} still includes placeholder or future-tense evidence markers.`,
|
|
206
|
+
quality_path: qualityPath,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
generated_at: new Date().toISOString(),
|
|
212
|
+
mode,
|
|
213
|
+
recent_window_size: mode === 'recent-window' ? recentWindowSize : null,
|
|
214
|
+
scanned: orderedFeatures.length,
|
|
215
|
+
considered: consideredFeatures.length,
|
|
216
|
+
analyzed,
|
|
217
|
+
grandfathered,
|
|
218
|
+
issue_count: issues.length,
|
|
219
|
+
grandfathering: {
|
|
220
|
+
enabled: true,
|
|
221
|
+
max_feat_id: grandfatherMaxFeat,
|
|
222
|
+
policy: `Skip blocking regression checks for archived FEAT ids <= FEAT-${String(grandfatherMaxFeat).padStart(4, '0')}.`,
|
|
223
|
+
},
|
|
224
|
+
issues,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=historical-quality-regression.service.js.map
|
|
@@ -224,7 +224,7 @@ export class IngestDepositoService {
|
|
|
224
224
|
'frontend-extractor-sdd',
|
|
225
225
|
'planning-normalizer-sdd',
|
|
226
226
|
],
|
|
227
|
-
recommended_prompt: relProjectPath(paths, path.join(paths.promptsDir, '01-ingestao-deposito.md')),
|
|
227
|
+
recommended_prompt: relProjectPath(paths, path.join(paths.promptsDir, config.layout === 'en-US' ? '01-source-intake.md' : '01-ingestao-deposito.md')),
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
230
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type WorkspaceChangelogDocument, type WorkspacePlanDocument, type WorkspaceQualityDocument, type WorkspaceSpecDocument, type WorkspaceTasksDocument } from '../workspace-schemas.js';
|
|
2
|
+
export type PlanningExecutionCoherenceIssueCode = 'MISSING_FILE_EVIDENCE' | 'MISSING_COMMAND_EVIDENCE' | 'ACCEPTANCE_NOT_MET' | 'RISK_STATUS_OPEN' | 'ADR_MISSING';
|
|
3
|
+
export interface PlanningExecutionCoherenceIssue {
|
|
4
|
+
code: PlanningExecutionCoherenceIssueCode;
|
|
5
|
+
severity: 'error' | 'warning';
|
|
6
|
+
message: string;
|
|
7
|
+
evidence: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface PlanningExecutionCoherenceReport {
|
|
10
|
+
schema_version: 1;
|
|
11
|
+
feature_id: string;
|
|
12
|
+
generated_at: string;
|
|
13
|
+
workspace_path: string;
|
|
14
|
+
adr_path: string;
|
|
15
|
+
healthy: boolean;
|
|
16
|
+
planned: {
|
|
17
|
+
files: string[];
|
|
18
|
+
commands: string[];
|
|
19
|
+
};
|
|
20
|
+
execution: {
|
|
21
|
+
files: string[];
|
|
22
|
+
commands: string[];
|
|
23
|
+
};
|
|
24
|
+
issues: PlanningExecutionCoherenceIssue[];
|
|
25
|
+
}
|
|
26
|
+
export interface EvaluatePlanningExecutionCoherenceInput {
|
|
27
|
+
featureId: string;
|
|
28
|
+
workspacePath: string;
|
|
29
|
+
adrPath: string;
|
|
30
|
+
adrExists: boolean;
|
|
31
|
+
spec: WorkspaceSpecDocument;
|
|
32
|
+
plan: WorkspacePlanDocument;
|
|
33
|
+
tasks: WorkspaceTasksDocument;
|
|
34
|
+
changelog: WorkspaceChangelogDocument;
|
|
35
|
+
quality: WorkspaceQualityDocument;
|
|
36
|
+
changedFiles: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface PlanningExecutionCoherenceOptions {
|
|
39
|
+
changedFiles?: string[];
|
|
40
|
+
}
|
|
41
|
+
export declare function evaluatePlanningExecutionCoherence(input: EvaluatePlanningExecutionCoherenceInput): PlanningExecutionCoherenceReport;
|
|
42
|
+
export declare class PlanningExecutionCoherenceService {
|
|
43
|
+
execute(projectRoot: string, featureId: string, options?: PlanningExecutionCoherenceOptions): Promise<PlanningExecutionCoherenceReport>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=planning-execution-coherence.service.d.ts.map
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { existsSync, promises as fs } from 'node:fs';
|
|
3
|
+
import { execFile } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { activeDocNamesForLayout, ensureMemoryInitialized, relProjectPath } from '../legacy-operations.js';
|
|
6
|
+
import { loadProjectSddConfig, resolveSddPaths } from '../state.js';
|
|
7
|
+
import { parseWorkspaceYamlDocument, } from '../workspace-schemas.js';
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
function uniqueSorted(values) {
|
|
10
|
+
return Array.from(new Set(values.filter(Boolean))).sort((a, b) => a.localeCompare(b));
|
|
11
|
+
}
|
|
12
|
+
function normalizeCommand(value) {
|
|
13
|
+
return value.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
function normalizePathForCoherence(value) {
|
|
16
|
+
const normalized = value.replace(/\\/g, '/').trim();
|
|
17
|
+
return normalized.replace(/\.sdd\/(planned|active|archived)\/(FEAT-\d{4})\//, '.sdd/*/$2/');
|
|
18
|
+
}
|
|
19
|
+
function pathCovered(plannedPath, evidencePaths) {
|
|
20
|
+
const planned = normalizePathForCoherence(plannedPath);
|
|
21
|
+
return evidencePaths.some((candidate) => {
|
|
22
|
+
const normalizedCandidate = normalizePathForCoherence(candidate);
|
|
23
|
+
return (normalizedCandidate === planned ||
|
|
24
|
+
normalizedCandidate.endsWith(`/${planned}`) ||
|
|
25
|
+
planned.endsWith(`/${normalizedCandidate}`));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function collectPlannedFiles(plan, tasks, quality) {
|
|
29
|
+
const includePath = (value) => {
|
|
30
|
+
const normalized = value.replace(/\\/g, '/');
|
|
31
|
+
if (normalized.startsWith('.sdd/state/'))
|
|
32
|
+
return false;
|
|
33
|
+
if (normalized.startsWith('.sdd/archived/'))
|
|
34
|
+
return false;
|
|
35
|
+
return true;
|
|
36
|
+
};
|
|
37
|
+
return uniqueSorted([
|
|
38
|
+
...plan.execution_plan.command_sequence.flatMap((step) => step.expected_state_writes.filter(includePath)),
|
|
39
|
+
...tasks.tasks
|
|
40
|
+
.filter((task) => task.phase !== 'finalization')
|
|
41
|
+
.flatMap((task) => task.files_touched.filter(includePath)),
|
|
42
|
+
...quality.traceability.requirements.flatMap((req) => req.code_refs.map((ref) => ref.path)),
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
function collectPlannedCommands(plan, tasks, quality) {
|
|
46
|
+
return uniqueSorted([
|
|
47
|
+
...plan.governance.validation_gates.map((gate) => gate.command),
|
|
48
|
+
...tasks.tasks.flatMap((task) => task.test_scripts.map((script) => script.command)),
|
|
49
|
+
...quality.validation_strategies.map((strategy) => strategy.command),
|
|
50
|
+
]).map(normalizeCommand);
|
|
51
|
+
}
|
|
52
|
+
function collectExecutionFiles(quality, changelog, changedFiles) {
|
|
53
|
+
const changelogRefs = changelog.entries.flatMap((entry) => entry.refs);
|
|
54
|
+
return uniqueSorted([
|
|
55
|
+
...changedFiles,
|
|
56
|
+
...quality.evidence_log.map((entry) => entry.artifact ?? '').filter(Boolean),
|
|
57
|
+
...quality.traceability.requirements.flatMap((req) => req.evidence_refs),
|
|
58
|
+
...changelogRefs,
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
function collectExecutionCommands(quality) {
|
|
62
|
+
return uniqueSorted(quality.evidence_log
|
|
63
|
+
.map((entry) => entry.provenance?.command ?? '')
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.map(normalizeCommand));
|
|
66
|
+
}
|
|
67
|
+
function expectsAdr(spec, tasks) {
|
|
68
|
+
const corpus = [spec.objective, spec.expected_outcome, ...tasks.tasks.map((task) => `${task.title} ${task.description}`)]
|
|
69
|
+
.join(' ')
|
|
70
|
+
.toLowerCase();
|
|
71
|
+
return corpus.includes('adr');
|
|
72
|
+
}
|
|
73
|
+
export function evaluatePlanningExecutionCoherence(input) {
|
|
74
|
+
const plannedFiles = collectPlannedFiles(input.plan, input.tasks, input.quality);
|
|
75
|
+
const plannedCommands = collectPlannedCommands(input.plan, input.tasks, input.quality);
|
|
76
|
+
const executionFiles = collectExecutionFiles(input.quality, input.changelog, input.changedFiles);
|
|
77
|
+
const executionCommands = collectExecutionCommands(input.quality);
|
|
78
|
+
const issues = [];
|
|
79
|
+
const missingFiles = plannedFiles.filter((plannedFile) => !pathCovered(plannedFile, executionFiles));
|
|
80
|
+
if (missingFiles.length > 0) {
|
|
81
|
+
issues.push({
|
|
82
|
+
code: 'MISSING_FILE_EVIDENCE',
|
|
83
|
+
severity: 'error',
|
|
84
|
+
message: 'Planned files are not reflected in diff/evidence artifacts.',
|
|
85
|
+
evidence: {
|
|
86
|
+
missing_files: missingFiles,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const missingCommands = plannedCommands.filter((command) => !executionCommands.includes(command));
|
|
91
|
+
if (missingCommands.length > 0) {
|
|
92
|
+
issues.push({
|
|
93
|
+
code: 'MISSING_COMMAND_EVIDENCE',
|
|
94
|
+
severity: 'warning',
|
|
95
|
+
message: 'Planned validation commands are missing from evidence provenance.',
|
|
96
|
+
evidence: {
|
|
97
|
+
missing_commands: missingCommands,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const notMetAcceptance = input.quality.acceptance_matrix.filter((entry) => entry.status === 'not_met');
|
|
102
|
+
if (notMetAcceptance.length > 0) {
|
|
103
|
+
issues.push({
|
|
104
|
+
code: 'ACCEPTANCE_NOT_MET',
|
|
105
|
+
severity: 'error',
|
|
106
|
+
message: 'Quality acceptance matrix still has not_met criteria.',
|
|
107
|
+
evidence: {
|
|
108
|
+
criteria: notMetAcceptance.map((entry) => entry.criterion),
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const openRisks = input.quality.requirement_validation_evidence_risk_matrix.filter((entry) => entry.risk_status === 'open');
|
|
113
|
+
if (openRisks.length > 0) {
|
|
114
|
+
issues.push({
|
|
115
|
+
code: 'RISK_STATUS_OPEN',
|
|
116
|
+
severity: 'warning',
|
|
117
|
+
message: 'Requirement risk matrix still has open risk entries.',
|
|
118
|
+
evidence: {
|
|
119
|
+
requirements: openRisks.map((entry) => entry.requirement_ref),
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (expectsAdr(input.spec, input.tasks) && !input.adrExists) {
|
|
124
|
+
issues.push({
|
|
125
|
+
code: 'ADR_MISSING',
|
|
126
|
+
severity: 'error',
|
|
127
|
+
message: 'Planning requires ADR coherence but ADR file is missing.',
|
|
128
|
+
evidence: {
|
|
129
|
+
expected_adr: input.adrPath,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const healthy = !issues.some((issue) => issue.severity === 'error');
|
|
134
|
+
return {
|
|
135
|
+
schema_version: 1,
|
|
136
|
+
feature_id: input.featureId,
|
|
137
|
+
generated_at: new Date().toISOString(),
|
|
138
|
+
workspace_path: input.workspacePath,
|
|
139
|
+
adr_path: input.adrPath,
|
|
140
|
+
healthy,
|
|
141
|
+
planned: {
|
|
142
|
+
files: plannedFiles,
|
|
143
|
+
commands: plannedCommands,
|
|
144
|
+
},
|
|
145
|
+
execution: {
|
|
146
|
+
files: executionFiles,
|
|
147
|
+
commands: executionCommands,
|
|
148
|
+
},
|
|
149
|
+
issues,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
async function listChangedFiles(projectRoot) {
|
|
153
|
+
try {
|
|
154
|
+
const { stdout } = await execFileAsync('git', ['status', '--porcelain'], {
|
|
155
|
+
cwd: projectRoot,
|
|
156
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
157
|
+
});
|
|
158
|
+
return uniqueSorted(stdout
|
|
159
|
+
.split('\n')
|
|
160
|
+
.map((line) => line.trim())
|
|
161
|
+
.filter(Boolean)
|
|
162
|
+
.map((line) => line.slice(3).trim())
|
|
163
|
+
.map((line) => (line.includes('->') ? line.split('->').pop() ?? line : line))
|
|
164
|
+
.map((line) => line.trim())
|
|
165
|
+
.filter(Boolean));
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async function resolveWorkspacePath(projectRoot, featureId) {
|
|
172
|
+
const config = await loadProjectSddConfig(projectRoot);
|
|
173
|
+
const paths = resolveSddPaths(projectRoot, config);
|
|
174
|
+
await ensureMemoryInitialized(paths);
|
|
175
|
+
const roots = [paths.activeDir, paths.plannedDir, paths.archivedDir];
|
|
176
|
+
for (const root of roots) {
|
|
177
|
+
const workspacePath = path.join(root, featureId);
|
|
178
|
+
if (existsSync(workspacePath)) {
|
|
179
|
+
return {
|
|
180
|
+
workspacePath,
|
|
181
|
+
adrPath: path.join(paths.coreDir, 'adrs', `ADR-${featureId}.md`),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
throw new Error(`Workspace not found for ${featureId}.`);
|
|
186
|
+
}
|
|
187
|
+
export class PlanningExecutionCoherenceService {
|
|
188
|
+
async execute(projectRoot, featureId, options = {}) {
|
|
189
|
+
if (!/^FEAT-\d{4}$/.test(featureId)) {
|
|
190
|
+
throw new Error('Invalid feature id. Use FEAT-####.');
|
|
191
|
+
}
|
|
192
|
+
const config = await loadProjectSddConfig(projectRoot);
|
|
193
|
+
const paths = resolveSddPaths(projectRoot, config);
|
|
194
|
+
const names = activeDocNamesForLayout(config);
|
|
195
|
+
const { workspacePath, adrPath } = await resolveWorkspacePath(projectRoot, featureId);
|
|
196
|
+
const readDoc = async (name) => {
|
|
197
|
+
const filePath = path.join(workspacePath, name);
|
|
198
|
+
if (!existsSync(filePath)) {
|
|
199
|
+
throw new Error(`${name} not found for ${featureId}.`);
|
|
200
|
+
}
|
|
201
|
+
return fs.readFile(filePath, 'utf-8');
|
|
202
|
+
};
|
|
203
|
+
const [specRaw, planRaw, tasksRaw, changelogRaw, qualityRaw] = await Promise.all([
|
|
204
|
+
readDoc(names.spec),
|
|
205
|
+
readDoc(names.plan),
|
|
206
|
+
readDoc(names.tasks),
|
|
207
|
+
readDoc(names.changelog),
|
|
208
|
+
readDoc(names.quality),
|
|
209
|
+
]);
|
|
210
|
+
const report = evaluatePlanningExecutionCoherence({
|
|
211
|
+
featureId,
|
|
212
|
+
workspacePath: relProjectPath(paths, workspacePath),
|
|
213
|
+
adrPath: relProjectPath(paths, adrPath),
|
|
214
|
+
adrExists: existsSync(adrPath),
|
|
215
|
+
spec: parseWorkspaceYamlDocument('1-spec.yaml', specRaw),
|
|
216
|
+
plan: parseWorkspaceYamlDocument('2-plan.yaml', planRaw),
|
|
217
|
+
tasks: parseWorkspaceYamlDocument('3-tasks.yaml', tasksRaw),
|
|
218
|
+
changelog: parseWorkspaceYamlDocument('4-changelog.yaml', changelogRaw),
|
|
219
|
+
quality: parseWorkspaceYamlDocument('5-quality.yaml', qualityRaw),
|
|
220
|
+
changedFiles: options.changedFiles ?? (await listChangedFiles(projectRoot)),
|
|
221
|
+
});
|
|
222
|
+
return report;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=planning-execution-coherence.service.js.map
|
package/dist/core/sdd/state.js
CHANGED
|
@@ -305,9 +305,9 @@ export function defaultFoldersForLayout(layout) {
|
|
|
305
305
|
const DEFAULT_SDD_CONFIG = {
|
|
306
306
|
enabled: true,
|
|
307
307
|
memoryDir: '.sdd',
|
|
308
|
-
language: '
|
|
309
|
-
layout: '
|
|
310
|
-
folders: defaultFoldersForLayout('
|
|
308
|
+
language: 'en-US',
|
|
309
|
+
layout: 'en-US',
|
|
310
|
+
folders: defaultFoldersForLayout('en-US'),
|
|
311
311
|
frontend: { enabled: false },
|
|
312
312
|
views: { autoRender: true },
|
|
313
313
|
};
|
|
@@ -358,8 +358,18 @@ export function mergeRuntimeConfig(raw) {
|
|
|
358
358
|
}
|
|
359
359
|
const frontend = isRecord(raw.frontend) ? raw.frontend : {};
|
|
360
360
|
const views = isRecord(raw.views) ? raw.views : {};
|
|
361
|
-
const language = raw.language === '
|
|
362
|
-
|
|
361
|
+
const language = raw.language === 'pt-BR'
|
|
362
|
+
? 'pt-BR'
|
|
363
|
+
: raw.language === 'en-US'
|
|
364
|
+
? 'en-US'
|
|
365
|
+
: DEFAULT_SDD_CONFIG.language;
|
|
366
|
+
const layout = raw.layout === 'pt-BR'
|
|
367
|
+
? 'pt-BR'
|
|
368
|
+
: raw.layout === 'en-US'
|
|
369
|
+
? 'en-US'
|
|
370
|
+
: raw.layout === 'legacy'
|
|
371
|
+
? 'legacy'
|
|
372
|
+
: DEFAULT_SDD_CONFIG.layout;
|
|
363
373
|
const folderDefaults = defaultFoldersForLayout(layout);
|
|
364
374
|
const rawFolders = isRecord(raw.folders) ? raw.folders : {};
|
|
365
375
|
// compatibilidade retroativa para nome legado "pendencias"
|
package/dist/core/sdd/types.d.ts
CHANGED
|
@@ -92,8 +92,8 @@ export declare const SourceClassificationSchema: z.ZodEnum<{
|
|
|
92
92
|
other: "other";
|
|
93
93
|
}>;
|
|
94
94
|
export declare const SourceVerificationStatusSchema: z.ZodEnum<{
|
|
95
|
-
verified: "verified";
|
|
96
95
|
stale: "stale";
|
|
96
|
+
verified: "verified";
|
|
97
97
|
unverified: "unverified";
|
|
98
98
|
needs_review: "needs_review";
|
|
99
99
|
}>;
|
|
@@ -616,8 +616,8 @@ export declare const SourceDocumentRecordSchema: z.ZodObject<{
|
|
|
616
616
|
jurisdiction_tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
617
617
|
last_verified_at: z.ZodOptional<z.ZodString>;
|
|
618
618
|
verification_status: z.ZodDefault<z.ZodEnum<{
|
|
619
|
-
verified: "verified";
|
|
620
619
|
stale: "stale";
|
|
620
|
+
verified: "verified";
|
|
621
621
|
unverified: "unverified";
|
|
622
622
|
needs_review: "needs_review";
|
|
623
623
|
}>>;
|
|
@@ -1235,8 +1235,8 @@ export declare const SourceIndexStateSchema: z.ZodObject<{
|
|
|
1235
1235
|
jurisdiction_tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1236
1236
|
last_verified_at: z.ZodOptional<z.ZodString>;
|
|
1237
1237
|
verification_status: z.ZodDefault<z.ZodEnum<{
|
|
1238
|
-
verified: "verified";
|
|
1239
1238
|
stale: "stale";
|
|
1239
|
+
verified: "verified";
|
|
1240
1240
|
unverified: "unverified";
|
|
1241
1241
|
needs_review: "needs_review";
|
|
1242
1242
|
}>>;
|
|
@@ -449,8 +449,8 @@ export declare const workspaceQualityLedgerSchema: z.ZodObject<{
|
|
|
449
449
|
export declare const workspaceTokenTelemetrySchema: z.ZodObject<{
|
|
450
450
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
451
451
|
standard: "standard";
|
|
452
|
-
compact: "compact";
|
|
453
452
|
full: "full";
|
|
453
|
+
compact: "compact";
|
|
454
454
|
}>>;
|
|
455
455
|
budget_chars: z.ZodOptional<z.ZodNumber>;
|
|
456
456
|
actual_chars: z.ZodOptional<z.ZodNumber>;
|
|
@@ -470,8 +470,8 @@ export declare const workspaceTokenBudgetGatesSchema: z.ZodObject<{
|
|
|
470
470
|
telemetry: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
471
471
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
472
472
|
standard: "standard";
|
|
473
|
-
compact: "compact";
|
|
474
473
|
full: "full";
|
|
474
|
+
compact: "compact";
|
|
475
475
|
}>>;
|
|
476
476
|
budget_chars: z.ZodOptional<z.ZodNumber>;
|
|
477
477
|
actual_chars: z.ZodOptional<z.ZodNumber>;
|
|
@@ -553,6 +553,29 @@ export declare const workspaceRuntimeQualityGatesSchema: z.ZodObject<{
|
|
|
553
553
|
notes: z.ZodOptional<z.ZodString>;
|
|
554
554
|
}, z.core.$strip>>>;
|
|
555
555
|
}, z.core.$strip>;
|
|
556
|
+
export declare const workspaceCriticalEvidenceProvenanceSchema: z.ZodObject<{
|
|
557
|
+
command: z.ZodString;
|
|
558
|
+
exit_code: z.ZodNumber;
|
|
559
|
+
timestamp_iso: z.ZodString;
|
|
560
|
+
commit_sha: z.ZodString;
|
|
561
|
+
artifact_path: z.ZodString;
|
|
562
|
+
artifact_hash: z.ZodString;
|
|
563
|
+
}, z.core.$strip>;
|
|
564
|
+
export declare const workspaceEvidenceLogEntrySchema: z.ZodObject<{
|
|
565
|
+
timestamp: z.ZodString;
|
|
566
|
+
kind: z.ZodString;
|
|
567
|
+
result: z.ZodString;
|
|
568
|
+
artifact: z.ZodOptional<z.ZodString>;
|
|
569
|
+
critical: z.ZodOptional<z.ZodBoolean>;
|
|
570
|
+
provenance: z.ZodOptional<z.ZodObject<{
|
|
571
|
+
command: z.ZodString;
|
|
572
|
+
exit_code: z.ZodNumber;
|
|
573
|
+
timestamp_iso: z.ZodString;
|
|
574
|
+
commit_sha: z.ZodString;
|
|
575
|
+
artifact_path: z.ZodString;
|
|
576
|
+
artifact_hash: z.ZodString;
|
|
577
|
+
}, z.core.$strip>>;
|
|
578
|
+
}, z.core.$strip>;
|
|
556
579
|
export declare const workspaceQualitySchema: z.ZodObject<{
|
|
557
580
|
schema_version: z.ZodLiteral<1>;
|
|
558
581
|
feature_id: z.ZodString;
|
|
@@ -571,6 +594,15 @@ export declare const workspaceQualitySchema: z.ZodObject<{
|
|
|
571
594
|
kind: z.ZodString;
|
|
572
595
|
result: z.ZodString;
|
|
573
596
|
artifact: z.ZodOptional<z.ZodString>;
|
|
597
|
+
critical: z.ZodOptional<z.ZodBoolean>;
|
|
598
|
+
provenance: z.ZodOptional<z.ZodObject<{
|
|
599
|
+
command: z.ZodString;
|
|
600
|
+
exit_code: z.ZodNumber;
|
|
601
|
+
timestamp_iso: z.ZodString;
|
|
602
|
+
commit_sha: z.ZodString;
|
|
603
|
+
artifact_path: z.ZodString;
|
|
604
|
+
artifact_hash: z.ZodString;
|
|
605
|
+
}, z.core.$strip>>;
|
|
574
606
|
}, z.core.$strip>>;
|
|
575
607
|
skill_evidence: z.ZodDefault<z.ZodObject<{
|
|
576
608
|
required_skill_ids: z.ZodArray<z.ZodString>;
|
|
@@ -702,8 +734,8 @@ export declare const workspaceQualitySchema: z.ZodObject<{
|
|
|
702
734
|
telemetry: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
703
735
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
704
736
|
standard: "standard";
|
|
705
|
-
compact: "compact";
|
|
706
737
|
full: "full";
|
|
738
|
+
compact: "compact";
|
|
707
739
|
}>>;
|
|
708
740
|
budget_chars: z.ZodOptional<z.ZodNumber>;
|
|
709
741
|
actual_chars: z.ZodOptional<z.ZodNumber>;
|
|
@@ -1024,6 +1056,15 @@ export declare const workspaceDocumentSchemas: {
|
|
|
1024
1056
|
kind: z.ZodString;
|
|
1025
1057
|
result: z.ZodString;
|
|
1026
1058
|
artifact: z.ZodOptional<z.ZodString>;
|
|
1059
|
+
critical: z.ZodOptional<z.ZodBoolean>;
|
|
1060
|
+
provenance: z.ZodOptional<z.ZodObject<{
|
|
1061
|
+
command: z.ZodString;
|
|
1062
|
+
exit_code: z.ZodNumber;
|
|
1063
|
+
timestamp_iso: z.ZodString;
|
|
1064
|
+
commit_sha: z.ZodString;
|
|
1065
|
+
artifact_path: z.ZodString;
|
|
1066
|
+
artifact_hash: z.ZodString;
|
|
1067
|
+
}, z.core.$strip>>;
|
|
1027
1068
|
}, z.core.$strip>>;
|
|
1028
1069
|
skill_evidence: z.ZodDefault<z.ZodObject<{
|
|
1029
1070
|
required_skill_ids: z.ZodArray<z.ZodString>;
|
|
@@ -1155,8 +1196,8 @@ export declare const workspaceDocumentSchemas: {
|
|
|
1155
1196
|
telemetry: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1156
1197
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
1157
1198
|
standard: "standard";
|
|
1158
|
-
compact: "compact";
|
|
1159
1199
|
full: "full";
|
|
1200
|
+
compact: "compact";
|
|
1160
1201
|
}>>;
|
|
1161
1202
|
budget_chars: z.ZodOptional<z.ZodNumber>;
|
|
1162
1203
|
actual_chars: z.ZodOptional<z.ZodNumber>;
|