State Model - AFPS Tracker
Review page for the proposed logical domain/state/contract model for AFPS Tracker's first repo read-through. This page proposes canonical writes to design/afps-tracker/domain-model-afps-tracker.md, design/afps-tracker/model-tree-afps-tracker.yaml, and branch model_ref attachments in design/afps-tracker/flow-tree-afps-tracker.yaml, but no canonical state-model artifacts have been written yet.
Table Of Contents
Decision Summary
The proposed model keeps AFPS Tracker passive and read-first. Canonical truth remains in AFPS artifacts; the tracker models source-derived workflow state, claim support, diagnostics, and handoff readiness without owning storage, endpoints, auth, migrations, or deployment decisions.
ProductPath the primary aggregate root, is consistent across all five frameworks and keeps source artifacts, claims, diagnostics, and handoffs interpreted through the selected path.
Framework Inputs
| Order | Framework | Canonical contribution | Intermediate |
|---|---|---|---|
| 1 | event-modeling | Timeline of scan, source resolution, diagnostic evaluation, trust degradation, boundary explanation, and handoff generation. | design/afps-tracker/state-model-afps-tracker/event-modeling.md |
| 2 | domain-model | DDD spine: ProductPath primary aggregate, Portfolio thin orientation aggregate, first-class claim/evidence/provenance/diagnostic/handoff elements. | design/afps-tracker/state-model-afps-tracker/domain-model.md |
| 3 | state-machine | Lifecycle states, transitions, guards, UI-state mappings, warning preservation, blocking diagnostics, and boundary suppression. | design/afps-tracker/state-model-afps-tracker/state-machine.md |
| 4 | data-model | Logical ERD with repository context, portfolio snapshot, path refs, product paths, artifacts, claims, evidence, provenance, diagnostics, and handoffs. | design/afps-tracker/state-model-afps-tracker/data-model.md |
| 5 | contract-map | Logical command/query contracts and shared response types, especially TrustEnvelope, DiagnosticRef, and HandoffBoundary. | design/afps-tracker/state-model-afps-tracker/contract-map.md |
Proposed Domain Model
This is the proposed full content for design/afps-tracker/domain-model-afps-tracker.md.
---
skill: state-model
status: proposed
topic: afps-tracker
product_path: research/afps-tracker
flow_tree: design/afps-tracker/flow-tree-afps-tracker.yaml
model_tree: design/afps-tracker/model-tree-afps-tracker.yaml
alignment_page: alignment/state-model-afps-tracker.html
---
# AFPS Tracker Domain Model
## Scope
AFPS Tracker models the first repo read-through for an AFPS-style repository. The operator opens a repository, orients across active and parallel product paths, verifies selected-path stage/status/reason/evidence/provenance, recovers from diagnostics, and leaves with a source-backed handoff or boundary explanation.
The model is logical only. It describes entities, states, events, commands, queries, read models, policies, and logical request/response/error shapes. It does not define storage engines, real endpoints, URLs, authentication, authorization, migrations, indexes, file watchers, deployment, or high-fidelity UI.
## Ubiquitous Language
- Product path: source-derived AFPS product/research path, usually scoped under `research/{slug}`.
- Portfolio: repo-local collection of active, parallel, inactive, excluded, and unresolved product path references.
- Source artifact: canonical AFPS file or generated artifact used as evidence or provenance.
- Source-backed claim: displayed or handoffable assertion with traceable source support or an explicit caveat.
- Evidence link: claim-to-source reference, including unresolved or contradictory support.
- Provenance record: approval, canonicalization, amendment, archive, review, or working-packet lineage.
- Diagnostic issue: trust degradation item scoped to source, claim, path, portfolio, or handoff level.
- Trust level: clean, warning, blocked, partial, inferred, unsupported, contradicted, source-backed, explanatory, or out-of-scope.
- Parser confidence: certainty of extraction or mapping from source artifacts.
- Source confidence: confidence that source/provenance supports a claim.
- Handoff eligibility: clean-copy, warning-copy, blocked, explanatory, promoted-boundary, out-of-scope, or unavailable.
- Boundary kind: inactive, archived, deferred, revisit-candidate, promoted, out-of-scope, unsupported, or unresolved.
## Aggregate Roots
### Portfolio
Thin orientation aggregate for a repo-local read-through. It groups source path references, active path refs, inactive/boundary refs, and unresolved refs.
Invariants:
- Active path refs must resolve to product path records or explicit unresolved diagnostics.
- Archived, deferred, revisit-candidate, promoted, `_archive`, and out-of-scope refs remain visible but cannot silently become active route targets.
- Portfolio-level source health is displayed separately from selected-path trust.
Flow bindings: `uf-orient-portfolio` reads/displays; `uf-recover-diagnostics` transitions; `uf-explain-boundaries` reads excluded refs.
### ProductPath
Primary aggregate root for selected-path interpretation. It owns path identity, source state, stage, reason, next skill, evidence/provenance refs, derived trust, diagnostics, handoff eligibility, and boundary explanation.
Invariants:
- A path fact is clean only when source artifacts, evidence links, or provenance support it.
- Missing, contradictory, stale, inaccessible, or low-confidence source facts degrade trust instead of being hidden.
- Inactive, promoted, unresolved, blocked, out-of-scope, unsupported, or contradicted paths cannot emit a normal clean next-skill handoff.
- Warning or partial handoffs must preserve warnings and diagnostic refs.
Flow bindings: all six user-flow nodes read, display, write, or transition through this aggregate.
## Entities And Value Objects
| Element | Kind | Key attributes | Relationships | Lifecycle |
| --- | --- | --- | --- | --- |
| RepositoryContext | entity | repository_ref, scan_started_at, scan_completed_at, scan_state, source_health, warnings | one optional PortfolioSnapshot; many SourceArtifacts and DiagnosticIssues | Portfolio scan state |
| PortfolioSnapshot | entity/read model | snapshot_id, progress_manifest_ref, snapshot_state, active_path_refs, excluded_path_refs, parser_confidence, source_confidence | many PortfolioPathRefs and ProductPaths | Portfolio state |
| PortfolioPathRef | entity | path_ref_id, path_id, scope_path, source_status, resolution_state, boundary_kind, diagnostic_refs | resolves to zero or one ProductPath | Ref resolution state |
| ProductPath | aggregate-root | path_id, label, scope_path, source_status, pipeline_stage, reason, next_skill, revisit_trigger, last_touched, path_state, trust_level, handoff_eligibility, boundary_kind | many SourceArtifacts, SourceBackedClaims, EvidenceLinks, ProvenanceRecords, DiagnosticIssues, HandoffSummaries | Product path state |
| SourceArtifact | entity | artifact_id, artifact_ref, artifact_kind, source_role, read_status, approval_status, freshness_state, parser_confidence, source_confidence, warnings | supports claims, evidence, provenance, diagnostics | Source artifact state |
| SourceBackedClaim | entity | claim_id, claim_kind, claim_text, support_status, parser_confidence, source_confidence, trust_level, derived_from, warnings | has zero or many EvidenceLinks and DiagnosticIssues | Claim support state |
| EvidenceLink | entity/value slice | evidence_link_id, claim_id, evidence_ref, resolved_ref, resolution_state, support_status, read_status, source_hint, warnings | links claim to zero or one SourceArtifact | Evidence link state |
| ProvenanceRecord | entity/value slice | provenance_id, provenance_ref, provenance_kind, approval_state, decision_summary, canonical_target, archive_refs, confidence, warnings | supports claims and handoffs | Provenance state |
| DiagnosticIssue | entity | issue_id, issue_kind, severity, level, state, affected_refs, affected_claims, affected_paths, handoff_impact, recommended_manual_check | affects source, claim, path, portfolio, or handoff | Diagnostic issue state |
| HandoffSummary | entity/read model output | summary_id, handoff_type, copy_state, confidence, next_skill, branch_state_explanation, handoff_boundary, included refs, blocked_reasons | reads ProductPath, claims, evidence, provenance, diagnostics | Handoff summary state |
## State Machines
### Portfolio
States: `unscanned`, `scanning`, `no-afps-state`, `manifest-malformed`, `paths-discovered`, `partial`, `source-backed`, `blocked`.
Key transitions:
- `unscanned -> scanning` on `ScanPortfolio`.
- `scanning -> no-afps-state` on missing progress/product-path state.
- `scanning -> manifest-malformed` on malformed source.
- `scanning -> paths-discovered` when product path records or refs are interpretable.
- `paths-discovered -> partial|source-backed|blocked` after diagnostic classification.
UI state mappings: empty initial frame, loading portfolio overview, empty/no-manifest state, grouped path rows, partial/warning badges, clean portfolio overview, blocking portfolio diagnostic.
### ProductPath
States: `undiscovered`, `discovered`, `selected`, `source-inventorying`, `source-backed`, `partial`, `warning`, `blocked`, `inactive`, `promoted-boundary`, `out-of-scope`.
Key transitions:
- `undiscovered -> discovered` when a source record exists.
- `discovered -> selected` on `ProductPathSelected`.
- `selected -> source-inventorying` when scoped artifacts, evidence, provenance, diagnostics, and next skill are resolved.
- `source-inventorying -> source-backed|partial|blocked` from source and claim support.
- `source-backed -> warning|blocked` when diagnostics appear.
- `discovered|selected -> inactive|promoted-boundary|out-of-scope` when boundary policy suppresses normal routing.
UI state mappings: portfolio row, detail loading, clean selected-path detail, partial badges, warning detail, blocked diagnostics, inactive/promoted/out-of-scope explanation.
### SourceArtifact
States: `referenced`, `resolving`, `found`, `parsed`, `confirmed`, `review-only`, `amended`, `archived`, `missing`, `unreadable`, `malformed`, `stale`, `unsupported`.
UI state mappings: source ref row, source loading row, resolved source path, parsed facts, confirmed/review/amended/archive badges, missing/unreadable/malformed/stale/unsupported diagnostics.
### EvidenceLink
States: `unresolved`, `resolving`, `resolved`, `supports-claim`, `partially-supports-claim`, `contradicts-claim`, `inaccessible`.
UI state mappings: unresolved evidence marker, evidence loading marker, resolved evidence path/section, source-backed claim badge, partial support badge, contradiction warning/blocker, inaccessible warning.
### ProvenanceRecord
States: `missing`, `discovered`, `review`, `confirmed`, `amended`, `archived`, `partial`, `contradicted`.
UI state mappings: missing provenance warning, pending provenance row, review caveat, confirmed approval badge, amended badge, archive marker, partial provenance badge, contradiction blocker.
### DiagnosticIssue
Severity states: `none`, `raised`, `classified`, `warning`, `blocked`, `partial`, `resolved-by-source-review`.
Affected-level states: `source-level`, `claim-level`, `path-level`, `portfolio-level`, `handoff-level`.
Synthesis rule: severity and affected level are orthogonal fields and must not be flattened into one ambiguous status.
### HandoffSummary
States: `unavailable`, `requested`, `clean-copy`, `warning-copy`, `blocked`, `explanatory`, `promoted-boundary`, `out-of-scope`, `copied`, `suppressed`.
UI state mappings: disabled/absent handoff area, preparation state, clean copy-ready summary, warning copy-ready summary, blocked summary with reasons, boundary explanation, copy success, suppressed copy state.
## Events
Repository and portfolio events: `RepositoryScanStarted`, `ProgressManifestLocated`, `ProgressManifestMissing`, `ProgressManifestParsed`, `ProgressManifestMalformed`, `ActivePathsNormalized`, `ProductPathRecordDiscovered`, `ProductPathRecordExcluded`, `ActivePathReferenceUnresolved`.
Selection and source events: `ProductPathSelected`, `ScopedSourceInventoryStarted`, `ScopedResearchArtifactResolved`, `ScopedResearchArtifactMissing`, `EvidenceRefResolutionStarted`, `EvidenceRefResolved`, `EvidenceRefUnresolved`, `ClaimInspectionRequested`, `ClaimSupportEvaluated`, `SourcePreviewPrepared`, `SourcePreviewUnavailable`.
Provenance events: `ProvenanceRecordDiscovered`, `ProvenanceRecordConfirmed`, `ProvenanceRecordReviewOnly`, `ProvenanceRecordArchived`, `ProvenanceRecordMissing`.
Diagnostic and trust events: `DiagnosticIssueRaised`, `DiagnosticIssueClassified`, `TrustLevelChanged`, `HandoffEligibilityChanged`, `NextSkillCandidateDetected`, `NextSkillCandidateSuppressed`.
Handoff and boundary events: `HandoffGenerationRequested`, `HandoffSummaryPrepared`, `CleanCopyPrepared`, `WarningCopyPrepared`, `HandoffBlocked`, `HandoffCopyRequested`, `HandoffCopied`, `HandoffCopySuppressed`, `BoundaryExplanationRequested`, `PromotedBoundaryDetected`, `InactivePathExplained`, `OutOfScopeRequestExplained`.
## Commands And Queries
Commands:
- `ScanPortfolio`: starts repo-local source read-through and derives portfolio orientation.
- `SelectProductPath`: establishes selected-path context.
- `EvaluateDiagnostics`: classifies source, claim, path, portfolio, and handoff issues.
- `GenerateHandoff`: prepares clean, warning, blocked, explanatory, promoted-boundary, or out-of-scope handoff output.
- `CopyHandoff`: records logical copy/export attempt and suppression reasons when copying is not allowed.
Queries:
- `ListPortfolioPaths`: returns grouped portfolio state.
- `GetSelectedPathDetail`: returns source-backed detail for one selected path.
- `InspectEvidenceRef`: resolves and classifies claim-to-source evidence.
- `InspectProvenance`: returns approval, canonicalization, amendment, archive, and review lineage.
- `GetDiagnostics`: returns current diagnostic state scoped to portfolio, path, claim, source, or handoff.
- `ExplainBoundary`: explains inactive, promoted, out-of-scope, unresolved, unsupported, or contradicted path state without normal active routing.
Shared logical response types: `RepositoryContextInput`, `ProductPathSelector`, `ArtifactRef`, `ClaimRef`, `TrustEnvelope`, `DiagnosticRef`, and `HandoffBoundary`.
## Read Models
- Portfolio Overview: scan status, active paths, grouped path refs, source health, warnings, parser confidence.
- Selected Path Detail: selected path facts, refs, confidence, claims, diagnostics, handoff eligibility, available and blocked actions.
- Evidence Inspector: claim ID/text, evidence link, resolved ref, support status, source hint, trust, diagnostics, preview availability.
- Provenance Timeline: approval/canonical/amend/archive/review records, confidence, warnings, diagnostics, handoff relevance.
- Diagnostics Panel: issues by severity and level, affected sources/claims/paths, handoff impacts, manual checks, trust changes.
- Handoff Summary: handoff type, copy state, next skill when permitted, explanation, refs, warnings, blockers, boundary.
## Policies
- Source Truth Policy: displayed facts and handoff claims must be source-backed or explicitly labeled derived, inferred, unsupported, partial, or contradicted.
- Active Path Resolution Policy: active refs must resolve to non-excluded product path records or visible unresolved diagnostics.
- Evidence Support Policy: source-backed labels require readable artifacts, mapped fields/sections, approval records, or source hints.
- Provenance Confidence Policy: confirmed provenance requires confirmed alignment or canonical artifact evidence; review-only remains partial.
- Diagnostic Severity Policy: degrade trust at the narrowest affected level before escalating to path or handoff.
- Handoff Eligibility Policy: clean copy requires source-backed next work and no blocking diagnostics; warning copy preserves caveats; inactive/promoted/out-of-scope/unresolved/contradicted paths produce explanatory or blocked handoffs.
- Boundary Preservation Policy: promoted development/execution work remains outside AFPS Tracker unless a separate flow owns it.
- Confidence Separation Policy: parser confidence and source confidence remain separate fields.
- Next Command Suppression Policy: promoted, inactive, out-of-scope, unsupported, contradicted, blocked, or source-insufficient states suppress normal next-command output.
## Flow Binding Matrix
| Flow node | Reads | Writes/triggers | Displays | Transitions |
| --- | --- | --- | --- | --- |
| `uf-orient-portfolio` | RepositoryContext, PortfolioSnapshot, PortfolioPathRef, ProductPath, SourceArtifact, diagnostics | `ScanPortfolio`, `SelectProductPath` | Portfolio Overview, source health, path groups, active/parallel/inactive states | portfolio scan; unresolved refs; path selected |
| `uf-verify-selected-path` | ProductPath, SourceArtifact, SourceBackedClaim, TrustEnvelope, HandoffEligibility | selected-path context, scoped source inventory | Selected Path Detail with source-backed/inferred/partial/warning/blocked labels | selected path source-backed/partial/warning/blocked |
| `uf-inspect-source-provenance` | EvidenceLink, SourceArtifact, SourceBackedClaim, ProvenanceRecord, SourceConfidence | `InspectEvidenceRef`, `InspectProvenance`, claim inspection | Evidence Inspector, Provenance Timeline | evidence/provenance resolved, unresolved, confirmed, review, missing, contradicted |
| `uf-recover-diagnostics` | DiagnosticIssue, affected scopes, TrustLevel, HandoffEligibility | `EvaluateDiagnostics`, trust transitions | Diagnostics Panel | clean/warning/blocked/partial/source-backed degradation and recovery |
| `uf-handoff-resume` | ProductPath, SourceBackedClaim, DiagnosticIssue, HandoffSummary, HandoffEligibility | `GenerateHandoff`, `CopyHandoff` | Handoff Summary and copy/suppression state | requested, clean-copy, warning-copy, blocked, copied, suppressed |
| `uf-explain-boundaries` | ProductPath, BoundaryKind, source rationale, evidence/provenance, diagnostics | `ExplainBoundary`, boundary handoff generation | inactive/promoted/out-of-scope/unsupported/unresolved explanations | active route suppressed; explanatory/boundary handoff prepared |
## Assumptions And Confidence
High confidence:
- ProductPath is the right primary aggregate for selected-path interpretation.
- Portfolio should stay a thin orientation aggregate.
- Parser confidence and source confidence must remain separate.
- Diagnostics need orthogonal severity and affected-level fields.
- Handoff generation is policy output, not independent source truth.
Medium confidence:
- RepositoryContext and PortfolioSnapshot are the right names for read-through context entities.
- One model can cover all six first-read-through branches before key-moments has promoted/pruned individual branches.
Watch item:
- If later key-moments work prunes or narrows branches, this model should be narrowed through modify-back rather than treated as final for pruned paths.
## Physical Concern Deferrals
Deferred to `$spec-interview` or later implementation planning: file watching, parsing implementation, caching, persistence, database schema, storage engine, indexes, migrations, real routes/endpoints/URLs/transports, authentication, authorization, sandbox/permission implementation, deployment, source preview rendering, clipboard/export mechanics, and high-fidelity UI component layout.
Proposed Model Tree YAML
This is the proposed content for design/afps-tracker/model-tree-afps-tracker.yaml.
schema_version: v0.1
mode: product-path
topic: afps-tracker
product_path: research/afps-tracker
status: proposed
flow_tree_ref: design/afps-tracker/flow-tree-afps-tracker.yaml
domain_model_ref: design/afps-tracker/domain-model-afps-tracker.md
alignment_page: alignment/state-model-afps-tracker.html
source_artifacts:
- design/afps-tracker/_working/state-model-afps-tracker-brief.md
- design/afps-tracker/flow-tree-afps-tracker.yaml
- design/afps-tracker/user-flow-afps-tracker.md
- design/afps-tracker/state-model-afps-tracker/event-modeling.md
- design/afps-tracker/state-model-afps-tracker/domain-model.md
- design/afps-tracker/state-model-afps-tracker/state-machine.md
- design/afps-tracker/state-model-afps-tracker/data-model.md
- design/afps-tracker/state-model-afps-tracker/contract-map.md
frameworks:
- id: event-modeling
status: synthesized
source: design/afps-tracker/state-model-afps-tracker/event-modeling.md
- id: domain-model
status: synthesized
source: design/afps-tracker/state-model-afps-tracker/domain-model.md
- id: state-machine
status: synthesized
source: design/afps-tracker/state-model-afps-tracker/state-machine.md
- id: data-model
status: synthesized
source: design/afps-tracker/state-model-afps-tracker/data-model.md
- id: contract-map
status: synthesized
source: design/afps-tracker/state-model-afps-tracker/contract-map.md
entities:
- id: portfolio
kind: aggregate-root
attributes: [source_health, active_path_refs, excluded_path_refs, unresolved_refs, parser_confidence, source_confidence]
relationships: [{to: product-path, cardinality: one-to-many}]
lifecycle_ref: portfolio-state
flow_bindings:
- {flow_node_ref: uf-orient-portfolio, access: displays}
- {flow_node_ref: uf-recover-diagnostics, access: transitions}
- {flow_node_ref: uf-explain-boundaries, access: reads}
- id: repository-context
kind: entity
attributes: [repository_ref, scan_started_at, scan_completed_at, scan_state, source_health, warnings]
relationships: [{to: portfolio-snapshot, cardinality: one-to-zero-or-one}, {to: source-artifact, cardinality: one-to-many}]
lifecycle_ref: portfolio-state
flow_bindings:
- {flow_node_ref: uf-orient-portfolio, access: triggers}
- {flow_node_ref: uf-recover-diagnostics, access: displays}
- id: portfolio-snapshot
kind: entity
attributes: [snapshot_id, progress_manifest_ref, snapshot_state, active_path_refs, excluded_path_refs, parser_confidence, source_confidence]
relationships: [{to: portfolio-path-ref, cardinality: one-to-many}, {to: product-path, cardinality: one-to-many}]
lifecycle_ref: portfolio-state
flow_bindings:
- {flow_node_ref: uf-orient-portfolio, access: displays}
- {flow_node_ref: uf-explain-boundaries, access: reads}
- id: portfolio-path-ref
kind: entity
attributes: [path_ref_id, path_id, scope_path, source_status, resolution_state, boundary_kind, diagnostic_refs]
relationships: [{to: product-path, cardinality: many-to-zero-or-one}]
flow_bindings:
- {flow_node_ref: uf-orient-portfolio, access: displays}
- {flow_node_ref: uf-recover-diagnostics, access: writes}
- {flow_node_ref: uf-explain-boundaries, access: reads}
- id: product-path
kind: aggregate-root
attributes: [path_id, label, scope_path, source_status, pipeline_stage, reason, next_skill, revisit_trigger, last_touched, path_state, trust_level, handoff_eligibility, boundary_kind]
relationships: [{to: source-artifact, cardinality: one-to-many}, {to: source-backed-claim, cardinality: one-to-many}, {to: diagnostic-issue, cardinality: one-to-many}, {to: handoff-summary, cardinality: one-to-many}]
lifecycle_ref: product-path-state
flow_bindings:
- {flow_node_ref: uf-orient-portfolio, access: displays}
- {flow_node_ref: uf-verify-selected-path, access: writes}
- {flow_node_ref: uf-recover-diagnostics, access: transitions}
- {flow_node_ref: uf-handoff-resume, access: reads}
- {flow_node_ref: uf-explain-boundaries, access: displays}
- id: source-artifact
kind: entity
attributes: [artifact_id, artifact_ref, artifact_kind, source_role, read_status, approval_status, freshness_state, parser_confidence, source_confidence, warnings]
relationships: [{to: source-backed-claim, cardinality: many-to-many}, {to: provenance-record, cardinality: many-to-many}]
lifecycle_ref: source-artifact-state
flow_bindings:
- {flow_node_ref: uf-verify-selected-path, access: reads}
- {flow_node_ref: uf-inspect-source-provenance, access: displays}
- {flow_node_ref: uf-recover-diagnostics, access: transitions}
- id: source-backed-claim
kind: entity
attributes: [claim_id, claim_kind, claim_text, support_status, parser_confidence, source_confidence, trust_level, derived_from, warnings]
relationships: [{to: evidence-link, cardinality: one-to-many}, {to: diagnostic-issue, cardinality: one-to-many}]
lifecycle_ref: evidence-link-state
flow_bindings:
- {flow_node_ref: uf-verify-selected-path, access: displays}
- {flow_node_ref: uf-inspect-source-provenance, access: reads}
- {flow_node_ref: uf-recover-diagnostics, access: reads}
- {flow_node_ref: uf-handoff-resume, access: reads}
- id: evidence-link
kind: entity
attributes: [evidence_link_id, claim_id, evidence_ref, resolved_ref, resolution_state, support_status, read_status, source_hint, warnings]
relationships: [{to: source-artifact, cardinality: many-to-zero-or-one}]
lifecycle_ref: evidence-link-state
flow_bindings:
- {flow_node_ref: uf-inspect-source-provenance, access: triggers}
- {flow_node_ref: uf-recover-diagnostics, access: transitions}
- id: provenance-record
kind: entity
attributes: [provenance_id, provenance_ref, provenance_kind, approval_state, decision_summary, canonical_target, archive_refs, confidence, warnings]
relationships: [{to: source-artifact, cardinality: many-to-many}]
lifecycle_ref: provenance-record-state
flow_bindings:
- {flow_node_ref: uf-inspect-source-provenance, access: displays}
- {flow_node_ref: uf-recover-diagnostics, access: reads}
- {flow_node_ref: uf-handoff-resume, access: reads}
- id: diagnostic-issue
kind: entity
attributes: [issue_id, issue_kind, severity, level, state, affected_refs, affected_claims, affected_paths, handoff_impact, recommended_manual_check]
relationships: [{to: product-path, cardinality: many-to-one}, {to: source-backed-claim, cardinality: many-to-one}, {to: handoff-summary, cardinality: many-to-many}]
lifecycle_ref: diagnostic-issue-state
flow_bindings:
- {flow_node_ref: uf-recover-diagnostics, access: writes}
- {flow_node_ref: uf-orient-portfolio, access: displays}
- {flow_node_ref: uf-handoff-resume, access: reads}
- id: handoff-summary
kind: entity
attributes: [summary_id, handoff_type, copy_state, confidence, next_skill, branch_state_explanation, handoff_boundary, included_evidence_refs, included_provenance_refs, included_diagnostic_refs, blocked_reasons]
relationships: [{to: product-path, cardinality: many-to-one}, {to: diagnostic-issue, cardinality: many-to-many}]
lifecycle_ref: handoff-summary-state
flow_bindings:
- {flow_node_ref: uf-handoff-resume, access: writes}
- {flow_node_ref: uf-explain-boundaries, access: displays}
value_objects:
- {id: artifact-ref, fields: [path, section_hint, artifact_kind, source_role]}
- {id: evidence-ref, fields: [ref, resolved_ref, claim_id, support_status]}
- {id: path-state, values: [active, parallel-active, archived, deferred, revisit-candidate, promoted, out-of-scope, unresolved, partial, warning, blocked, source-backed, selected]}
- {id: trust-level, values: [clean, warning, blocked, partial, inferred, unsupported, contradicted, source-backed, explanatory, out-of-scope]}
- {id: parser-confidence, values: [high, medium, low, unknown]}
- {id: source-confidence, values: [confirmed, partial, review-only, unsupported, contradicted, missing, unknown]}
- {id: handoff-eligibility, values: [clean-copy, warning-copy, blocked, explanatory, promoted-boundary, out-of-scope, unavailable]}
- {id: boundary-kind, values: [inactive, archived, deferred, revisit-candidate, promoted, out-of-scope, unsupported, unresolved]}
state_machines:
- id: portfolio-state
subject: Portfolio
states:
- {id: unscanned, maps_to_ui_state: empty initial portfolio frame}
- {id: scanning, maps_to_ui_state: loading portfolio overview}
- {id: no-afps-state, maps_to_ui_state: empty or no-manifest state}
- {id: manifest-malformed, maps_to_ui_state: blocking parse diagnostic}
- {id: paths-discovered, maps_to_ui_state: grouped portfolio rows}
- {id: partial, maps_to_ui_state: visible warning or partial badges}
- {id: source-backed, maps_to_ui_state: clean portfolio overview}
- {id: blocked, maps_to_ui_state: blocking portfolio diagnostic}
transitions:
- {from: unscanned, event: ScanPortfolio, to: scanning}
- {from: scanning, event: ProgressManifestMissing, to: no-afps-state}
- {from: scanning, event: ProgressManifestMalformed, to: manifest-malformed}
- {from: scanning, event: ProductPathRecordDiscovered, to: paths-discovered}
- {from: paths-discovered, event: DiagnosticIssueClassified, to: source-backed}
- {from: paths-discovered, event: ActivePathReferenceUnresolved, to: partial}
- {from: partial, event: DiagnosticIssueClassified, to: blocked}
- id: product-path-state
subject: ProductPath
states:
- {id: undiscovered, maps_to_ui_state: unresolved active ref or absent path}
- {id: discovered, maps_to_ui_state: portfolio row}
- {id: selected, maps_to_ui_state: product-path detail loading frame}
- {id: source-inventorying, maps_to_ui_state: detail surface source checks}
- {id: source-backed, maps_to_ui_state: clean selected-path detail}
- {id: partial, maps_to_ui_state: partial badges and unresolved refs}
- {id: warning, maps_to_ui_state: warning detail and handoff caveats}
- {id: blocked, maps_to_ui_state: blocked detail and diagnostics}
- {id: inactive, maps_to_ui_state: inactive path explanation}
- {id: promoted-boundary, maps_to_ui_state: promoted boundary explanation}
- {id: out-of-scope, maps_to_ui_state: out-of-scope explanation}
transitions:
- {from: undiscovered, event: ProductPathRecordDiscovered, to: discovered}
- {from: discovered, event: ProductPathSelected, to: selected}
- {from: selected, event: ScopedSourceInventoryStarted, to: source-inventorying}
- {from: source-inventorying, event: ClaimSupportEvaluated, to: source-backed}
- {from: source-inventorying, event: EvidenceRefUnresolved, to: partial}
- {from: source-backed, event: DiagnosticIssueRaised, to: warning}
- {from: warning, event: DiagnosticIssueClassified, to: blocked}
- {from: discovered, event: ProductPathRecordExcluded, to: inactive}
- {from: discovered, event: PromotedBoundaryDetected, to: promoted-boundary}
- id: source-artifact-state
subject: SourceArtifact
states: [referenced, resolving, found, parsed, confirmed, review-only, amended, archived, missing, unreadable, malformed, stale, unsupported]
transitions: [{from: referenced, event: EvidenceRefResolutionStarted, to: resolving}, {from: resolving, event: EvidenceRefResolved, to: found}, {from: found, event: ProgressManifestParsed, to: parsed}, {from: parsed, event: ProvenanceRecordConfirmed, to: confirmed}]
- id: evidence-link-state
subject: EvidenceLink
states: [unresolved, resolving, resolved, supports-claim, partially-supports-claim, contradicts-claim, inaccessible]
transitions: [{from: unresolved, event: InspectEvidenceRef, to: resolving}, {from: resolving, event: EvidenceRefResolved, to: resolved}, {from: resolved, event: ClaimSupportEvaluated, to: supports-claim}]
- id: provenance-record-state
subject: ProvenanceRecord
states: [missing, discovered, review, confirmed, amended, archived, partial, contradicted]
transitions: [{from: missing, event: ProvenanceRecordDiscovered, to: discovered}, {from: discovered, event: ProvenanceRecordConfirmed, to: confirmed}, {from: discovered, event: ProvenanceRecordReviewOnly, to: review}]
- id: diagnostic-issue-state
subject: DiagnosticIssue
states: [none, raised, classified, warning, blocked, partial, source-level, claim-level, path-level, portfolio-level, handoff-level, resolved-by-source-review]
transitions: [{from: none, event: DiagnosticIssueRaised, to: raised}, {from: raised, event: DiagnosticIssueClassified, to: classified}, {from: classified, event: severity-policy, to: warning}, {from: classified, event: severity-policy, to: blocked}]
- id: handoff-summary-state
subject: HandoffSummary
states: [unavailable, requested, clean-copy, warning-copy, blocked, explanatory, promoted-boundary, out-of-scope, copied, suppressed]
transitions: [{from: unavailable, event: GenerateHandoff, to: requested}, {from: requested, event: CleanCopyPrepared, to: clean-copy}, {from: requested, event: WarningCopyPrepared, to: warning-copy}, {from: requested, event: HandoffBlocked, to: blocked}, {from: clean-copy, event: CopyHandoff, to: copied}]
events:
- {id: repository-scan-started, flow_bindings: [{flow_node_ref: uf-orient-portfolio, access: triggers}]}
- {id: progress-manifest-parsed, flow_bindings: [{flow_node_ref: uf-orient-portfolio, access: reads}]}
- {id: product-path-selected, flow_bindings: [{flow_node_ref: uf-verify-selected-path, access: writes}]}
- {id: evidence-ref-resolved, flow_bindings: [{flow_node_ref: uf-inspect-source-provenance, access: displays}]}
- {id: provenance-record-confirmed, flow_bindings: [{flow_node_ref: uf-inspect-source-provenance, access: displays}]}
- {id: diagnostic-issue-classified, flow_bindings: [{flow_node_ref: uf-recover-diagnostics, access: transitions}]}
- {id: handoff-summary-prepared, flow_bindings: [{flow_node_ref: uf-handoff-resume, access: displays}]}
- {id: promoted-boundary-detected, flow_bindings: [{flow_node_ref: uf-explain-boundaries, access: displays}]}
commands:
- {id: scan-portfolio, flow_bindings: [{flow_node_ref: uf-orient-portfolio, access: triggers}]}
- {id: select-product-path, flow_bindings: [{flow_node_ref: uf-verify-selected-path, access: writes}]}
- {id: evaluate-diagnostics, flow_bindings: [{flow_node_ref: uf-recover-diagnostics, access: writes}]}
- {id: generate-handoff, flow_bindings: [{flow_node_ref: uf-handoff-resume, access: triggers}, {flow_node_ref: uf-explain-boundaries, access: triggers}]}
- {id: copy-handoff, flow_bindings: [{flow_node_ref: uf-handoff-resume, access: writes}]}
read_models:
- {id: portfolio-overview, flow_bindings: [{flow_node_ref: uf-orient-portfolio, access: displays}]}
- {id: selected-path-detail, flow_bindings: [{flow_node_ref: uf-verify-selected-path, access: displays}]}
- {id: evidence-inspector, flow_bindings: [{flow_node_ref: uf-inspect-source-provenance, access: displays}]}
- {id: provenance-timeline, flow_bindings: [{flow_node_ref: uf-inspect-source-provenance, access: displays}]}
- {id: diagnostics-panel, flow_bindings: [{flow_node_ref: uf-recover-diagnostics, access: displays}]}
- {id: handoff-summary, flow_bindings: [{flow_node_ref: uf-handoff-resume, access: displays}, {flow_node_ref: uf-explain-boundaries, access: displays}]}
policies:
- {id: source-truth-policy, flow_bindings: [{flow_node_ref: uf-verify-selected-path, access: reads}, {flow_node_ref: uf-inspect-source-provenance, access: reads}]}
- {id: active-path-resolution-policy, flow_bindings: [{flow_node_ref: uf-orient-portfolio, access: reads}, {flow_node_ref: uf-recover-diagnostics, access: transitions}]}
- {id: diagnostic-severity-policy, flow_bindings: [{flow_node_ref: uf-recover-diagnostics, access: transitions}]}
- {id: handoff-eligibility-policy, flow_bindings: [{flow_node_ref: uf-handoff-resume, access: displays}, {flow_node_ref: uf-explain-boundaries, access: displays}]}
- {id: boundary-preservation-policy, flow_bindings: [{flow_node_ref: uf-explain-boundaries, access: displays}]}
contracts:
- id: scan-portfolio-contract
kind: command
request_shape: {repository_context: RepositoryContextInput, include_inactive: boolean, include_diagnostics: boolean, source_refs: ArtifactRef[]}
response_shape: {scan_state: string, repository_ref: ArtifactRef, portfolio_snapshot_id: string, source_health: TrustEnvelope, path_counts: object, active_path_refs: PortfolioPathRef[], excluded_path_refs: PortfolioPathRef[], unresolved_path_refs: PortfolioPathRef[], diagnostics: DiagnosticRef[]}
error_shape: [no-afps-state, progress-manifest-missing, progress-manifest-malformed, permission-denied, scan-partial, source-unreadable]
flow_bindings: [{flow_node_ref: uf-orient-portfolio, access: triggers}]
- id: get-selected-path-detail-contract
kind: query
request_shape: {selector: ProductPathSelector, include_claims: boolean, include_refs: boolean, include_diagnostics: boolean}
response_shape: {path_id: string, label: string, scope_path: ArtifactRef, source_status: PathState, path_state: PathState, pipeline_stage: string, reason: string, next_skill: string, trust: TrustEnvelope, claims: SourceBackedClaim[], diagnostics: DiagnosticRef[], handoff_eligibility: HandoffEligibility}
error_shape: [path-not-selected, path-not-found, source-artifact-missing, path-detail-partial, path-detail-blocked, path-state-contradicted]
flow_bindings: [{flow_node_ref: uf-verify-selected-path, access: reads}]
- id: inspect-evidence-ref-contract
kind: query
request_shape: {claim_ref: ClaimRef, evidence_ref: EvidenceRef, path_id: string, source_hint: string, preview_requested: boolean}
response_shape: {claim_id: string, evidence_link_id: string, resolved_ref: ArtifactRef, support_status: string, trust: TrustEnvelope, diagnostics: DiagnosticRef[]}
error_shape: [claim-not-found, evidence-ref-missing, evidence-ref-unresolved, source-preview-unavailable, evidence-inaccessible, claim-contradicted]
flow_bindings: [{flow_node_ref: uf-inspect-source-provenance, access: displays}]
- id: inspect-provenance-contract
kind: query
request_shape: {path_id: string, claim_ref: ClaimRef, artifact_ref: ArtifactRef, include_archives: boolean, include_review_records: boolean}
response_shape: {records: ProvenanceRecord[], approval_state: string, confirmed_records: ProvenanceRecord[], review_only_records: ProvenanceRecord[], archive_refs: ArtifactRef[], confidence: SourceConfidence, warnings: string[], diagnostics: DiagnosticRef[]}
error_shape: [provenance-missing, provenance-review-only, provenance-contradicted, archive-ref-missing, canonical-target-unreadable]
flow_bindings: [{flow_node_ref: uf-inspect-source-provenance, access: displays}]
- id: evaluate-diagnostics-contract
kind: command
request_shape: {repository_ref: ArtifactRef, path_id: string, claim_refs: ClaimRef[], artifact_refs: ArtifactRef[], evaluation_reason: string, prior_diagnostic_refs: DiagnosticRef[]}
response_shape: {diagnostics: DiagnosticRef[], trust_changes: object[], handoff_eligibility: HandoffEligibility, affected_read_models: string[], manual_checks: string[], warnings_to_preserve: string[], blocked_reasons: string[]}
error_shape: [diagnostic-source-missing, diagnostic-scope-ambiguous, cannot-classify-issue, source-review-required]
flow_bindings: [{flow_node_ref: uf-recover-diagnostics, access: writes}]
- id: generate-handoff-contract
kind: command
request_shape: {selector: ProductPathSelector, handoff_intent: string, detail_level: string, include_refs: boolean, include_diagnostics: boolean}
response_shape: {summary_id: string, handoff_type: string, handoff_state: string, path_id: string, next_skill: string, branch_state_explanation: string, confidence: TrustEnvelope, evidence_refs: EvidenceRef[], provenance_refs: ProvenanceRecord[], warnings: string[], blocked_reasons: string[], boundary: HandoffBoundary, copy_allowed: boolean, normal_next_command_suppressed: boolean}
error_shape: [handoff-unavailable, blocking-diagnostics-present, next-skill-unsupported, boundary-explanation-required, source-support-insufficient, out-of-scope-request]
flow_bindings: [{flow_node_ref: uf-handoff-resume, access: triggers}, {flow_node_ref: uf-explain-boundaries, access: triggers}]
- id: copy-handoff-contract
kind: command
request_shape: {summary_id: string, copy_intent: string, acknowledged_warnings: string[], requested_format: string}
response_shape: {copy_state: string, summary_id: string, warnings_preserved: string[], suppression_reason: string, copied_payload_shape: string, diagnostic_refs: DiagnosticRef[], boundary: HandoffBoundary}
error_shape: [summary-not-found, warnings-not-preserved, copy-blocked-by-diagnostics, next-command-suppressed, copy-format-unsupported]
flow_bindings: [{flow_node_ref: uf-handoff-resume, access: writes}]
- id: explain-boundary-contract
kind: query
request_shape: {selector: ProductPathSelector, boundary_kind: BoundaryKind, requested_by: string, include_refs: boolean}
response_shape: {path_id: string, boundary_kind: BoundaryKind, source_status: PathState, branch_state_explanation: string, normal_route_suppressed: boolean, suppression_reason: string, promoted_boundary: boolean, handoff_boundary: HandoffBoundary, evidence_refs: EvidenceRef[], provenance_refs: ProvenanceRecord[], warnings: string[], diagnostics: DiagnosticRef[], next_step_visibility: string}
error_shape: [boundary-not-applicable, boundary-source-missing, promoted-boundary-unsupported, out-of-scope-request, inactive-state-contradicted]
flow_bindings: [{flow_node_ref: uf-explain-boundaries, access: reads}]
Flow Bindings
| Flow node | Primary read model | Core elements | Trust behavior |
|---|---|---|---|
uf-orient-portfolio | Portfolio Overview | RepositoryContext, PortfolioSnapshot, PortfolioPathRef, ProductPath, DiagnosticIssue | Shows active, parallel, inactive, excluded, unresolved, partial, warning, and blocked states. |
uf-verify-selected-path | Selected Path Detail | ProductPath, SourceArtifact, SourceBackedClaim, EvidenceLink, ProvenanceRecord | Separates source-backed, inferred, partial, unsupported, contradicted, and blocked claims. |
uf-inspect-source-provenance | Evidence Inspector and Provenance Timeline | EvidenceLink, SourceArtifact, SourceBackedClaim, ProvenanceRecord | Preserves claim IDs, support status, parser confidence, source confidence, and provenance caveats. |
uf-recover-diagnostics | Diagnostics Panel | DiagnosticIssue, TrustLevel, HandoffEligibility, affected refs/claims/paths | Degrades trust at narrowest scope and names handoff impact. |
uf-handoff-resume | Handoff Summary | HandoffSummary, ProductPath, SourceBackedClaim, EvidenceLink, ProvenanceRecord, DiagnosticIssue | Clean copy only when source-backed; warning copy preserves caveats; blocked copy names suppression reasons. |
uf-explain-boundaries | Boundary Explanation | ProductPath, BoundaryKind, HandoffSummary, diagnostics, evidence/provenance refs | Suppresses normal routing for inactive, promoted, out-of-scope, unresolved, unsupported, or contradicted states. |
Visual Model
Logical ERD
| Source | Relationship | Target |
|---|---|---|
| RepositoryContext | one to zero-or-one | PortfolioSnapshot |
| PortfolioSnapshot | one to many | PortfolioPathRef and ProductPath |
| ProductPath | one to many | SourceArtifact, SourceBackedClaim, ProvenanceRecord, DiagnosticIssue, HandoffSummary |
| SourceBackedClaim | one to many | EvidenceLink and DiagnosticIssue |
Product Path Lifecycle
| Transition | Trigger | UI state |
|---|---|---|
| undiscovered to discovered | ProductPathRecordDiscovered | Portfolio row |
| discovered to selected | ProductPathSelected | Detail loading frame |
| source-inventorying to source-backed/warning/blocked | Claim support and diagnostics | Clean, warning, or blocked detail |
| discovered to inactive/promoted/out-of-scope | Boundary policy | Explanation instead of normal routing |
Proposed File Changes After Approval
| Path | Change | Approval dependency |
|---|---|---|
design/afps-tracker/domain-model-afps-tracker.md | New canonical domain model Markdown from the proposed content above. | Domain model approval gate. |
design/afps-tracker/model-tree-afps-tracker.yaml | New canonical model-tree manifest from the proposed YAML above. | Model-tree approval gate. |
design/afps-tracker/flow-tree-afps-tracker.yaml | Add model_tree_ref and attach branches[].model_ref to the six covered flow branches. Do not touch route or duplicate flow_bindings. | Flow binding approval gate. |
research/afps-tracker/glossary.md | Append only glossary terms approved in the glossary gate. | Glossary gate. |
docs/history/archive/YYYY-MM-DD/HHMMSS/... | Archive the brief and framework intermediates at canonical write time. | Final approval. |
alignment/state-model-afps-tracker.html | Convert this page from review to confirmed after approved YAML is consumed and canonical artifacts are written. | Final approval. |
Approval Gates
Domain Model Approval
Approve the proposed logical domain model Markdown?
Model Tree Manifest Approval
Approve the proposed model-tree YAML shape and flow bindings?
Flow Binding Approval
Approve attaching this model to all six covered first-read-through branches and writing the optional top-level model_tree_ref pointer?
Glossary Additions Gate
Choose whether to append the proposed model terms to the AFPS Tracker glossary.
Compile Responses
Use this after selecting gate answers. Partial feedback is allowed; approval becomes ready only when every required gate is answered without modification or clarification requests.