@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,63 @@
|
|
|
1
|
+
export function evaluateEnterpriseAllocatorProvenance(state) {
|
|
2
|
+
const findings = [];
|
|
3
|
+
for (const reservation of state.reservations) {
|
|
4
|
+
const hasAudit = state.audit_log.some((event) => event.idempotency_key === reservation.idempotency_key &&
|
|
5
|
+
(event.event_type === 'reservation_created' || event.event_type === 'reservation_replayed'));
|
|
6
|
+
if (!hasAudit) {
|
|
7
|
+
findings.push({
|
|
8
|
+
severity: 'blocker',
|
|
9
|
+
code: 'reservation-missing-audit',
|
|
10
|
+
message: `Reservation ${reservation.artifact_id} has no allocator audit event.`,
|
|
11
|
+
ref: reservation.artifact_id,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
for (const lease of state.leases) {
|
|
16
|
+
const hasAudit = state.audit_log.some((event) => event.lease_id === lease.lease_id && event.event_type === 'lease_acquired');
|
|
17
|
+
if (!hasAudit) {
|
|
18
|
+
findings.push({
|
|
19
|
+
severity: 'blocker',
|
|
20
|
+
code: 'lease-missing-audit',
|
|
21
|
+
message: `Lease ${lease.lease_id} has no acquisition audit event.`,
|
|
22
|
+
ref: lease.lease_id,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
for (const write of state.canonical_writes) {
|
|
27
|
+
const hasAudit = state.audit_log.some((event) => event.idempotency_key === write.idempotency_key &&
|
|
28
|
+
(event.event_type === 'canonical_write_committed' || event.event_type === 'canonical_write_replayed'));
|
|
29
|
+
if (!hasAudit) {
|
|
30
|
+
findings.push({
|
|
31
|
+
severity: 'blocker',
|
|
32
|
+
code: 'canonical-write-missing-audit',
|
|
33
|
+
message: `Canonical write ${write.artifact_id}@${write.revision} has no write audit event.`,
|
|
34
|
+
ref: write.artifact_id,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const draft of state.drafts) {
|
|
39
|
+
if (draft.converted_artifact_id) {
|
|
40
|
+
const reservation = state.reservations.find((candidate) => candidate.artifact_id === draft.converted_artifact_id);
|
|
41
|
+
if (!reservation) {
|
|
42
|
+
findings.push({
|
|
43
|
+
severity: 'blocker',
|
|
44
|
+
code: 'draft-conversion-missing-reservation',
|
|
45
|
+
message: `Draft ${draft.draft_id} converted to ${draft.converted_artifact_id} without a reservation record.`,
|
|
46
|
+
ref: draft.draft_id,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
valid: findings.every((finding) => finding.severity !== 'blocker'),
|
|
53
|
+
findings,
|
|
54
|
+
counters: {
|
|
55
|
+
reservations: state.reservations.length,
|
|
56
|
+
leases: state.leases.length,
|
|
57
|
+
canonical_writes: state.canonical_writes.length,
|
|
58
|
+
drafts: state.drafts.length,
|
|
59
|
+
audit_events: state.audit_log.length,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=enterprise-provenance-gates.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { GlobalConfig } from '../global-config.js';
|
|
2
|
+
export type EnterpriseProvisioningStatus = 'disabled' | 'ready' | 'blocked';
|
|
3
|
+
export interface EnterpriseProvisioningPolicyReport {
|
|
4
|
+
schema_version: 1;
|
|
5
|
+
mode: 'local' | 'enterprise';
|
|
6
|
+
requested_mode?: 'local' | 'enterprise';
|
|
7
|
+
effective_mode?: 'local' | 'enterprise';
|
|
8
|
+
local_mode_exception_accepted?: boolean;
|
|
9
|
+
requested: boolean;
|
|
10
|
+
required_for_numbered_artifacts: boolean;
|
|
11
|
+
status: EnterpriseProvisioningStatus;
|
|
12
|
+
project_id?: string;
|
|
13
|
+
tenant_id?: string;
|
|
14
|
+
authority_url_env?: string;
|
|
15
|
+
redacted_authority_url?: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
next_action: string;
|
|
18
|
+
validation_errors: string[];
|
|
19
|
+
rules: {
|
|
20
|
+
canonical_numbered_artifacts: string;
|
|
21
|
+
offline_enterprise: string;
|
|
22
|
+
local_mode: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export declare function buildEnterpriseProvisioningPolicyReport(config: GlobalConfig, env?: NodeJS.ProcessEnv): EnterpriseProvisioningPolicyReport;
|
|
26
|
+
//# sourceMappingURL=enterprise-provisioning-policy.d.ts.map
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const DEFAULT_RULES = {
|
|
2
|
+
canonical_numbered_artifacts: 'Enterprise multi-agent mode must reserve DEB, INS, EPIC, FEAT, and other numbered artifacts through the online provisioning authority before canonical writes.',
|
|
3
|
+
offline_enterprise: 'When the authority is unavailable, Enterprise agents may create noncanonical drafts only; conversion to canonical artifacts requires a later online reservation.',
|
|
4
|
+
local_mode: 'Local/single-agent mode may keep using repository-local CodeSDD state and is not required to contact the provisioning authority.',
|
|
5
|
+
};
|
|
6
|
+
export function buildEnterpriseProvisioningPolicyReport(config, env = process.env) {
|
|
7
|
+
const provisioning = config.enterprise?.provisioning ?? {};
|
|
8
|
+
const mode = provisioning.mode ?? 'local';
|
|
9
|
+
const required = Boolean(provisioning.required_for_numbered_artifacts || mode === 'enterprise');
|
|
10
|
+
const requestedMode = mode;
|
|
11
|
+
const effectiveMode = required ? 'enterprise' : 'local';
|
|
12
|
+
const localModeExceptionAccepted = !required;
|
|
13
|
+
const authorityUrl = resolveAuthorityUrl(provisioning.authority_url, provisioning.authority_url_env, env);
|
|
14
|
+
const validationErrors = [];
|
|
15
|
+
if (required && !provisioning.project_id) {
|
|
16
|
+
validationErrors.push('enterprise.provisioning.project_id is required in Enterprise provisioning mode.');
|
|
17
|
+
}
|
|
18
|
+
if (required && !authorityUrl) {
|
|
19
|
+
validationErrors.push('enterprise.provisioning.authority_url or authority_url_env is required in Enterprise provisioning mode.');
|
|
20
|
+
}
|
|
21
|
+
if (authorityUrl && !isValidAuthorityUrl(authorityUrl)) {
|
|
22
|
+
validationErrors.push('enterprise.provisioning authority URL must be http(s) and include a hostname.');
|
|
23
|
+
}
|
|
24
|
+
if (mode === 'local' && !required) {
|
|
25
|
+
return {
|
|
26
|
+
schema_version: 1,
|
|
27
|
+
mode,
|
|
28
|
+
requested_mode: requestedMode,
|
|
29
|
+
effective_mode: effectiveMode,
|
|
30
|
+
local_mode_exception_accepted: localModeExceptionAccepted,
|
|
31
|
+
requested: false,
|
|
32
|
+
required_for_numbered_artifacts: false,
|
|
33
|
+
status: 'disabled',
|
|
34
|
+
project_id: provisioning.project_id,
|
|
35
|
+
tenant_id: provisioning.tenant_id,
|
|
36
|
+
authority_url_env: provisioning.authority_url_env,
|
|
37
|
+
redacted_authority_url: authorityUrl ? redactUrl(authorityUrl) : undefined,
|
|
38
|
+
reason: 'Enterprise provisioning requested mode is local and no Enterprise reservation request is active; local mode exception is accepted.',
|
|
39
|
+
next_action: 'none',
|
|
40
|
+
validation_errors: validationErrors,
|
|
41
|
+
rules: DEFAULT_RULES,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const status = validationErrors.length === 0 ? 'ready' : 'blocked';
|
|
45
|
+
return {
|
|
46
|
+
schema_version: 1,
|
|
47
|
+
mode,
|
|
48
|
+
requested_mode: requestedMode,
|
|
49
|
+
effective_mode: effectiveMode,
|
|
50
|
+
local_mode_exception_accepted: localModeExceptionAccepted,
|
|
51
|
+
requested: true,
|
|
52
|
+
required_for_numbered_artifacts: required,
|
|
53
|
+
status,
|
|
54
|
+
project_id: provisioning.project_id,
|
|
55
|
+
tenant_id: provisioning.tenant_id,
|
|
56
|
+
authority_url_env: provisioning.authority_url_env,
|
|
57
|
+
redacted_authority_url: authorityUrl ? redactUrl(authorityUrl) : undefined,
|
|
58
|
+
reason: status === 'ready'
|
|
59
|
+
? requestedMode === 'enterprise'
|
|
60
|
+
? 'Enterprise provisioning policy is configured for canonical numbered artifact reservations.'
|
|
61
|
+
: 'Enterprise provisioning is requested by required_for_numbered_artifacts despite local requested mode and is configured for canonical numbered artifact reservations.'
|
|
62
|
+
: 'Enterprise provisioning policy is requested but missing required project identity or authority configuration.',
|
|
63
|
+
next_action: status === 'ready'
|
|
64
|
+
? 'none'
|
|
65
|
+
: 'Configure enterprise.provisioning.project_id and enterprise.provisioning.authority_url or authority_url_env in ~/.codesdd/config.toml, or keep enterprise.provisioning.mode=local with required_for_numbered_artifacts=false when Enterprise reservations are not intended.',
|
|
66
|
+
validation_errors: validationErrors,
|
|
67
|
+
rules: DEFAULT_RULES,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function resolveAuthorityUrl(explicitUrl, authorityUrlEnv, env) {
|
|
71
|
+
if (explicitUrl)
|
|
72
|
+
return explicitUrl;
|
|
73
|
+
if (authorityUrlEnv)
|
|
74
|
+
return env[authorityUrlEnv];
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
function isValidAuthorityUrl(value) {
|
|
78
|
+
try {
|
|
79
|
+
const parsed = new URL(value);
|
|
80
|
+
return (parsed.protocol === 'https:' || parsed.protocol === 'http:') && parsed.hostname.length > 0;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function redactUrl(value) {
|
|
87
|
+
try {
|
|
88
|
+
const parsed = new URL(value);
|
|
89
|
+
if (parsed.username)
|
|
90
|
+
parsed.username = '[REDACTED]';
|
|
91
|
+
if (parsed.password)
|
|
92
|
+
parsed.password = '[REDACTED]';
|
|
93
|
+
for (const key of [...parsed.searchParams.keys()]) {
|
|
94
|
+
if (/key|secret|token|password|credential|private|auth/i.test(key)) {
|
|
95
|
+
parsed.searchParams.set(key, '[REDACTED]');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return parsed.toString();
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return '[REDACTED]';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=enterprise-provisioning-policy.js.map
|
|
@@ -91,10 +91,10 @@ export declare const debateFrontmatterSchema: z.ZodObject<{
|
|
|
91
91
|
mediator: z.ZodObject<{
|
|
92
92
|
choice: z.ZodString;
|
|
93
93
|
rationale: z.ZodString;
|
|
94
|
-
accepted_risks: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
94
|
+
accepted_risks: z.ZodDefault<z.ZodArray<z.ZodPreprocess<z.ZodObject<{
|
|
95
95
|
risk: z.ZodString;
|
|
96
96
|
mitigation: z.ZodString;
|
|
97
|
-
}, z.core.$strict
|
|
97
|
+
}, z.core.$strict>>>>;
|
|
98
98
|
reversal_conditions: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
99
99
|
}, z.core.$strict>;
|
|
100
100
|
output: z.ZodEnum<{
|
|
@@ -59,12 +59,21 @@ const debateScoringSchema = z
|
|
|
59
59
|
scores: z.record(z.string().regex(/^[A-Z]$/), z.number()),
|
|
60
60
|
})
|
|
61
61
|
.strict();
|
|
62
|
-
const
|
|
62
|
+
const DEFAULT_ACCEPTED_RISK_MITIGATION = 'Mitigation not provided by the source artifact; preserve this risk and require explicit mitigation before finalize.';
|
|
63
|
+
const debateAcceptedRiskSchema = z.preprocess((value) => {
|
|
64
|
+
if (typeof value !== 'string')
|
|
65
|
+
return value;
|
|
66
|
+
const risk = value.trim();
|
|
67
|
+
return {
|
|
68
|
+
risk,
|
|
69
|
+
mitigation: DEFAULT_ACCEPTED_RISK_MITIGATION,
|
|
70
|
+
};
|
|
71
|
+
}, z
|
|
63
72
|
.object({
|
|
64
73
|
risk: z.string().min(1),
|
|
65
74
|
mitigation: z.string().min(1),
|
|
66
75
|
})
|
|
67
|
-
.strict();
|
|
76
|
+
.strict());
|
|
68
77
|
const debateDecisionSchema = z
|
|
69
78
|
.object({
|
|
70
79
|
question: z.string().min(1),
|
|
@@ -13,6 +13,7 @@ import { buildAgentRuntimeJsonSchemas } from './agent-runtime-contract.js';
|
|
|
13
13
|
import { parallelFeatAutomationPlanSchema, parallelFeatAutomationRequestSchema, parallelFeatSchedulerRequestSchema, parallelFeatSchedulerResultSchema, } from './parallel-feat-automation.js';
|
|
14
14
|
import { backlogProjectionPlanSchema, backlogProviderContractSchema, } from './backlog-provider-contract.js';
|
|
15
15
|
import { qualityArchitectureSchema, qualityEvidenceBundleSchema, qualityRunSchema, qualityScenarioSchema, } from './quality-validation.js';
|
|
16
|
+
import { reversaEvidenceBundleSchema } from './reversa-evidence.js';
|
|
16
17
|
import { buildSdkAgentPluginQualityGateJsonSchemas } from './sdk-agent-plugin-quality-gates.js';
|
|
17
18
|
import { deepagentDecisionEvidenceSchema, deepagentEnvContractSchema, deepagentQualityEvidenceSchema, deepagentRunEvidenceSchema, deepagentRunPlanSchema, deepagentRunRequestSchema, deepagentSubagentEvidenceSchema, deepagentToolCallEvidenceSchema, } from './deepagent-contracts.js';
|
|
18
19
|
import { adrFrontmatterSchema, debateFrontmatterSchema, discardedFrontmatterSchema, epicFrontmatterSchema, insightFrontmatterSchema, } from './governance-schemas.js';
|
|
@@ -137,6 +138,9 @@ export function buildWorkspaceJsonSchemaCatalog() {
|
|
|
137
138
|
'quality-evidence-bundle.yaml': normalizeJsonSchemaDocument(toJSONSchema(qualityEvidenceBundleSchema), 'CodeSDD Quality Evidence Bundle', 'Machine-readable evidence bundle contract tying scenario, run, artifacts, checksums, findings, and exceptions together.'),
|
|
138
139
|
...buildSdkAgentPluginQualityGateJsonSchemas(),
|
|
139
140
|
},
|
|
141
|
+
reversa_contracts: {
|
|
142
|
+
'reversa-evidence-bundle.yaml': normalizeJsonSchemaDocument(toJSONSchema(reversaEvidenceBundleSchema), 'CodeSDD Reversa Evidence Bundle', 'Machine-readable evidence bundle contract for Reversa intake, extraction, generation, migration, reconstruction, and equivalence phases.'),
|
|
143
|
+
},
|
|
140
144
|
deepagent_execution: {
|
|
141
145
|
'deepagent-run-request.yaml': normalizeJsonSchemaDocument(toJSONSchema(deepagentRunRequestSchema), 'CodeSDD DeepAgent Run Request', 'Machine-readable request contract for governed DeepAgents execution with scoped tools, write policy, env contract, and expected evidence.'),
|
|
142
146
|
'deepagent-run-plan.yaml': normalizeJsonSchemaDocument(toJSONSchema(deepagentRunPlanSchema), 'CodeSDD DeepAgent Run Plan', 'Machine-readable tactical plan contract for DeepAgents runs with subagent routing, approvals, validation matrix, and residual risks.'),
|
|
@@ -136,16 +136,19 @@ Decide ____ instead of ____ to solve ____.
|
|
|
136
136
|
|
|
137
137
|
## 3) Options Considered (Minimum 2)
|
|
138
138
|
### Option A
|
|
139
|
+
- Status (selected/discarded):
|
|
139
140
|
- Proposal:
|
|
140
141
|
- Pros:
|
|
141
142
|
- Cons:
|
|
142
143
|
|
|
143
144
|
### Option B
|
|
145
|
+
- Status (selected/discarded):
|
|
144
146
|
- Proposal:
|
|
145
147
|
- Pros:
|
|
146
148
|
- Cons:
|
|
147
149
|
|
|
148
150
|
### Option C (Optional)
|
|
151
|
+
- Status (selected/discarded):
|
|
149
152
|
- Proposal:
|
|
150
153
|
- Pros:
|
|
151
154
|
- Cons:
|
|
@@ -194,7 +197,15 @@ Decide ____ instead of ____ to solve ____.
|
|
|
194
197
|
- APPROVED -> EPIC-####
|
|
195
198
|
- DISCARDED -> Record in discarded
|
|
196
199
|
|
|
197
|
-
##
|
|
200
|
+
## 10) Planning Completeness Gate (Required before promotion)
|
|
201
|
+
- Measurable acceptance:
|
|
202
|
+
- Non-scope:
|
|
203
|
+
- Definition of Done:
|
|
204
|
+
- Validation commands:
|
|
205
|
+
-
|
|
206
|
+
- Residual risk:
|
|
207
|
+
|
|
208
|
+
## 11) Metadata
|
|
198
209
|
- Source insight: ${insight.id}
|
|
199
210
|
- Insight title: ${insight.title}
|
|
200
211
|
- Created at: ${insight.created_at || now}
|
|
@@ -745,19 +756,92 @@ export async function findDebateFile(paths, debateId) {
|
|
|
745
756
|
return null;
|
|
746
757
|
return path.join(debateDir, found.name);
|
|
747
758
|
}
|
|
759
|
+
const GENERIC_DECISION_QUESTION_PATTERNS = [
|
|
760
|
+
/^decide\s+____\s+instead\s+of\s+____\s+to\s+solve\s+____\.?$/i,
|
|
761
|
+
/^decidir\s+____\s+em\s+vez\s+de\s+____\s+para\s+resolver\s+____\.?$/i,
|
|
762
|
+
/which option should we choose\??$/i,
|
|
763
|
+
/qual opcao devemos escolher\??$/i,
|
|
764
|
+
/decide between option [a-z] and option [a-z]\.?$/i,
|
|
765
|
+
/decidir entre opcao [a-z] e opcao [a-z]\.?$/i,
|
|
766
|
+
];
|
|
767
|
+
function isPlaceholderLike(value) {
|
|
768
|
+
const normalized = value.trim().toLowerCase();
|
|
769
|
+
if (!normalized)
|
|
770
|
+
return true;
|
|
771
|
+
const placeholderTokens = ['____', '(fill in', '(preencher', 'todo', 'tbd', 'n/a'];
|
|
772
|
+
return placeholderTokens.some((token) => normalized.includes(token));
|
|
773
|
+
}
|
|
774
|
+
function isGenericDecisionQuestion(question) {
|
|
775
|
+
const normalized = question.trim().replace(/\s+/g, ' ').toLowerCase();
|
|
776
|
+
if (normalized.length < 30)
|
|
777
|
+
return true;
|
|
778
|
+
return GENERIC_DECISION_QUESTION_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
779
|
+
}
|
|
780
|
+
function extractNamedListValue(content, labels) {
|
|
781
|
+
const escaped = labels.map((label) => label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
782
|
+
const match = content.match(new RegExp(`-\\s*(?:${escaped}):\\s*(.+)`, 'i'));
|
|
783
|
+
if (!match)
|
|
784
|
+
return '';
|
|
785
|
+
return match[1].trim();
|
|
786
|
+
}
|
|
787
|
+
function hasValidationCommand(content) {
|
|
788
|
+
const sectionMatch = content.match(/-\s*Validation commands:\s*([\s\S]*?)(?=\n-\s*Residual risk:|\n##\s+\d+\)|$)/i);
|
|
789
|
+
if (!sectionMatch)
|
|
790
|
+
return false;
|
|
791
|
+
const lines = sectionMatch[1]
|
|
792
|
+
.split(/\r?\n/)
|
|
793
|
+
.map((line) => line.trim())
|
|
794
|
+
.filter((line) => line.startsWith('-'))
|
|
795
|
+
.map((line) => line.replace(/^-\s*/, '').replace(/`/g, '').trim())
|
|
796
|
+
.filter((line) => line.length > 0);
|
|
797
|
+
if (lines.length === 0)
|
|
798
|
+
return false;
|
|
799
|
+
return lines.some((line) => line.includes('pnpm') || line.includes('npm') || line.includes('vitest'));
|
|
800
|
+
}
|
|
801
|
+
function collectPlanningGateMissing(content, selectedOption, optionIds) {
|
|
802
|
+
const missing = [];
|
|
803
|
+
const nonSelectedOptionIds = optionIds.filter((optionId) => optionId !== selectedOption);
|
|
804
|
+
if (nonSelectedOptionIds.length === 0) {
|
|
805
|
+
missing.push('Provide at least one discarded alternative option different from mediator choice');
|
|
806
|
+
}
|
|
807
|
+
const measurableAcceptance = extractNamedListValue(content, ['Measurable acceptance']);
|
|
808
|
+
if (isPlaceholderLike(measurableAcceptance) || !/\d|%|<=|>=|\bwithin\b|\bunder\b|\bmax\b/i.test(measurableAcceptance)) {
|
|
809
|
+
missing.push('Define measurable acceptance criteria in the planning completeness gate');
|
|
810
|
+
}
|
|
811
|
+
const nonScope = extractNamedListValue(content, ['Non-scope', 'Nao-escopo']);
|
|
812
|
+
if (isPlaceholderLike(nonScope)) {
|
|
813
|
+
missing.push('Document non-scope in the planning completeness gate');
|
|
814
|
+
}
|
|
815
|
+
const definitionOfDone = extractNamedListValue(content, ['Definition of Done', 'DoD']);
|
|
816
|
+
if (isPlaceholderLike(definitionOfDone)) {
|
|
817
|
+
missing.push('Document Definition of Done (DoD) in the planning completeness gate');
|
|
818
|
+
}
|
|
819
|
+
if (!hasValidationCommand(content)) {
|
|
820
|
+
missing.push('Document executable validation commands in the planning completeness gate');
|
|
821
|
+
}
|
|
822
|
+
const residualRisk = extractNamedListValue(content, ['Residual risk', 'Risco residual']);
|
|
823
|
+
if (isPlaceholderLike(residualRisk)) {
|
|
824
|
+
missing.push('Document residual risk in the planning completeness gate');
|
|
825
|
+
}
|
|
826
|
+
return missing;
|
|
827
|
+
}
|
|
748
828
|
export function validateDebateDocument(content) {
|
|
749
829
|
try {
|
|
750
830
|
const parsed = parseGovernanceFile('inline-content', content, debateFrontmatterSchema);
|
|
751
831
|
if (parsed.hasFrontmatter && parsed.frontmatter) {
|
|
752
832
|
const missing = [];
|
|
753
833
|
const question = parsed.frontmatter.decision.question.trim().toLowerCase();
|
|
754
|
-
if (
|
|
834
|
+
if (isGenericDecisionQuestion(question) || question.includes('____')) {
|
|
755
835
|
missing.push('Fill the decision question with real context');
|
|
756
836
|
}
|
|
837
|
+
if (parsed.frontmatter.decision.options.length < 2) {
|
|
838
|
+
missing.push('Provide at least two options in the decision matrix');
|
|
839
|
+
}
|
|
757
840
|
const rationale = parsed.frontmatter.decision.mediator.rationale.trim().toLowerCase();
|
|
758
841
|
if (!rationale || rationale.includes('____') || rationale.includes('(fill in') || rationale.includes('(preencher')) {
|
|
759
842
|
missing.push('Inform the mediator decision rationale');
|
|
760
843
|
}
|
|
844
|
+
missing.push(...collectPlanningGateMissing(parsed.body, parsed.frontmatter.decision.mediator.choice.trim().toUpperCase(), parsed.frontmatter.decision.options.map((option) => option.id.trim().toUpperCase())));
|
|
761
845
|
if (/\- Unit coverage:\s*$/m.test(parsed.body)) {
|
|
762
846
|
missing.push('Inform required unit coverage evidence in the quality contract');
|
|
763
847
|
}
|
|
@@ -770,7 +854,7 @@ export function validateDebateDocument(content) {
|
|
|
770
854
|
if (/\- Exceptions:\s*\n\s+- None, or formal exception/m.test(parsed.body)) {
|
|
771
855
|
missing.push('Confirm there is no quality exception or document the formal exception');
|
|
772
856
|
}
|
|
773
|
-
return missing;
|
|
857
|
+
return Array.from(new Set(missing));
|
|
774
858
|
}
|
|
775
859
|
}
|
|
776
860
|
catch (error) {
|
|
@@ -782,6 +866,11 @@ export function validateDebateDocument(content) {
|
|
|
782
866
|
content.includes('Decide ____ instead of ____ to solve ____.')) {
|
|
783
867
|
missing.push('Fill the decision question with real context');
|
|
784
868
|
}
|
|
869
|
+
const selectedChoice = content.match(/-\s+(?:Escolha|Choice)(?:\s+\(A\/B\/C\))?:\s*(?:op(?:c|ç)[aã]o\s*)?([ABC])\b/i)?.[1] ||
|
|
870
|
+
content.match(/-\s+Op(?:c|ç)[aã]o\s+escolhida:\s*([ABC])\b/i)?.[1] ||
|
|
871
|
+
'A';
|
|
872
|
+
const optionIds = Array.from(content.matchAll(/###\s+Option\s+([A-Z])/gi)).map((match) => match[1]);
|
|
873
|
+
missing.push(...collectPlanningGateMissing(content, selectedChoice.toUpperCase(), optionIds));
|
|
785
874
|
if (/\- (?:Escolha|Choice) \(A\/B\/C\):\s*$/m.test(content)) {
|
|
786
875
|
missing.push('Inform the mediator choice in "Choice (A/B/C)"');
|
|
787
876
|
}
|
|
@@ -800,7 +889,7 @@ export function validateDebateDocument(content) {
|
|
|
800
889
|
if (/\- Exceptions:\s*\n\s+- None, or formal exception/m.test(content)) {
|
|
801
890
|
missing.push('Confirm there is no quality exception or document the formal exception');
|
|
802
891
|
}
|
|
803
|
-
return missing;
|
|
892
|
+
return Array.from(new Set(missing));
|
|
804
893
|
}
|
|
805
894
|
export function pickTopSkills(catalogSkills, ids, max = 3) {
|
|
806
895
|
if (!ids || ids.length === 0)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const DerivationProfileSchema: z.ZodEnum<{
|
|
3
|
-
prototype: "prototype";
|
|
4
3
|
"foundation-compatible": "foundation-compatible";
|
|
4
|
+
prototype: "prototype";
|
|
5
5
|
"enterprise-strict": "enterprise-strict";
|
|
6
6
|
}>;
|
|
7
7
|
export declare const PreviewGateStatusSchema: z.ZodEnum<{
|
|
@@ -14,20 +14,92 @@ export declare const PackageStructureNodeKindSchema: z.ZodEnum<{
|
|
|
14
14
|
file: "file";
|
|
15
15
|
dir: "dir";
|
|
16
16
|
}>;
|
|
17
|
+
export declare const PreviewContextPatternSchema: z.ZodEnum<{
|
|
18
|
+
"bo-pattern": "bo-pattern";
|
|
19
|
+
"entity-pattern": "entity-pattern";
|
|
20
|
+
"application-only": "application-only";
|
|
21
|
+
}>;
|
|
22
|
+
export declare const PreviewDiagnosticSeveritySchema: z.ZodEnum<{
|
|
23
|
+
block: "block";
|
|
24
|
+
warn: "warn";
|
|
25
|
+
}>;
|
|
17
26
|
export declare const PackageStructureNodeSchema: z.ZodSchema<PackageStructureNode>;
|
|
27
|
+
export declare const ApplicationOnlyContextSchema: z.ZodObject<{
|
|
28
|
+
context: z.ZodString;
|
|
29
|
+
path: z.ZodString;
|
|
30
|
+
reason: z.ZodString;
|
|
31
|
+
adr_required: z.ZodDefault<z.ZodBoolean>;
|
|
32
|
+
contract_rule_ref: z.ZodLiteral<"DTAPI-P1-APPONLY-001">;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
export declare const PreviewContextClassificationSchema: z.ZodObject<{
|
|
35
|
+
context: z.ZodString;
|
|
36
|
+
pattern: z.ZodEnum<{
|
|
37
|
+
"bo-pattern": "bo-pattern";
|
|
38
|
+
"entity-pattern": "entity-pattern";
|
|
39
|
+
"application-only": "application-only";
|
|
40
|
+
}>;
|
|
41
|
+
source_paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
42
|
+
decision_refs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
export declare const PreviewDiagnosticSchema: z.ZodObject<{
|
|
45
|
+
code: z.ZodString;
|
|
46
|
+
severity: z.ZodEnum<{
|
|
47
|
+
block: "block";
|
|
48
|
+
warn: "warn";
|
|
49
|
+
}>;
|
|
50
|
+
message: z.ZodString;
|
|
51
|
+
remediation: z.ZodString;
|
|
52
|
+
path: z.ZodOptional<z.ZodString>;
|
|
53
|
+
}, z.core.$strip>;
|
|
18
54
|
export declare const PackageStructurePreviewSchema: z.ZodObject<{
|
|
19
55
|
schema_version: z.ZodLiteral<1>;
|
|
20
56
|
generated_at: z.ZodString;
|
|
21
57
|
project_name: z.ZodString;
|
|
22
58
|
profile: z.ZodEnum<{
|
|
23
|
-
prototype: "prototype";
|
|
24
59
|
"foundation-compatible": "foundation-compatible";
|
|
60
|
+
prototype: "prototype";
|
|
25
61
|
"enterprise-strict": "enterprise-strict";
|
|
26
62
|
}>;
|
|
63
|
+
source: z.ZodDefault<z.ZodEnum<{
|
|
64
|
+
template: "template";
|
|
65
|
+
"artifact-map": "artifact-map";
|
|
66
|
+
}>>;
|
|
27
67
|
contexts: z.ZodArray<z.ZodString>;
|
|
28
68
|
subsystems: z.ZodArray<z.ZodString>;
|
|
29
69
|
transports: z.ZodArray<z.ZodString>;
|
|
30
70
|
tree: z.ZodType<PackageStructureNode, unknown, z.core.$ZodTypeInternals<PackageStructureNode, unknown>>;
|
|
71
|
+
foundation_tests_projection: z.ZodOptional<z.ZodType<PackageStructureNode, unknown, z.core.$ZodTypeInternals<PackageStructureNode, unknown>>>;
|
|
72
|
+
runtime_scripts_projection: z.ZodOptional<z.ZodType<PackageStructureNode, unknown, z.core.$ZodTypeInternals<PackageStructureNode, unknown>>>;
|
|
73
|
+
application_only_contexts: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
74
|
+
context: z.ZodString;
|
|
75
|
+
path: z.ZodString;
|
|
76
|
+
reason: z.ZodString;
|
|
77
|
+
adr_required: z.ZodDefault<z.ZodBoolean>;
|
|
78
|
+
contract_rule_ref: z.ZodLiteral<"DTAPI-P1-APPONLY-001">;
|
|
79
|
+
}, z.core.$strip>>>;
|
|
80
|
+
context_classification: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
81
|
+
context: z.ZodString;
|
|
82
|
+
pattern: z.ZodEnum<{
|
|
83
|
+
"bo-pattern": "bo-pattern";
|
|
84
|
+
"entity-pattern": "entity-pattern";
|
|
85
|
+
"application-only": "application-only";
|
|
86
|
+
}>;
|
|
87
|
+
source_paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
88
|
+
decision_refs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
89
|
+
}, z.core.$strip>>>;
|
|
90
|
+
contract_pack_refs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
91
|
+
diagnostics: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
92
|
+
code: z.ZodString;
|
|
93
|
+
severity: z.ZodEnum<{
|
|
94
|
+
block: "block";
|
|
95
|
+
warn: "warn";
|
|
96
|
+
}>;
|
|
97
|
+
message: z.ZodString;
|
|
98
|
+
remediation: z.ZodString;
|
|
99
|
+
path: z.ZodOptional<z.ZodString>;
|
|
100
|
+
}, z.core.$strip>>>;
|
|
101
|
+
artifact_languages: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
102
|
+
material_signature: z.ZodString;
|
|
31
103
|
}, z.core.$strip>;
|
|
32
104
|
export declare const HumanValidationGateSchema: z.ZodObject<{
|
|
33
105
|
gate_id: z.ZodString;
|
|
@@ -43,6 +115,9 @@ export declare const HumanValidationGateSchema: z.ZodObject<{
|
|
|
43
115
|
approved_by: z.ZodOptional<z.ZodString>;
|
|
44
116
|
correction_notes: z.ZodOptional<z.ZodString>;
|
|
45
117
|
exception_refs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
118
|
+
contract_pack_refs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
119
|
+
material_signature: z.ZodString;
|
|
120
|
+
serialized_at: z.ZodString;
|
|
46
121
|
}, z.core.$strip>;
|
|
47
122
|
export interface HumanValidationGateData {
|
|
48
123
|
selected_profile: z.infer<typeof DerivationProfileSchema>;
|
|
@@ -62,16 +137,23 @@ export interface DebGateInput {
|
|
|
62
137
|
subsystems?: string[];
|
|
63
138
|
transports?: string[];
|
|
64
139
|
generated_at?: string;
|
|
140
|
+
artifact_map?: unknown;
|
|
141
|
+
previous_human_validation_gate?: z.infer<typeof HumanValidationGateSchema>;
|
|
142
|
+
contract_pack_refs?: string[];
|
|
65
143
|
}
|
|
66
144
|
export declare function generatePackageStructurePreview(input: DebGateInput): z.infer<typeof PackageStructurePreviewSchema>;
|
|
67
145
|
export declare function formatPreviewAsTree(node: z.infer<typeof PackageStructureNodeSchema>, prefix?: string): string;
|
|
68
|
-
export declare function buildHumanValidationGate(preview: z.infer<typeof PackageStructurePreviewSchema
|
|
146
|
+
export declare function buildHumanValidationGate(preview: z.infer<typeof PackageStructurePreviewSchema>, options?: {
|
|
147
|
+
previous_gate?: z.infer<typeof HumanValidationGateSchema>;
|
|
148
|
+
exception_refs?: string[];
|
|
149
|
+
}): z.infer<typeof HumanValidationGateSchema>;
|
|
69
150
|
export declare function generateDevtrackApiDebGate(input: DebGateInput): HumanValidationGateData;
|
|
70
151
|
export declare function isGatePending(gate: z.infer<typeof HumanValidationGateSchema>): boolean;
|
|
71
152
|
export declare function isGateApproved(gate: z.infer<typeof HumanValidationGateSchema>): boolean;
|
|
72
153
|
export type DerivationProfile = z.infer<typeof DerivationProfileSchema>;
|
|
73
154
|
export type PreviewGateStatus = z.infer<typeof PreviewGateStatusSchema>;
|
|
74
155
|
export type PackageStructureNodeKind = z.infer<typeof PackageStructureNodeKindSchema>;
|
|
156
|
+
export type PreviewContextPattern = z.infer<typeof PreviewContextPatternSchema>;
|
|
75
157
|
export type PackageStructureNode = {
|
|
76
158
|
name: string;
|
|
77
159
|
kind: PackageStructureNodeKind;
|