{"record":{"id":"f257817f0fbf7ae2","repo":"Yeachan-Heo/oh-my-codex","slug":"final-architecture-invariant-gate-sourceartifacts","errorCode":null,"errorMessage":"Final architecture-invariant gate sourceArtifacts must include required invariant source artifact: ${required.sourceArtifact}","messagePattern":"Final architecture-invariant gate sourceArtifacts must include required invariant source artifact: (.+?)","errorType":"validation","errorClass":"UltragoalError","httpStatus":null,"severity":"error","filePath":"src/ultragoal/artifacts.ts","lineNumber":1645,"sourceCode":"  return uniqueRequiredArchitectureInvariants([...briefInvariants, ...steeringInvariants]);\n}\n\n\nfunction validateArchitectureInvariantGate(gate: Partial<UltragoalQualityGate>, requiredInvariants: readonly RequiredArchitectureInvariant[]): void {\n  const invariantGate = gate.architectureInvariantGate;\n  if (!invariantGate || typeof invariantGate !== 'object') {\n    throw new UltragoalError('Final quality gate is missing architectureInvariantGate evidence; include derived architecture/domain invariants, source artifacts, implementation/test/review evidence, or record final blockers for unproved invariants.');\n  }\n  if (invariantGate.status !== 'passed') {\n    throw new UltragoalError('Final architecture-invariant gate requires architectureInvariantGate.status=\"passed\"; record blocker-resolution work for unproved invariants.');\n  }\n  if (!Array.isArray(invariantGate.sourceArtifacts)) {\n    throw new UltragoalError('Final architecture-invariant gate requires architectureInvariantGate.sourceArtifacts.');\n  }\n  const sourceArtifacts = invariantGate.sourceArtifacts.map((source) => assertNonEmpty(source, 'architectureInvariantGate.sourceArtifacts[]'));\n  for (const required of requiredInvariants) {\n    if (!sourceArtifacts.some((source) => sourceReferencesArtifact(source, required.sourceArtifact))) {\n      throw new UltragoalError(`Final architecture-invariant gate sourceArtifacts must include required invariant source artifact: ${required.sourceArtifact}`);\n    }\n  }\n  assertNonEmpty(invariantGate.evidence, 'architectureInvariantGate.evidence');\n  if (!Array.isArray(invariantGate.invariants)) {\n    throw new UltragoalError('Final architecture-invariant gate requires architectureInvariantGate.invariants.');\n  }\n  const provided = new Map<string, UltragoalArchitectureInvariantEvidence[]>();\n  for (const invariant of invariantGate.invariants) {\n    if (!invariant || typeof invariant !== 'object') throw new UltragoalError('Final architecture-invariant gate invariants must be objects.');\n    const record = invariant as Partial<UltragoalArchitectureInvariantEvidence> & { blockers?: unknown };\n    const text = assertNonEmpty(record.invariant, 'architectureInvariantGate.invariants[].invariant');\n    const source = assertNonEmpty(record.source, 'architectureInvariantGate.invariants[].source');\n    if (!sourceReferencesAnyArtifact(source, sourceArtifacts)) {\n      throw new UltragoalError(`Final architecture invariant \"${text}\" source must reference one of architectureInvariantGate.sourceArtifacts; decorative provenance labels are not sufficient.`);\n    }\n    if (record.status !== 'proved') throw new UltragoalError(`Final architecture invariant \"${text}\" is not proved; record blocker-resolution work before final completion.`);\n    if (record.blockers !== undefined) throw new UltragoalError(`Final architecture invariant \"${text}\" has blockers; record blocker-resolution work before final completion.`);\n    assertNonEmpty(record.implementationEvidence, 'architectureInvariantGate.invariants[].implementationEvidence');","sourceCodeStart":1627,"sourceCodeEnd":1663,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/ultragoal/artifacts.ts#L1627-L1663","documentation":"None of the gate's sourceArtifacts entries reference a source artifact that a required architecture invariant derives from. For every required invariant, at least one sourceArtifacts entry must match via sourceReferencesArtifact (e.g. path containment/suffix match on required.sourceArtifact).","triggerScenarios":"Finalizing with sourceArtifacts that cite different files than the ones the plan's required invariants were derived from — e.g. ['docs/my-notes.md'] when an invariant requires 'docs/architecture/invariants.md'.","commonSituations":"Renaming/moving architecture docs after invariants were derived; citing a summary doc instead of the canonical invariant source; case or path-root differences between the stored artifact path and the cited string; multiple invariants each needing distinct sources that weren't all listed.","solutions":["Read the plan's required invariants and include each required.sourceArtifact verbatim in sourceArtifacts","If docs were moved, include both the new path and a reference that still matches the stored source (or re-derive invariants from the new location)","Check for path-root/case mismatches: the entry must satisfy sourceReferencesArtifact(entry, required.sourceArtifact)","List every required invariant's source, not just one"],"exampleFix":"// before (invariant requires 'docs/architecture/invariants.md')\nsourceArtifacts: ['notes/adr-001.md']\n\n// after\nsourceArtifacts: ['notes/adr-001.md', 'docs/architecture/invariants.md']","handlingStrategy":"validation","validationCode":"const plan = await readUltragoalPlan(cwd);\nconst required = plan.architectureInvariants ?? []; // required invariants\nconst cited = new Set(gate.architectureInvariantGate.sourceArtifacts);\nconst missing = required.filter(r => ![...cited].some(c => c === r.sourceArtifact || c.endsWith(r.sourceArtifact) || r.sourceArtifact.endsWith(c)));\nif (missing.length) gate.architectureInvariantGate.sourceArtifacts.push(...missing.map(m => m.sourceArtifact));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mirror each required invariant's sourceArtifact into sourceArtifacts when building the gate","Keep architecture docs at stable paths after invariants are derived","When docs move, include both old and new paths or re-derive invariants"],"tags":["ultragoal","quality-gate","source-artifacts","invariant-coverage"],"backgroundTag":"required-reference-not-cited","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}