{
  "package": {
    "name": "Repair Handoff Kit — LIGHT Draft",
    "kind": "hybrid",
    "oneLiner": "A proposed local job board, numbered PLA tags and staff checklist for three synthetic repair jobs.",
    "problemSpace": {
      "who": "Staff in a fictional repair shop.",
      "pain": "Job state, physical markers and pickup confirmation can disagree.",
      "context": "Teaching specification only. No application implementation exists; no deployment, fabrication or executed tests are claimed. Supplied failure scenarios are not observed operational failures.",
      "evidenceNodeIds": [
        "repair-question",
        "repair-samples",
        "repair-kit"
      ]
    },
    "solutionIdea": {
      "summary": "Keep one fixed job/token mapping, require explicit staff actions and current revisions, and stop handoffs whenever the record, item or marker is uncertain.",
      "differentiators": [
        "A numbered token locates a job; it never authenticates a customer.",
        "Physical reconciliation gates digital advancement.",
        "Corrections preserve history until proposed retention deletion; retirement prevents later resurrection."
      ],
      "nonGoals": [
        "Payments, customer messaging or customer-facing portals.",
        "Real personal data, production authentication or privacy assurances.",
        "Automated repair decisions, machine controls or repair-safety guarantees.",
        "Deployment, replacement-token issuance or additional synthetic jobs."
      ]
    },
    "concept": {
      "userJourney": [
        "Observation: J101/token101 is a desk lamp at intake awaiting diagnosis; J102/token102 is a radio in repair assigned to R2; J103/token103 is a kettle ready for staff-confirmed pickup.",
        "Design choice: Staff initialize the fixture set once, then compare each current record with its item and tag.",
        "Design choice: Staff request and confirm each allowed transition; conflicts stop advancement and handoff.",
        "Design choice: Before collection, staff follow the shop verification process outside this demo and explicitly confirm handoff.",
        "Design choice: Proposed retention retires eligible fixtures permanently rather than making them available for reseeding.",
        "Untested assumption: Staff can account for the item and tag at each required physical check."
      ],
      "successCriteria": [
        "Proposed checks reject duplicate IDs, invalid reversal references, stale actions and unconfirmed collection without mutation.",
        "Proposed scenarios stop swapped-marker and missing-marker handoffs.",
        "Proposed correction and restore checks preserve valid retained history and require appropriate staff reconciliation.",
        "Proposed deletion checks prevent expired fixtures from returning through initialization or older snapshots.",
        "No success, demand, deletion assurance or usability outcome is claimed."
      ]
    },
    "data": {
      "entities": [
        {
          "name": "Job",
          "fields": [
            "jobId: J101 | J102 | J103; unique while retained",
            "tokenId: token101 | token102 | token103; unique while retained; immutable canonical pair",
            "itemType: fixed desk lamp | radio | kettle",
            "state: intake | diagnosis | repair | ready | collected",
            "revision: increasing integer; never below durable per-fixture high-water mark",
            "markerStatus: unchecked | matched | missing | swapped | mismatch",
            "hold: boolean",
            "assignedStaffCode: R2 for J102; null otherwise",
            "collectedAt: local demo timestamp or null; corrections preserve prior/result values"
          ],
          "source": "repair-samples supplies starting records; other fields are proposed controls grounded in repair-kit."
        },
        {
          "name": "ActionLog",
          "fields": [
            "actionId: unique action-<sequence>; allocated atomically from the durable global actionSequenceHighWater; never reused",
            "jobId: canonical ID of an existing retained Job",
            "action: transition | correction | hold | reconciliation",
            "priorState",
            "resultState",
            "priorRevision",
            "resultRevision",
            "priorCollectedAt: timestamp or null",
            "resultCollectedAt: timestamp or null",
            "reasonCode: fixed enumeration",
            "reversesActionId: nullable; required for correction and correction undo; otherwise null",
            "Reference constraint: target must exist in the retained ActionLog, belong to the same job, have a lower action sequence "
          ],
          "source": "Proposed history contract for repair-samples failure scenarios; no personal details or free text."
        },
        {
          "name": "LifecycleGuard",
          "fields": [
            "fixturesInitialized: durable one-time latch",
            "actionSequenceHighWater: durable global maximum allocated action sequence",
            "fixtures: exactly J101, J102 and J103, each with retired boolean and revisionHighWater",
            "Contains no item description, staff code, state history, collection timestamp, confirmation flags or action payload",
            "Updated atomically with corresponding record writes or retirement; never rolled back or replaced by snapshot restore",
            "Retained for the lifetime of this demo lineage, including after all Job and ActionLog rows are deleted; missing or incon"
          ],
          "source": "Proposed minimal non-personal initialization, ID-allocation and retirement metadata closing the repair-kit retention/backup contract."
        },
        {
          "name": "LocalSnapshot",
          "fields": [
            "schemaVersion",
            "snapshotCreatedAt",
            "jobs: retained rows only",
            "actionLog: complete retained histories and reference targets for included jobs",
            "guardAtSnapshot: consistency and high-water evidence only; never authority to replace or lower the live LifecycleGuard",
            "Managed snapshot policy also covers temporary and pre-restore copies"
          ],
          "source": "Proposed local backup structure grounded in repair-kit."
        }
      ],
      "sources": [
        {
          "nodeId": "repair-question",
          "use": "Human-controlled lifecycle and exclusions."
        },
        {
          "nodeId": "repair-samples",
          "use": "Fixed synthetic starting records and failure scenarios."
        },
        {
          "nodeId": "repair-kit",
          "use": "Local board, physical marker, checklist and data boundaries."
        }
      ]
    },
    "architecture": {
      "overview": "Proposed React/TypeScript UI and Node.js local API backed by SQLite. Bind to loopback only; this is a demonstration boundary, not staff authentication. The API owns mappings, atomic revision/reference checks, one-time initialization, retirement and guarded restore. The durable LifecycleGuard is excluded from snapshot rollback.",
      "components": [
        {
          "name": "Web job board",
          "responsibility": "Show retained jobs, confirmations, holds, correction history and proposed backup/retention controls.",
          "technology": "React and TypeScript"
        },
        {
          "name": "Local record service",
          "responsibility": "Validate fixed IDs, allocate non-reused action IDs, perform atomic guarded writes and manage retirement and local snapshots.",
          "technology": "Node.js, TypeScript and SQLite"
        },
        {
          "name": "Numbered tags",
          "responsibility": "Locate the corresponding synthetic item without asserting identity.",
          "technology": "Proposed flat PLA tags with printed number labels"
        },
        {
          "name": "Handoff checklist",
          "responsibility": "Define physical reconciliation, transition confirmation and recovery steps.",
          "technology": "Markdown checklist displayed alongside the board"
        }
      ],
      "interfaces": [
        {
          "from": "Staff UI",
          "to": "Local record service",
          "protocol": "Loopback HTTP JSON",
          "purpose": "Mutations submit jobId, expectedRevision, action and required confirmations; corrections also submit reversesActionId. Invalid or stale requests change neither records, logs nor guard."
        },
        {
          "from": "Local record service",
          "to": "SQLite",
          "protocol": "SQL transaction",
          "purpose": "Enforce unique IDs, fixed mappings, same-job earlier-action references and atomic job/log/guard updates."
        },
        {
          "from": "Physical tag",
          "to": "Staff checklist",
          "protocol": "Manual visual comparison",
          "purpose": "Label 101 means token101/J101; 102 means token102/J102; 103 means token103/J103. Retirement never remaps a tag."
        },
        {
          "from": "Staff checklist",
          "to": "Local record service",
          "protocol": "Explicit staff-confirmed UI action",
          "purpose": "Apply the canonical transition and recovery rules only after required checks."
        }
      ],
      "deployment": "Future local demonstration only. No application implementation exists and no deployment is claimed. Planning artifacts are not evidence of implemented controls."
    },
    "modules": [
      {
        "id": "m1",
        "name": "Web job board",
        "purpose": "Own fixed records, guarded transitions, valid history and local data lifecycle.",
        "dependsOn": []
      },
      {
        "id": "m2",
        "name": "Physical marker",
        "purpose": "Specify three flat numbered tags and fixed visual matching.",
        "dependsOn": [
          "m1"
        ]
      },
      {
        "id": "m3",
        "name": "Staff handoff workflow",
        "purpose": "Own transition confirmations, physical recovery and pickup boundaries.",
        "dependsOn": [
          "m1",
          "m2"
        ]
      }
    ],
    "waves": [
      {
        "title": "Wave 1 — Record contract",
        "goal": "Implement the proposed local board, guards and data lifecycle against synthetic fixtures.",
        "moduleIds": [
          "m1"
        ],
        "mode": "sequential"
      },
      {
        "title": "Wave 2 — Physical and service integration",
        "goal": "Specify the tags, then integrate the checklist and proposed scenario checks.",
        "moduleIds": [
          "m2",
          "m3"
        ],
        "mode": "sequential"
      }
    ],
    "prds": [
      {
        "moduleId": "m1",
        "stories": [
          {
            "id": "S1",
            "title": "Load and locate the three canonical jobs",
            "acceptance": [
              "Initialize exactly J101/token101/intake, J102/token102/repair/R2 and J103/token103/ready once under R1.",
              "Reject duplicate jobId, duplicate tokenId and noncanonical pairs without mutation.",
              "After initialization, missing rows are not automatically seeded; retired fixtures remain absent.",
              "Accept only the fixed schema; reject personal-data fields and free-text fields."
            ]
          },
          {
            "id": "S2",
            "title": "Apply guarded actions and manage local copies",
            "acceptance": [
              "Each accepted job action atomically increments revision, allocates a unique actionId and appends valid history; invalid references and stale submissions change nothing.",
              "Transition, correction, deletion, backup and restore follow R2, R5 and R6.",
              "Show the proposed policy: deletion removes job/log content but retains minimal guard metadata; an older backup cannot revive a retired or expired fixture.",
              "Restore distinguishes active/held, collected-not-expired and retired fixtures; it does not require three Job rows."
            ]
          }
        ]
      },
      {
        "moduleId": "m2",
        "stories": [
          {
            "id": "S3",
            "title": "Specify the numbered flat tags",
            "acceptance": [
              "Specify three PLA bodies, each 40 × 25 × 3 mm, flat and without holes.",
              "Assign printed labels 101, 102 and 103 to the three bodies.",
              "Describe dimensions as proposed nominal geometry; claim no fabrication, measured mass or durability result."
            ]
          },
          {
            "id": "S4",
            "title": "Match each physical tag to its job",
            "acceptance": [
              "Display J101/token101/101, J102/token102/102 and J103/token103/103 in the checklist.",
              "Require staff comparison of the current retained record, tag and synthetic item before advancement.",
              "Mark a missing, swapped or conflicting tag as held; provide no mapping edit or replacement-token action.",
              "A tag for a retired fixture does not authorize reinitialization, reassignment or another handoff."
            ]
          }
        ]
      },
      {
        "moduleId": "m3",
        "stories": [
          {
            "id": "S5",
            "title": "Confirm each lifecycle handoff",
            "acceptance": [
              "Use only the canonical transition table in R2; offer no direct jump to collected.",
              "For J103 collection, require ready state, current revision, matching item/tag, external-verification acknowledgement and separate pickup confirmation.",
              "State beside pickup controls that the token is a locator, not authentication."
            ]
          },
          {
            "id": "S6",
            "title": "Recover discrepancies without hiding them",
            "acceptance": [
              "Hold both affected jobs for swapped tags; hold the affected job for a missing tag.",
              "Require current-revision staff reconciliation before releasing a hold.",
              "Reverse accidental collection only when staff confirms the item did not leave; otherwise retain the hold for external resolution.",
              "Corrections reference an existing eligible earlier action for the same retained job; retirement ends correction availability."
            ]
          }
        ]
      }
    ],
    "bom": [
      {
        "part": "Flat PLA tag body",
        "quantity": 3,
        "specification": "One per synthetic job; nominal 40 × 25 × 3 mm solid rectangular body; no holes.",
        "estimatedCost": "Not supplied",
        "supplierHint": "Unspecified"
      },
      {
        "part": "Printed number label",
        "quantity": 3,
        "specification": "One label each numbered 101, 102 and 103; placed within the tag face. Stock, dimensions and adhesive unresolved.",
        "estimatedCost": "Not supplied",
        "supplierHint": "Unspecified"
      }
    ],
    "designSystem": {
      "principles": [
        "Show jobId, tokenId, state and revision together for retained jobs.",
        "Use text for holds, retirement and errors; do not rely on color.",
        "Separate select, review and confirm steps.",
        "Keep the demo-only and token-not-authentication notices visible."
      ],
      "tone": "Short, explicit staff instructions.",
      "colors": [
        "Neutral background",
        "Dark text",
        "Amber plus text for holds"
      ],
      "typography": "System sans-serif; monospace job and token identifiers."
    },
    "agentConcurrency": {
      "maxParallelBuilders": 1,
      "sharedFiles": [
        "src/domain.ts",
        "db/schema.sql",
        "docs/handoff.md"
      ],
      "rules": [
        "Paths are proposed implementation coordination paths, not claims of application implementation.",
        "Complete Wave 1 before Wave 2; within Wave 2 build M2 before M3.",
        "Keep mapping, transitions, reference validation and retention/restore contracts centralized.",
        "Add no canvas cards, jobs or token IDs."
      ]
    },
    "controlsAndTests": [
      {
        "area": "Scope and initialization",
        "check": "Initialize three fixtures once; reject duplicate initialization and never reseed a missing or retired row.",
        "method": "Proposed fixture tests covering first initialization, repeated startup, partial data loss, retirement and missing guard."
      },
      {
        "area": "Duplicate and concurrent writes",
        "check": "Job/token/action IDs are unique; only one action using the same revision succeeds; committed action IDs are never reused.",
        "method": "Proposed transaction tests comparing records, logs and guard before and after concurrent or rejected requests."
      },
      {
        "area": "Reversal references",
        "check": "Only existing eligible earlier same-job targets succeed atomically; self, cross-job, nonexistent, future and ineligible targets fail.",
        "method": "Proposed reference-validation tests, including correction/undo, concurrent retirement, incomplete snapshot chains and ID"
      },
      {
        "area": "State machine",
        "check": "Only adjacent confirmed transitions succeed; cancellation and absent confirmation produce no mutation.",
        "method": "Proposed table-driven tests across all five states and correction guards."
      },
      {
        "area": "Marker recovery",
        "check": "Swapping token101 and token102 holds both jobs; removing token102 blocks its handoff.",
        "method": "Proposed tabletop walkthrough; restore original placement and explicitly reconcile before release."
      },
      {
        "area": "Pickup and correction",
        "check": "Token103 alone cannot collect J103; uncertain item whereabouts prevents reversal; correction undo does not renew the original collection age.",
        "method": "Proposed UI scenarios for omitted confirmation, stale views, erroneous collection and correction/undo timestamps."
      },
      {
        "area": "Retention and managed copies",
        "check": "At the proposed 30-day boundary, unheld collected jobs retire; active and held jobs remain. Complete job histories are deleted together, guard metadata remains, and affected managed snapshots are removed.",
        "method": "Proposed before/at/after-boundary and interrupted-cleanup scenarios, including pre-restore copies, hold release and a no"
      },
      {
        "area": "Restore",
        "check": "Retired or expired fixtures never return; missing rows are not seeded; valid retained histories keep their IDs and references; new revisions and action IDs exceed both histories and durable high-water marks.",
        "method": "Proposed snapshot scenarios for active/held jobs, unexpired collection, retirement, older active snapshots after expiry,"
      },
      {
        "area": "Physical prototype",
        "check": "Check nominal 40 × 25 × 3 mm body, absence of holes, label legibility and attachment.",
        "method": "Proposed dimensional inspection and handling review after a prototype exists; no tolerance or pass result is supplied."
      }
    ],
    "dependencies": [
      {
        "name": "React and TypeScript",
        "kind": "library",
        "reason": "Proposed local staff interface and typed domain contract."
      },
      {
        "name": "Node.js",
        "kind": "library",
        "reason": "Proposed local API runtime."
      },
      {
        "name": "SQLite",
        "kind": "library",
        "reason": "Local transactional storage, uniqueness and reference constraints."
      },
      {
        "name": "PLA bodies and printed labels",
        "kind": "hardware",
        "reason": "Proposed physical locators."
      },
      {
        "name": "Three supplied synthetic records",
        "kind": "data",
        "reason": "Exclusive demonstration dataset."
      }
    ],
    "risks": [
      {
        "risk": "Possession of a numbered tag is mistaken for identity proof.",
        "mitigation": "Require external shop verification and separate staff confirmation; display the locator-only warning."
      },
      {
        "risk": "Invalid or reused action IDs make corrections ambiguous or leave dangling references.",
        "mitigation": "Use durable monotonic allocation, atomic same-job earlier-target validation, complete retained histories and rejection of conflicting snapshot IDs. Delete a retiring job's history as a unit."
      },
      {
        "risk": "An older snapshot or startup seed resurrects a deleted or expired fixture.",
        "mitigation": "Keep the initialization latch, retirement flags and high-water marks outside restore rollback. Check current eligibility before restore; require the latest guarded revision when recovering a missing row; never reseed."
      },
      {
        "risk": "The durable guard is lost or rolled back with the data.",
        "mitigation": "Fail closed on initialization and restore rather than infer freshness from an old backup. Whole-store loss recovery remains unresolved; this is not a tamper-resistance claim."
      },
      {
        "risk": "A restored record disagrees with physical reality.",
        "mitigation": "Freeze actions, preserve eligible current data, compare histories and require category-specific staff reconciliation. Restore does not silently replace newer state or bypass R5."
      },
      {
        "risk": "Cleanup is interrupted, copied snapshots remain, or the demo clock gives an incorrect age.",
        "mitigation": "Retirement blocks reimport even if cleanup is incomplete; report pending managed-copy cleanup. Unmanaged copies, clock reliability and deletion assurance remain unvalidated."
      },
      {
        "risk": "A lost tag cannot be safely replaced under the fixed-ID scope.",
        "mitigation": "Keep the job held until the original is recovered and reconciled; leave replacement policy unresolved."
      },
      {
        "risk": "PLA or label performance is unsuitable.",
        "mitigation": "Treat material, attachment, cleaning and handling suitability as untested prototype questions."
      }
    ],
    "openQuestions": [
      "Prototype: What dimensional tolerance and handling criteria should govern a later physical review?",
      "Material: What PLA grade, label stock, label dimensions and attachment method are suitable?",
      "Physical data: Tag mass is unknown; no measured or calculated mass is claimed.",
      "Recovery: How would a production shop invalidate and replace a permanently lost marker?",
      "Privacy: Are the proposed 30-day content policy and lifetime non-personal guard metadata appropriate? Neither is validated.",
      "Backup: How should guard loss, whole-store loss and protection against rollback be handled beyond this fail-closed demo contract?",
      "Deletion: How would production systems address unmanaged copies, interrupted cleanup and deletion assurance?",
      "Time: What clock and timestamp controls would make retention age dependable outside the demo?"
    ],
    "geometry": {
      "parts": [
        {
          "id": "g1",
          "name": "Flat numbered tag body",
          "moduleId": "m2",
          "bomPart": "Flat PLA tag body",
          "kind": "mechanical",
          "description": "Three identical proposed bodies; labels distinguish 101, 102 and 103. Not a counter stand.",
          "dimensionsMm": {
            "x": 40,
            "y": 25,
            "z": 3
          },
          "material": "PLA; grade unresolved",
          "massG": 0,
          "features": [
            "Solid rectangular body",
            "Flat faces",
            "No holes",
            "Printed number label applied separately",
            "Mass is unknown; massG zero is not a measured or calculated mass"
          ],
          "tool": "openscad"
        }
      ]
    },
    "evidenceNodeIds": [
      "repair-question",
      "repair-samples",
      "repair-kit"
    ],
    "specRevision": 1,
    "requirements": [
      {
        "id": "R1",
        "text": "S1: Enforce the canonical synthetic record boundary and one-time fixture initialization.",
        "acceptance": [
          "In a deliberately new demo lineage, staff initialize the complete fixture set once: J101/token101/desk lamp/intake, J102/token102/radio/repair/R2 and J103/token103/kettle/ready. Intake means recorded and awaiting diagnosis.",
          "Account for the starting markers; atomically create the three records and set the durable fixturesInitialized latch. Fixture initialization is not evidence of prior staff lifecycle actions.",
          "Enforce unique jobId and tokenId plus immutable canonical pair validation in storage and requests; reject other IDs, personal-data fields and free text.",
          "Reject repeated initialization without mutation. After the latch is set, missing rows require R6 recovery or represent retirement; absence never authorizes seeding.",
          "Do not clear the latch or retirement flags to restart these fixtures. Missing or inconsistent guard metadata blocks initialization and restore rather than treating the store as new."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "The durable guard remains available throughout the demo lineage; no reset/reseed feature is provided."
        ],
        "unresolved": [
          "Recovery after loss of the guard is outside this light draft."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R2",
        "text": "S2 and S5: Use one staff-controlled transition table with atomic revision and action-reference guards.",
        "acceptance": [
          "Initialization is the one-time operation in R1, not an ordinary intake/re-entry transition.",
          "Start diagnosis: intake to diagnosis. Start repair: diagnosis to repair. Mark ready: repair to ready. Each requires current revision, matched item/tag, no hold and explicit staff confirmation; preserve J102's R2 assignment.",
          "Confirm collection: ready to collected requires all preceding guards plus external-verification acknowledgement and separate pickup confirmation. Set collectedAt; collected has no normal outgoing transition.",
          "Reject stale revisions, skipped states, missing confirmation, unresolved markers and retired IDs without mutation.",
          "Each accepted job action atomically allocates a globally unique actionId above the durable action-sequence high-water mark, increments job revision, updates guard high-water marks and appends prior/result values.",
          "For every non-null reversesActionId, atomically require an existing same-job target with lower action sequence and earlier resultRevision, plus R5 eligibility. Reject self, cross-job, nonexistent or ineligible references without allocating a committed ID or changing records.",
          "Corrections are separate actions under R5. Retention retirement under R6 is not a lifecycle transition and leaves no job content behind as an audit log."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-question",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "The linear lifecycle and durable sequence allocator are proposed teaching design choices."
        ],
        "unresolved": [],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R3",
        "text": "S3 and S4: Specify fixed physical locators and block unresolved marker discrepancies.",
        "acceptance": [
          "Specify three flat PLA tag bodies at exactly 40 × 25 × 3 mm nominal geometry, no holes, with printed number labels 101, 102 and 103.",
          "Match labels to J101/token101, J102/token102 and J103/token103; never edit these mappings.",
          "A swap holds both affected retained jobs until staff restores original placement and confirms each item/tag match.",
          "A missing marker holds its job until the original marker is recovered and reconciled; issue no replacement in this demo.",
          "Retirement does not change the physical label or authorize another job. No tag reassignment or fixture resurrection is provided."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "Exact tag geometry is a supplied design constraint, not a measured observation."
        ],
        "unresolved": [
          "Prototype tolerance, mass, material suitability and label specification."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R4",
        "text": "S5: Keep pickup explicitly human-owned and outside token-based authentication.",
        "acceptance": [
          "Display that a numbered token is a locator, not customer authentication.",
          "Require staff to acknowledge following the shop verification process outside this demo before confirming collection.",
          "Presenting token103, selecting collected or cancelling confirmation must not alone change J103 from ready.",
          "Store only fixed confirmation flags; capture no identity details or verification free text."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-question",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "An acknowledgement is a workflow control, not proof that verification occurred."
        ],
        "unresolved": [
          "The external shop verification process is deliberately unspecified."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R5",
        "text": "S2 and S6: Make retained-history corrections explicit, validly referenced and physically reconciled.",
        "acceptance": [
          "Hold disputed retained jobs; require current revision, fixed reason code and staff item/tag reconciliation for correction.",
          "Correct the latest erroneous lifecycle transition to its logged prior state: diagnosis to intake, repair to diagnosis, ready to repair, or collected to ready. Intervening hold/reconciliation entries do not authorize reversal of an older lifecycle transition.",
          "Collected to ready additionally requires confirmation that the item did not leave. If it left or whereabouts are uncertain, retain the hold and do not reverse state.",
          "Append a correction with its own unique actionId and reversesActionId targeting the eligible transition. Undo only the latest correction, referencing that correction's actionId, using current revision and applicable destination guards, including fresh pickup confirmation for collected.",
          "Validate target existence, earlier order, same job and eligibility atomically with revision checks and the new log entry. Never replace a target entry or silently overwrite history.",
          "Record prior/result collectedAt. A collection reversal clears the current timestamp but retains it in history; undo restores that timestamp rather than restarting the retention period.",
          "Retain complete reference chains while the job exists. Retirement deletes all of that job's logs together; no corrections or reference targets remain available for that retired job."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "A status correction does not reverse physical work or recover an item."
        ],
        "unresolved": [
          "Items already handed to the wrong person require resolution outside this demo."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R6",
        "text": "S2: Use a proposed retention, snapshot and restore contract that cannot reinitialize or restore retired fixtures.",
        "acceptance": [
          "Proposed policy: staff-run cleanup retires a collected, unheld job once at least 30 days have elapsed since collectedAt. Active jobs and held jobs remain; a hold preserves the original collection timestamp. Releasing a hold on an already-due collected job requires retirement in that staff operation, not a renewed retention period.",
          "Before snapshot or restore, staff run the same eligibility check. An already-due unheld collected record must be retired before proceeding; an older active snapshot cannot override this outcome.",
          "Retirement atomically marks the fixture retired and deletes its Job row and complete ActionLog history. Retain only the LifecycleGuard: initialization latch, three canonical IDs with retirement flags and revision high-water marks, and global action-sequence high-water mark. This metadata is distinct from deleted job/log content and is retained for the demo lineage.",
          "No action ID is reused after deletion. No surviving action may reference a retired job's logs. Static canonical mapping documentation and physical tags remain, but do not recreate operational records.",
          "Create a consistent managed local snapshot at staff session end after cleanup. Remove managed snapshots older than 30 days and every managed snapshot containing content for a newly retired fixture, regardless of snapshot age. This includes pre-restore and temporary copies; do not rewrite them into selectively incomplete action histories.",
          "If managed-copy cleanup is interrupted, report it as pending and retry before creating another snapshot. Retirement flags still block import. No claim covers secure erasure, unmanaged copies or deletion assurance.",
          "Before restore, freeze mutations, complete due retirement and managed-copy cleanup, and preserve an eligible pre-restore copy. Validate schema, canonical mappings and snapshot guard consistency. The live durable guard is never replaced, lowered or inferred from an older snapshot; missing or inconsistent guard blocks restore.",
          "Classify each canonical fixture using the live guard and current data. Retired: require no Job row, reject its content from import, and remove any managed candidate containing it. Active or held: require retained current data or a recoverable snapshot row, staff item/tag reconciliation and preservation of holds until explicit release. Collected but not expired: reconcile recorded handoff and original collectedAt with staff; do not require return of the collected item or reset its age.",
          "For a missing non-retired current row, accept recovery only from a complete candidate whose job revision equals the live guard's latest revisionHighWater. An older candidate cannot establish current state or collection age and must be rejected. Evaluate the recovered latest state for expiry before materializing it: retire an expired unheld collected fixture instead; retain a held fixture.",
          "For existing current rows, require consistency with the live guard. Compare candidate and current histories; require an explicit staff decision for discrepancies. Keep newer current state rather than silently replacing it with older state; lifecycle rollback requires R5, not snapshot selection. Preserve original collection age and do not clear a hold through restore.",
          "For retained jobs, preserve current history and valid candidate history without renumbering action IDs. Identical IDs must have identical content or restore fails. Require complete same-job earlier-action reference chains; reject dangling, cross-job, self or conflicting references. Reject candidate sequences or revisions inconsistent with the live guard.",
          "At atomic restore commit, assign each retained job a revision above its current, candidate and guard high-water values. Append a fresh reconciliation action with an ID above both histories and the durable global high-water mark, update the guard and require UI reload. Retired fixtures stay absent and receive no new job/log content."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "Thirty days, staff-run cleanup, session-end snapshots and lifetime guard retention are proposed demo policies, not validated requirements.",
          "The demo clock and durable guard are available and consistent; the design claims no resistance to external store rollback.",
          "A backup older than a missing row's latest guarded revision may be unusable; safety against stale resurrection takes precedence over recovery availability."
        ],
        "unresolved": [
          "Production retention approval, clock reliability, guard protection, whole-store recovery, unmanaged copies and deletion assurance."
        ],
        "reviewState": "needs-review",
        "revision": 1
      }
    ]
  },
  "recordedBasis": {
    "contract": "recorded-package-basis",
    "version": 1,
    "scope": {
      "canvas": "my",
      "revision": 1
    },
    "materials": [
      {
        "reference": {
          "nodeId": "repair-question",
          "contentRevision": 1
        },
        "title": "Keep the job and the handoff together",
        "kind": "question",
        "attribution": "",
        "evidenceStatus": "unassessed"
      },
      {
        "reference": {
          "nodeId": "repair-samples",
          "contentRevision": 1
        },
        "title": "Three synthetic jobs and failure cases",
        "kind": "observation",
        "attribution": "",
        "evidenceStatus": "unassessed"
      },
      {
        "reference": {
          "nodeId": "repair-kit",
          "contentRevision": 1
        },
        "title": "Three parts, one human-owned record",
        "kind": "idea",
        "attribution": "",
        "evidenceStatus": "unassessed"
      }
    ],
    "concepts": [],
    "humanDecisionRecords": [],
    "qualification": "No linked decision is inferred; review the retained records before treating this draft as a commitment."
  },
  "frozenSpecification": {
    "contract": "frozen-specification-export",
    "contractVersion": 1,
    "authority": "export-only",
    "identity": {
      "packageId": "package:cookbook-repair-shop",
      "investigationId": "cookbook-repair-shop",
      "specRevision": 1,
      "specificationDigest": "cc845ed7b8271207783d439f0d64d233f24743af3beabaa4e8eb7ccb1e983a24",
      "created": "2026-10-01T20:05:35.146Z"
    },
    "state": "needs-review",
    "approval": null,
    "package": {
      "name": "Repair Handoff Kit — LIGHT Draft",
      "kind": "hybrid",
      "oneLiner": "A proposed local job board, numbered PLA tags and staff checklist for three synthetic repair jobs.",
      "problemSpace": {
        "who": "Staff in a fictional repair shop.",
        "pain": "Job state, physical markers and pickup confirmation can disagree.",
        "context": "Teaching specification only. No application implementation exists; no deployment, fabrication or executed tests are claimed. Supplied failure scenarios are not observed operational failures.",
        "evidenceNodeIds": [
          "repair-question",
          "repair-samples",
          "repair-kit"
        ]
      },
      "solutionIdea": {
        "summary": "Keep one fixed job/token mapping, require explicit staff actions and current revisions, and stop handoffs whenever the record, item or marker is uncertain.",
        "differentiators": [
          "A numbered token locates a job; it never authenticates a customer.",
          "Physical reconciliation gates digital advancement.",
          "Corrections preserve history until proposed retention deletion; retirement prevents later resurrection."
        ],
        "nonGoals": [
          "Payments, customer messaging or customer-facing portals.",
          "Real personal data, production authentication or privacy assurances.",
          "Automated repair decisions, machine controls or repair-safety guarantees.",
          "Deployment, replacement-token issuance or additional synthetic jobs."
        ]
      },
      "concept": {
        "userJourney": [
          "Observation: J101/token101 is a desk lamp at intake awaiting diagnosis; J102/token102 is a radio in repair assigned to R2; J103/token103 is a kettle ready for staff-confirmed pickup.",
          "Design choice: Staff initialize the fixture set once, then compare each current record with its item and tag.",
          "Design choice: Staff request and confirm each allowed transition; conflicts stop advancement and handoff.",
          "Design choice: Before collection, staff follow the shop verification process outside this demo and explicitly confirm handoff.",
          "Design choice: Proposed retention retires eligible fixtures permanently rather than making them available for reseeding.",
          "Untested assumption: Staff can account for the item and tag at each required physical check."
        ],
        "successCriteria": [
          "Proposed checks reject duplicate IDs, invalid reversal references, stale actions and unconfirmed collection without mutation.",
          "Proposed scenarios stop swapped-marker and missing-marker handoffs.",
          "Proposed correction and restore checks preserve valid retained history and require appropriate staff reconciliation.",
          "Proposed deletion checks prevent expired fixtures from returning through initialization or older snapshots.",
          "No success, demand, deletion assurance or usability outcome is claimed."
        ]
      },
      "data": {
        "entities": [
          {
            "name": "Job",
            "fields": [
              "jobId: J101 | J102 | J103; unique while retained",
              "tokenId: token101 | token102 | token103; unique while retained; immutable canonical pair",
              "itemType: fixed desk lamp | radio | kettle",
              "state: intake | diagnosis | repair | ready | collected",
              "revision: increasing integer; never below durable per-fixture high-water mark",
              "markerStatus: unchecked | matched | missing | swapped | mismatch",
              "hold: boolean",
              "assignedStaffCode: R2 for J102; null otherwise",
              "collectedAt: local demo timestamp or null; corrections preserve prior/result values"
            ],
            "source": "repair-samples supplies starting records; other fields are proposed controls grounded in repair-kit."
          },
          {
            "name": "ActionLog",
            "fields": [
              "actionId: unique action-<sequence>; allocated atomically from the durable global actionSequenceHighWater; never reused",
              "jobId: canonical ID of an existing retained Job",
              "action: transition | correction | hold | reconciliation",
              "priorState",
              "resultState",
              "priorRevision",
              "resultRevision",
              "priorCollectedAt: timestamp or null",
              "resultCollectedAt: timestamp or null",
              "reasonCode: fixed enumeration",
              "reversesActionId: nullable; required for correction and correction undo; otherwise null",
              "Reference constraint: target must exist in the retained ActionLog, belong to the same job, have a lower action sequence"
            ],
            "source": "Proposed history contract for repair-samples failure scenarios; no personal details or free text."
          },
          {
            "name": "LifecycleGuard",
            "fields": [
              "fixturesInitialized: durable one-time latch",
              "actionSequenceHighWater: durable global maximum allocated action sequence",
              "fixtures: exactly J101, J102 and J103, each with retired boolean and revisionHighWater",
              "Contains no item description, staff code, state history, collection timestamp, confirmation flags or action payload",
              "Updated atomically with corresponding record writes or retirement; never rolled back or replaced by snapshot restore",
              "Retained for the lifetime of this demo lineage, including after all Job and ActionLog rows are deleted; missing or incon"
            ],
            "source": "Proposed minimal non-personal initialization, ID-allocation and retirement metadata closing the repair-kit retention/backup contract."
          },
          {
            "name": "LocalSnapshot",
            "fields": [
              "schemaVersion",
              "snapshotCreatedAt",
              "jobs: retained rows only",
              "actionLog: complete retained histories and reference targets for included jobs",
              "guardAtSnapshot: consistency and high-water evidence only; never authority to replace or lower the live LifecycleGuard",
              "Managed snapshot policy also covers temporary and pre-restore copies"
            ],
            "source": "Proposed local backup structure grounded in repair-kit."
          }
        ],
        "sources": [
          {
            "nodeId": "repair-question",
            "use": "Human-controlled lifecycle and exclusions."
          },
          {
            "nodeId": "repair-samples",
            "use": "Fixed synthetic starting records and failure scenarios."
          },
          {
            "nodeId": "repair-kit",
            "use": "Local board, physical marker, checklist and data boundaries."
          }
        ]
      },
      "architecture": {
        "overview": "Proposed React/TypeScript UI and Node.js local API backed by SQLite. Bind to loopback only; this is a demonstration boundary, not staff authentication. The API owns mappings, atomic revision/reference checks, one-time initialization, retirement and guarded restore. The durable LifecycleGuard is excluded from snapshot rollback.",
        "components": [
          {
            "name": "Web job board",
            "responsibility": "Show retained jobs, confirmations, holds, correction history and proposed backup/retention controls.",
            "technology": "React and TypeScript"
          },
          {
            "name": "Local record service",
            "responsibility": "Validate fixed IDs, allocate non-reused action IDs, perform atomic guarded writes and manage retirement and local snapshots.",
            "technology": "Node.js, TypeScript and SQLite"
          },
          {
            "name": "Numbered tags",
            "responsibility": "Locate the corresponding synthetic item without asserting identity.",
            "technology": "Proposed flat PLA tags with printed number labels"
          },
          {
            "name": "Handoff checklist",
            "responsibility": "Define physical reconciliation, transition confirmation and recovery steps.",
            "technology": "Markdown checklist displayed alongside the board"
          }
        ],
        "interfaces": [
          {
            "from": "Staff UI",
            "to": "Local record service",
            "protocol": "Loopback HTTP JSON",
            "purpose": "Mutations submit jobId, expectedRevision, action and required confirmations; corrections also submit reversesActionId. Invalid or stale requests change neither records, logs nor guard."
          },
          {
            "from": "Local record service",
            "to": "SQLite",
            "protocol": "SQL transaction",
            "purpose": "Enforce unique IDs, fixed mappings, same-job earlier-action references and atomic job/log/guard updates."
          },
          {
            "from": "Physical tag",
            "to": "Staff checklist",
            "protocol": "Manual visual comparison",
            "purpose": "Label 101 means token101/J101; 102 means token102/J102; 103 means token103/J103. Retirement never remaps a tag."
          },
          {
            "from": "Staff checklist",
            "to": "Local record service",
            "protocol": "Explicit staff-confirmed UI action",
            "purpose": "Apply the canonical transition and recovery rules only after required checks."
          }
        ],
        "deployment": "Future local demonstration only. No application implementation exists and no deployment is claimed. Planning artifacts are not evidence of implemented controls."
      },
      "modules": [
        {
          "id": "m1",
          "name": "Web job board",
          "purpose": "Own fixed records, guarded transitions, valid history and local data lifecycle.",
          "dependsOn": []
        },
        {
          "id": "m2",
          "name": "Physical marker",
          "purpose": "Specify three flat numbered tags and fixed visual matching.",
          "dependsOn": [
            "m1"
          ]
        },
        {
          "id": "m3",
          "name": "Staff handoff workflow",
          "purpose": "Own transition confirmations, physical recovery and pickup boundaries.",
          "dependsOn": [
            "m1",
            "m2"
          ]
        }
      ],
      "waves": [
        {
          "title": "Wave 1 — Record contract",
          "goal": "Implement the proposed local board, guards and data lifecycle against synthetic fixtures.",
          "moduleIds": [
            "m1"
          ],
          "mode": "sequential"
        },
        {
          "title": "Wave 2 — Physical and service integration",
          "goal": "Specify the tags, then integrate the checklist and proposed scenario checks.",
          "moduleIds": [
            "m2",
            "m3"
          ],
          "mode": "sequential"
        }
      ],
      "prds": [
        {
          "moduleId": "m1",
          "stories": [
            {
              "id": "S1",
              "title": "Load and locate the three canonical jobs",
              "acceptance": [
                "Initialize exactly J101/token101/intake, J102/token102/repair/R2 and J103/token103/ready once under R1.",
                "Reject duplicate jobId, duplicate tokenId and noncanonical pairs without mutation.",
                "After initialization, missing rows are not automatically seeded; retired fixtures remain absent.",
                "Accept only the fixed schema; reject personal-data fields and free-text fields."
              ]
            },
            {
              "id": "S2",
              "title": "Apply guarded actions and manage local copies",
              "acceptance": [
                "Each accepted job action atomically increments revision, allocates a unique actionId and appends valid history; invalid references and stale submissions change nothing.",
                "Transition, correction, deletion, backup and restore follow R2, R5 and R6.",
                "Show the proposed policy: deletion removes job/log content but retains minimal guard metadata; an older backup cannot revive a retired or expired fixture.",
                "Restore distinguishes active/held, collected-not-expired and retired fixtures; it does not require three Job rows."
              ]
            }
          ]
        },
        {
          "moduleId": "m2",
          "stories": [
            {
              "id": "S3",
              "title": "Specify the numbered flat tags",
              "acceptance": [
                "Specify three PLA bodies, each 40 × 25 × 3 mm, flat and without holes.",
                "Assign printed labels 101, 102 and 103 to the three bodies.",
                "Describe dimensions as proposed nominal geometry; claim no fabrication, measured mass or durability result."
              ]
            },
            {
              "id": "S4",
              "title": "Match each physical tag to its job",
              "acceptance": [
                "Display J101/token101/101, J102/token102/102 and J103/token103/103 in the checklist.",
                "Require staff comparison of the current retained record, tag and synthetic item before advancement.",
                "Mark a missing, swapped or conflicting tag as held; provide no mapping edit or replacement-token action.",
                "A tag for a retired fixture does not authorize reinitialization, reassignment or another handoff."
              ]
            }
          ]
        },
        {
          "moduleId": "m3",
          "stories": [
            {
              "id": "S5",
              "title": "Confirm each lifecycle handoff",
              "acceptance": [
                "Use only the canonical transition table in R2; offer no direct jump to collected.",
                "For J103 collection, require ready state, current revision, matching item/tag, external-verification acknowledgement and separate pickup confirmation.",
                "State beside pickup controls that the token is a locator, not authentication."
              ]
            },
            {
              "id": "S6",
              "title": "Recover discrepancies without hiding them",
              "acceptance": [
                "Hold both affected jobs for swapped tags; hold the affected job for a missing tag.",
                "Require current-revision staff reconciliation before releasing a hold.",
                "Reverse accidental collection only when staff confirms the item did not leave; otherwise retain the hold for external resolution.",
                "Corrections reference an existing eligible earlier action for the same retained job; retirement ends correction availability."
              ]
            }
          ]
        }
      ],
      "bom": [
        {
          "part": "Flat PLA tag body",
          "quantity": 3,
          "specification": "One per synthetic job; nominal 40 × 25 × 3 mm solid rectangular body; no holes.",
          "estimatedCost": "Not supplied",
          "supplierHint": "Unspecified"
        },
        {
          "part": "Printed number label",
          "quantity": 3,
          "specification": "One label each numbered 101, 102 and 103; placed within the tag face. Stock, dimensions and adhesive unresolved.",
          "estimatedCost": "Not supplied",
          "supplierHint": "Unspecified"
        }
      ],
      "designSystem": {
        "principles": [
          "Show jobId, tokenId, state and revision together for retained jobs.",
          "Use text for holds, retirement and errors; do not rely on color.",
          "Separate select, review and confirm steps.",
          "Keep the demo-only and token-not-authentication notices visible."
        ],
        "tone": "Short, explicit staff instructions.",
        "colors": [
          "Neutral background",
          "Dark text",
          "Amber plus text for holds"
        ],
        "typography": "System sans-serif; monospace job and token identifiers."
      },
      "agentConcurrency": {
        "maxParallelBuilders": 1,
        "sharedFiles": [
          "src/domain.ts",
          "db/schema.sql",
          "docs/handoff.md"
        ],
        "rules": [
          "Paths are proposed implementation coordination paths, not claims of application implementation.",
          "Complete Wave 1 before Wave 2; within Wave 2 build M2 before M3.",
          "Keep mapping, transitions, reference validation and retention/restore contracts centralized.",
          "Add no canvas cards, jobs or token IDs."
        ]
      },
      "controlsAndTests": [
        {
          "area": "Scope and initialization",
          "check": "Initialize three fixtures once; reject duplicate initialization and never reseed a missing or retired row.",
          "method": "Proposed fixture tests covering first initialization, repeated startup, partial data loss, retirement and missing guard."
        },
        {
          "area": "Duplicate and concurrent writes",
          "check": "Job/token/action IDs are unique; only one action using the same revision succeeds; committed action IDs are never reused.",
          "method": "Proposed transaction tests comparing records, logs and guard before and after concurrent or rejected requests."
        },
        {
          "area": "Reversal references",
          "check": "Only existing eligible earlier same-job targets succeed atomically; self, cross-job, nonexistent, future and ineligible targets fail.",
          "method": "Proposed reference-validation tests, including correction/undo, concurrent retirement, incomplete snapshot chains and ID"
        },
        {
          "area": "State machine",
          "check": "Only adjacent confirmed transitions succeed; cancellation and absent confirmation produce no mutation.",
          "method": "Proposed table-driven tests across all five states and correction guards."
        },
        {
          "area": "Marker recovery",
          "check": "Swapping token101 and token102 holds both jobs; removing token102 blocks its handoff.",
          "method": "Proposed tabletop walkthrough; restore original placement and explicitly reconcile before release."
        },
        {
          "area": "Pickup and correction",
          "check": "Token103 alone cannot collect J103; uncertain item whereabouts prevents reversal; correction undo does not renew the original collection age.",
          "method": "Proposed UI scenarios for omitted confirmation, stale views, erroneous collection and correction/undo timestamps."
        },
        {
          "area": "Retention and managed copies",
          "check": "At the proposed 30-day boundary, unheld collected jobs retire; active and held jobs remain. Complete job histories are deleted together, guard metadata remains, and affected managed snapshots are removed.",
          "method": "Proposed before/at/after-boundary and interrupted-cleanup scenarios, including pre-restore copies, hold release and a no"
        },
        {
          "area": "Restore",
          "check": "Retired or expired fixtures never return; missing rows are not seeded; valid retained histories keep their IDs and references; new revisions and action IDs exceed both histories and durable high-water marks.",
          "method": "Proposed snapshot scenarios for active/held jobs, unexpired collection, retirement, older active snapshots after expiry,"
        },
        {
          "area": "Physical prototype",
          "check": "Check nominal 40 × 25 × 3 mm body, absence of holes, label legibility and attachment.",
          "method": "Proposed dimensional inspection and handling review after a prototype exists; no tolerance or pass result is supplied."
        }
      ],
      "dependencies": [
        {
          "name": "React and TypeScript",
          "kind": "library",
          "reason": "Proposed local staff interface and typed domain contract."
        },
        {
          "name": "Node.js",
          "kind": "library",
          "reason": "Proposed local API runtime."
        },
        {
          "name": "SQLite",
          "kind": "library",
          "reason": "Local transactional storage, uniqueness and reference constraints."
        },
        {
          "name": "PLA bodies and printed labels",
          "kind": "hardware",
          "reason": "Proposed physical locators."
        },
        {
          "name": "Three supplied synthetic records",
          "kind": "data",
          "reason": "Exclusive demonstration dataset."
        }
      ],
      "risks": [
        {
          "risk": "Possession of a numbered tag is mistaken for identity proof.",
          "mitigation": "Require external shop verification and separate staff confirmation; display the locator-only warning."
        },
        {
          "risk": "Invalid or reused action IDs make corrections ambiguous or leave dangling references.",
          "mitigation": "Use durable monotonic allocation, atomic same-job earlier-target validation, complete retained histories and rejection of conflicting snapshot IDs. Delete a retiring job's history as a unit."
        },
        {
          "risk": "An older snapshot or startup seed resurrects a deleted or expired fixture.",
          "mitigation": "Keep the initialization latch, retirement flags and high-water marks outside restore rollback. Check current eligibility before restore; require the latest guarded revision when recovering a missing row; never reseed."
        },
        {
          "risk": "The durable guard is lost or rolled back with the data.",
          "mitigation": "Fail closed on initialization and restore rather than infer freshness from an old backup. Whole-store loss recovery remains unresolved; this is not a tamper-resistance claim."
        },
        {
          "risk": "A restored record disagrees with physical reality.",
          "mitigation": "Freeze actions, preserve eligible current data, compare histories and require category-specific staff reconciliation. Restore does not silently replace newer state or bypass R5."
        },
        {
          "risk": "Cleanup is interrupted, copied snapshots remain, or the demo clock gives an incorrect age.",
          "mitigation": "Retirement blocks reimport even if cleanup is incomplete; report pending managed-copy cleanup. Unmanaged copies, clock reliability and deletion assurance remain unvalidated."
        },
        {
          "risk": "A lost tag cannot be safely replaced under the fixed-ID scope.",
          "mitigation": "Keep the job held until the original is recovered and reconciled; leave replacement policy unresolved."
        },
        {
          "risk": "PLA or label performance is unsuitable.",
          "mitigation": "Treat material, attachment, cleaning and handling suitability as untested prototype questions."
        }
      ],
      "openQuestions": [
        "Prototype: What dimensional tolerance and handling criteria should govern a later physical review?",
        "Material: What PLA grade, label stock, label dimensions and attachment method are suitable?",
        "Physical data: Tag mass is unknown; no measured or calculated mass is claimed.",
        "Recovery: How would a production shop invalidate and replace a permanently lost marker?",
        "Privacy: Are the proposed 30-day content policy and lifetime non-personal guard metadata appropriate? Neither is validated.",
        "Backup: How should guard loss, whole-store loss and protection against rollback be handled beyond this fail-closed demo contract?",
        "Deletion: How would production systems address unmanaged copies, interrupted cleanup and deletion assurance?",
        "Time: What clock and timestamp controls would make retention age dependable outside the demo?"
      ],
      "geometry": {
        "parts": [
          {
            "id": "g1",
            "name": "Flat numbered tag body",
            "moduleId": "m2",
            "bomPart": "Flat PLA tag body",
            "kind": "mechanical",
            "description": "Three identical proposed bodies; labels distinguish 101, 102 and 103. Not a counter stand.",
            "dimensionsMm": {
              "x": 40,
              "y": 25,
              "z": 3
            },
            "material": "PLA; grade unresolved",
            "massG": 0,
            "features": [
              "Solid rectangular body",
              "Flat faces",
              "No holes",
              "Printed number label applied separately",
              "Mass is unknown; massG zero is not a measured or calculated mass"
            ],
            "tool": "openscad"
          }
        ]
      },
      "evidenceNodeIds": [
        "repair-question",
        "repair-samples",
        "repair-kit"
      ],
      "specRevision": 1,
      "requirements": [
        {
          "id": "R1",
          "text": "S1: Enforce the canonical synthetic record boundary and one-time fixture initialization.",
          "acceptance": [
            "In a deliberately new demo lineage, staff initialize the complete fixture set once: J101/token101/desk lamp/intake, J102/token102/radio/repair/R2 and J103/token103/kettle/ready. Intake means recorded and awaiting diagnosis.",
            "Account for the starting markers; atomically create the three records and set the durable fixturesInitialized latch. Fixture initialization is not evidence of prior staff lifecycle actions.",
            "Enforce unique jobId and tokenId plus immutable canonical pair validation in storage and requests; reject other IDs, personal-data fields and free text.",
            "Reject repeated initialization without mutation. After the latch is set, missing rows require R6 recovery or represent retirement; absence never authorizes seeding.",
            "Do not clear the latch or retirement flags to restart these fixtures. Missing or inconsistent guard metadata blocks initialization and restore rather than treating the store as new."
          ],
          "decisionRefs": [],
          "evidenceVersionRefs": [
            {
              "canvas": "my",
              "nodeId": "repair-samples",
              "contentRevision": 1
            },
            {
              "canvas": "my",
              "nodeId": "repair-kit",
              "contentRevision": 1
            }
          ],
          "assumptions": [
            "The durable guard remains available throughout the demo lineage; no reset/reseed feature is provided."
          ],
          "unresolved": [
            "Recovery after loss of the guard is outside this light draft."
          ],
          "reviewState": "needs-review",
          "revision": 1
        },
        {
          "id": "R2",
          "text": "S2 and S5: Use one staff-controlled transition table with atomic revision and action-reference guards.",
          "acceptance": [
            "Initialization is the one-time operation in R1, not an ordinary intake/re-entry transition.",
            "Start diagnosis: intake to diagnosis. Start repair: diagnosis to repair. Mark ready: repair to ready. Each requires current revision, matched item/tag, no hold and explicit staff confirmation; preserve J102's R2 assignment.",
            "Confirm collection: ready to collected requires all preceding guards plus external-verification acknowledgement and separate pickup confirmation. Set collectedAt; collected has no normal outgoing transition.",
            "Reject stale revisions, skipped states, missing confirmation, unresolved markers and retired IDs without mutation.",
            "Each accepted job action atomically allocates a globally unique actionId above the durable action-sequence high-water mark, increments job revision, updates guard high-water marks and appends prior/result values.",
            "For every non-null reversesActionId, atomically require an existing same-job target with lower action sequence and earlier resultRevision, plus R5 eligibility. Reject self, cross-job, nonexistent or ineligible references without allocating a committed ID or changing records.",
            "Corrections are separate actions under R5. Retention retirement under R6 is not a lifecycle transition and leaves no job content behind as an audit log."
          ],
          "decisionRefs": [],
          "evidenceVersionRefs": [
            {
              "canvas": "my",
              "nodeId": "repair-question",
              "contentRevision": 1
            },
            {
              "canvas": "my",
              "nodeId": "repair-samples",
              "contentRevision": 1
            }
          ],
          "assumptions": [
            "The linear lifecycle and durable sequence allocator are proposed teaching design choices."
          ],
          "unresolved": [],
          "reviewState": "needs-review",
          "revision": 1
        },
        {
          "id": "R3",
          "text": "S3 and S4: Specify fixed physical locators and block unresolved marker discrepancies.",
          "acceptance": [
            "Specify three flat PLA tag bodies at exactly 40 × 25 × 3 mm nominal geometry, no holes, with printed number labels 101, 102 and 103.",
            "Match labels to J101/token101, J102/token102 and J103/token103; never edit these mappings.",
            "A swap holds both affected retained jobs until staff restores original placement and confirms each item/tag match.",
            "A missing marker holds its job until the original marker is recovered and reconciled; issue no replacement in this demo.",
            "Retirement does not change the physical label or authorize another job. No tag reassignment or fixture resurrection is provided."
          ],
          "decisionRefs": [],
          "evidenceVersionRefs": [
            {
              "canvas": "my",
              "nodeId": "repair-samples",
              "contentRevision": 1
            },
            {
              "canvas": "my",
              "nodeId": "repair-kit",
              "contentRevision": 1
            }
          ],
          "assumptions": [
            "Exact tag geometry is a supplied design constraint, not a measured observation."
          ],
          "unresolved": [
            "Prototype tolerance, mass, material suitability and label specification."
          ],
          "reviewState": "needs-review",
          "revision": 1
        },
        {
          "id": "R4",
          "text": "S5: Keep pickup explicitly human-owned and outside token-based authentication.",
          "acceptance": [
            "Display that a numbered token is a locator, not customer authentication.",
            "Require staff to acknowledge following the shop verification process outside this demo before confirming collection.",
            "Presenting token103, selecting collected or cancelling confirmation must not alone change J103 from ready.",
            "Store only fixed confirmation flags; capture no identity details or verification free text."
          ],
          "decisionRefs": [],
          "evidenceVersionRefs": [
            {
              "canvas": "my",
              "nodeId": "repair-question",
              "contentRevision": 1
            },
            {
              "canvas": "my",
              "nodeId": "repair-kit",
              "contentRevision": 1
            }
          ],
          "assumptions": [
            "An acknowledgement is a workflow control, not proof that verification occurred."
          ],
          "unresolved": [
            "The external shop verification process is deliberately unspecified."
          ],
          "reviewState": "needs-review",
          "revision": 1
        },
        {
          "id": "R5",
          "text": "S2 and S6: Make retained-history corrections explicit, validly referenced and physically reconciled.",
          "acceptance": [
            "Hold disputed retained jobs; require current revision, fixed reason code and staff item/tag reconciliation for correction.",
            "Correct the latest erroneous lifecycle transition to its logged prior state: diagnosis to intake, repair to diagnosis, ready to repair, or collected to ready. Intervening hold/reconciliation entries do not authorize reversal of an older lifecycle transition.",
            "Collected to ready additionally requires confirmation that the item did not leave. If it left or whereabouts are uncertain, retain the hold and do not reverse state.",
            "Append a correction with its own unique actionId and reversesActionId targeting the eligible transition. Undo only the latest correction, referencing that correction's actionId, using current revision and applicable destination guards, including fresh pickup confirmation for collected.",
            "Validate target existence, earlier order, same job and eligibility atomically with revision checks and the new log entry. Never replace a target entry or silently overwrite history.",
            "Record prior/result collectedAt. A collection reversal clears the current timestamp but retains it in history; undo restores that timestamp rather than restarting the retention period.",
            "Retain complete reference chains while the job exists. Retirement deletes all of that job's logs together; no corrections or reference targets remain available for that retired job."
          ],
          "decisionRefs": [],
          "evidenceVersionRefs": [
            {
              "canvas": "my",
              "nodeId": "repair-samples",
              "contentRevision": 1
            },
            {
              "canvas": "my",
              "nodeId": "repair-kit",
              "contentRevision": 1
            }
          ],
          "assumptions": [
            "A status correction does not reverse physical work or recover an item."
          ],
          "unresolved": [
            "Items already handed to the wrong person require resolution outside this demo."
          ],
          "reviewState": "needs-review",
          "revision": 1
        },
        {
          "id": "R6",
          "text": "S2: Use a proposed retention, snapshot and restore contract that cannot reinitialize or restore retired fixtures.",
          "acceptance": [
            "Proposed policy: staff-run cleanup retires a collected, unheld job once at least 30 days have elapsed since collectedAt. Active jobs and held jobs remain; a hold preserves the original collection timestamp. Releasing a hold on an already-due collected job requires retirement in that staff operation, not a renewed retention period.",
            "Before snapshot or restore, staff run the same eligibility check. An already-due unheld collected record must be retired before proceeding; an older active snapshot cannot override this outcome.",
            "Retirement atomically marks the fixture retired and deletes its Job row and complete ActionLog history. Retain only the LifecycleGuard: initialization latch, three canonical IDs with retirement flags and revision high-water marks, and global action-sequence high-water mark. This metadata is distinct from deleted job/log content and is retained for the demo lineage.",
            "No action ID is reused after deletion. No surviving action may reference a retired job's logs. Static canonical mapping documentation and physical tags remain, but do not recreate operational records.",
            "Create a consistent managed local snapshot at staff session end after cleanup. Remove managed snapshots older than 30 days and every managed snapshot containing content for a newly retired fixture, regardless of snapshot age. This includes pre-restore and temporary copies; do not rewrite them into selectively incomplete action histories.",
            "If managed-copy cleanup is interrupted, report it as pending and retry before creating another snapshot. Retirement flags still block import. No claim covers secure erasure, unmanaged copies or deletion assurance.",
            "Before restore, freeze mutations, complete due retirement and managed-copy cleanup, and preserve an eligible pre-restore copy. Validate schema, canonical mappings and snapshot guard consistency. The live durable guard is never replaced, lowered or inferred from an older snapshot; missing or inconsistent guard blocks restore.",
            "Classify each canonical fixture using the live guard and current data. Retired: require no Job row, reject its content from import, and remove any managed candidate containing it. Active or held: require retained current data or a recoverable snapshot row, staff item/tag reconciliation and preservation of holds until explicit release. Collected but not expired: reconcile recorded handoff and original collectedAt with staff; do not require return of the collected item or reset its age.",
            "For a missing non-retired current row, accept recovery only from a complete candidate whose job revision equals the live guard's latest revisionHighWater. An older candidate cannot establish current state or collection age and must be rejected. Evaluate the recovered latest state for expiry before materializing it: retire an expired unheld collected fixture instead; retain a held fixture.",
            "For existing current rows, require consistency with the live guard. Compare candidate and current histories; require an explicit staff decision for discrepancies. Keep newer current state rather than silently replacing it with older state; lifecycle rollback requires R5, not snapshot selection. Preserve original collection age and do not clear a hold through restore.",
            "For retained jobs, preserve current history and valid candidate history without renumbering action IDs. Identical IDs must have identical content or restore fails. Require complete same-job earlier-action reference chains; reject dangling, cross-job, self or conflicting references. Reject candidate sequences or revisions inconsistent with the live guard.",
            "At atomic restore commit, assign each retained job a revision above its current, candidate and guard high-water values. Append a fresh reconciliation action with an ID above both histories and the durable global high-water mark, update the guard and require UI reload. Retired fixtures stay absent and receive no new job/log content."
          ],
          "decisionRefs": [],
          "evidenceVersionRefs": [
            {
              "canvas": "my",
              "nodeId": "repair-kit",
              "contentRevision": 1
            }
          ],
          "assumptions": [
            "Thirty days, staff-run cleanup, session-end snapshots and lifetime guard retention are proposed demo policies, not validated requirements.",
            "The demo clock and durable guard are available and consistent; the design claims no resistance to external store rollback.",
            "A backup older than a missing row's latest guarded revision may be unusable; safety against stale resurrection takes precedence over recovery availability."
          ],
          "unresolved": [
            "Production retention approval, clock reliability, guard protection, whole-store recovery, unmanaged copies and deletion assurance."
          ],
          "reviewState": "needs-review",
          "revision": 1
        }
      ]
    },
    "requirements": [
      {
        "id": "R1",
        "text": "S1: Enforce the canonical synthetic record boundary and one-time fixture initialization.",
        "acceptance": [
          "In a deliberately new demo lineage, staff initialize the complete fixture set once: J101/token101/desk lamp/intake, J102/token102/radio/repair/R2 and J103/token103/kettle/ready. Intake means recorded and awaiting diagnosis.",
          "Account for the starting markers; atomically create the three records and set the durable fixturesInitialized latch. Fixture initialization is not evidence of prior staff lifecycle actions.",
          "Enforce unique jobId and tokenId plus immutable canonical pair validation in storage and requests; reject other IDs, personal-data fields and free text.",
          "Reject repeated initialization without mutation. After the latch is set, missing rows require R6 recovery or represent retirement; absence never authorizes seeding.",
          "Do not clear the latch or retirement flags to restart these fixtures. Missing or inconsistent guard metadata blocks initialization and restore rather than treating the store as new."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "The durable guard remains available throughout the demo lineage; no reset/reseed feature is provided."
        ],
        "unresolved": [
          "Recovery after loss of the guard is outside this light draft."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R2",
        "text": "S2 and S5: Use one staff-controlled transition table with atomic revision and action-reference guards.",
        "acceptance": [
          "Initialization is the one-time operation in R1, not an ordinary intake/re-entry transition.",
          "Start diagnosis: intake to diagnosis. Start repair: diagnosis to repair. Mark ready: repair to ready. Each requires current revision, matched item/tag, no hold and explicit staff confirmation; preserve J102's R2 assignment.",
          "Confirm collection: ready to collected requires all preceding guards plus external-verification acknowledgement and separate pickup confirmation. Set collectedAt; collected has no normal outgoing transition.",
          "Reject stale revisions, skipped states, missing confirmation, unresolved markers and retired IDs without mutation.",
          "Each accepted job action atomically allocates a globally unique actionId above the durable action-sequence high-water mark, increments job revision, updates guard high-water marks and appends prior/result values.",
          "For every non-null reversesActionId, atomically require an existing same-job target with lower action sequence and earlier resultRevision, plus R5 eligibility. Reject self, cross-job, nonexistent or ineligible references without allocating a committed ID or changing records.",
          "Corrections are separate actions under R5. Retention retirement under R6 is not a lifecycle transition and leaves no job content behind as an audit log."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-question",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "The linear lifecycle and durable sequence allocator are proposed teaching design choices."
        ],
        "unresolved": [],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R3",
        "text": "S3 and S4: Specify fixed physical locators and block unresolved marker discrepancies.",
        "acceptance": [
          "Specify three flat PLA tag bodies at exactly 40 × 25 × 3 mm nominal geometry, no holes, with printed number labels 101, 102 and 103.",
          "Match labels to J101/token101, J102/token102 and J103/token103; never edit these mappings.",
          "A swap holds both affected retained jobs until staff restores original placement and confirms each item/tag match.",
          "A missing marker holds its job until the original marker is recovered and reconciled; issue no replacement in this demo.",
          "Retirement does not change the physical label or authorize another job. No tag reassignment or fixture resurrection is provided."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "Exact tag geometry is a supplied design constraint, not a measured observation."
        ],
        "unresolved": [
          "Prototype tolerance, mass, material suitability and label specification."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R4",
        "text": "S5: Keep pickup explicitly human-owned and outside token-based authentication.",
        "acceptance": [
          "Display that a numbered token is a locator, not customer authentication.",
          "Require staff to acknowledge following the shop verification process outside this demo before confirming collection.",
          "Presenting token103, selecting collected or cancelling confirmation must not alone change J103 from ready.",
          "Store only fixed confirmation flags; capture no identity details or verification free text."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-question",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "An acknowledgement is a workflow control, not proof that verification occurred."
        ],
        "unresolved": [
          "The external shop verification process is deliberately unspecified."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R5",
        "text": "S2 and S6: Make retained-history corrections explicit, validly referenced and physically reconciled.",
        "acceptance": [
          "Hold disputed retained jobs; require current revision, fixed reason code and staff item/tag reconciliation for correction.",
          "Correct the latest erroneous lifecycle transition to its logged prior state: diagnosis to intake, repair to diagnosis, ready to repair, or collected to ready. Intervening hold/reconciliation entries do not authorize reversal of an older lifecycle transition.",
          "Collected to ready additionally requires confirmation that the item did not leave. If it left or whereabouts are uncertain, retain the hold and do not reverse state.",
          "Append a correction with its own unique actionId and reversesActionId targeting the eligible transition. Undo only the latest correction, referencing that correction's actionId, using current revision and applicable destination guards, including fresh pickup confirmation for collected.",
          "Validate target existence, earlier order, same job and eligibility atomically with revision checks and the new log entry. Never replace a target entry or silently overwrite history.",
          "Record prior/result collectedAt. A collection reversal clears the current timestamp but retains it in history; undo restores that timestamp rather than restarting the retention period.",
          "Retain complete reference chains while the job exists. Retirement deletes all of that job's logs together; no corrections or reference targets remain available for that retired job."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          },
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "A status correction does not reverse physical work or recover an item."
        ],
        "unresolved": [
          "Items already handed to the wrong person require resolution outside this demo."
        ],
        "reviewState": "needs-review",
        "revision": 1
      },
      {
        "id": "R6",
        "text": "S2: Use a proposed retention, snapshot and restore contract that cannot reinitialize or restore retired fixtures.",
        "acceptance": [
          "Proposed policy: staff-run cleanup retires a collected, unheld job once at least 30 days have elapsed since collectedAt. Active jobs and held jobs remain; a hold preserves the original collection timestamp. Releasing a hold on an already-due collected job requires retirement in that staff operation, not a renewed retention period.",
          "Before snapshot or restore, staff run the same eligibility check. An already-due unheld collected record must be retired before proceeding; an older active snapshot cannot override this outcome.",
          "Retirement atomically marks the fixture retired and deletes its Job row and complete ActionLog history. Retain only the LifecycleGuard: initialization latch, three canonical IDs with retirement flags and revision high-water marks, and global action-sequence high-water mark. This metadata is distinct from deleted job/log content and is retained for the demo lineage.",
          "No action ID is reused after deletion. No surviving action may reference a retired job's logs. Static canonical mapping documentation and physical tags remain, but do not recreate operational records.",
          "Create a consistent managed local snapshot at staff session end after cleanup. Remove managed snapshots older than 30 days and every managed snapshot containing content for a newly retired fixture, regardless of snapshot age. This includes pre-restore and temporary copies; do not rewrite them into selectively incomplete action histories.",
          "If managed-copy cleanup is interrupted, report it as pending and retry before creating another snapshot. Retirement flags still block import. No claim covers secure erasure, unmanaged copies or deletion assurance.",
          "Before restore, freeze mutations, complete due retirement and managed-copy cleanup, and preserve an eligible pre-restore copy. Validate schema, canonical mappings and snapshot guard consistency. The live durable guard is never replaced, lowered or inferred from an older snapshot; missing or inconsistent guard blocks restore.",
          "Classify each canonical fixture using the live guard and current data. Retired: require no Job row, reject its content from import, and remove any managed candidate containing it. Active or held: require retained current data or a recoverable snapshot row, staff item/tag reconciliation and preservation of holds until explicit release. Collected but not expired: reconcile recorded handoff and original collectedAt with staff; do not require return of the collected item or reset its age.",
          "For a missing non-retired current row, accept recovery only from a complete candidate whose job revision equals the live guard's latest revisionHighWater. An older candidate cannot establish current state or collection age and must be rejected. Evaluate the recovered latest state for expiry before materializing it: retire an expired unheld collected fixture instead; retain a held fixture.",
          "For existing current rows, require consistency with the live guard. Compare candidate and current histories; require an explicit staff decision for discrepancies. Keep newer current state rather than silently replacing it with older state; lifecycle rollback requires R5, not snapshot selection. Preserve original collection age and do not clear a hold through restore.",
          "For retained jobs, preserve current history and valid candidate history without renumbering action IDs. Identical IDs must have identical content or restore fails. Require complete same-job earlier-action reference chains; reject dangling, cross-job, self or conflicting references. Reject candidate sequences or revisions inconsistent with the live guard.",
          "At atomic restore commit, assign each retained job a revision above its current, candidate and guard high-water values. Append a fresh reconciliation action with an ID above both histories and the durable global high-water mark, update the guard and require UI reload. Retired fixtures stay absent and receive no new job/log content."
        ],
        "decisionRefs": [],
        "evidenceVersionRefs": [
          {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          }
        ],
        "assumptions": [
          "Thirty days, staff-run cleanup, session-end snapshots and lifetime guard retention are proposed demo policies, not validated requirements.",
          "The demo clock and durable guard are available and consistent; the design claims no resistance to external store rollback.",
          "A backup older than a missing row's latest guarded revision may be unusable; safety against stale resurrection takes precedence over recovery availability."
        ],
        "unresolved": [
          "Production retention approval, clock reliability, guard protection, whole-store recovery, unmanaged copies and deletion assurance."
        ],
        "reviewState": "needs-review",
        "revision": 1
      }
    ],
    "recordedBasis": {
      "contract": "recorded-package-basis",
      "version": 1,
      "scope": {
        "canvas": "my",
        "revision": 1
      },
      "materials": [
        {
          "reference": {
            "canvas": "my",
            "nodeId": "repair-question",
            "contentRevision": 1
          },
          "title": "Keep the job and the handoff together",
          "kind": "question",
          "attribution": "",
          "evidenceStatus": "unassessed"
        },
        {
          "reference": {
            "canvas": "my",
            "nodeId": "repair-samples",
            "contentRevision": 1
          },
          "title": "Three synthetic jobs and failure cases",
          "kind": "observation",
          "attribution": "",
          "evidenceStatus": "unassessed"
        },
        {
          "reference": {
            "canvas": "my",
            "nodeId": "repair-kit",
            "contentRevision": 1
          },
          "title": "Three parts, one human-owned record",
          "kind": "idea",
          "attribution": "",
          "evidenceStatus": "unassessed"
        }
      ],
      "concepts": [],
      "humanDecisionRecords": [],
      "qualification": "No linked decision is inferred; review the retained records before treating this draft as a commitment."
    },
    "evidence": [
      {
        "id": "repair-question",
        "kind": "question",
        "title": "Keep the job and the handoff together",
        "url": "",
        "contentRevision": 1
      },
      {
        "id": "repair-samples",
        "kind": "observation",
        "title": "Three synthetic jobs and failure cases",
        "url": "",
        "contentRevision": 1
      },
      {
        "id": "repair-kit",
        "kind": "idea",
        "title": "Three parts, one human-owned record",
        "url": "",
        "contentRevision": 1
      }
    ],
    "referenceAvailability": [
      {
        "reference": {
          "canvas": "my",
          "nodeId": "repair-samples",
          "contentRevision": 1
        },
        "status": "current"
      },
      {
        "reference": {
          "canvas": "my",
          "nodeId": "repair-kit",
          "contentRevision": 1
        },
        "status": "current"
      },
      {
        "reference": {
          "canvas": "my",
          "nodeId": "repair-question",
          "contentRevision": 1
        },
        "status": "current"
      }
    ],
    "disclosures": {
      "assumptions": [
        "The durable guard remains available throughout the demo lineage; no reset/reseed feature is provided.",
        "The linear lifecycle and durable sequence allocator are proposed teaching design choices.",
        "Exact tag geometry is a supplied design constraint, not a measured observation.",
        "An acknowledgement is a workflow control, not proof that verification occurred.",
        "A status correction does not reverse physical work or recover an item.",
        "Thirty days, staff-run cleanup, session-end snapshots and lifetime guard retention are proposed demo policies, not validated requirements.",
        "The demo clock and durable guard are available and consistent; the design claims no resistance to external store rollback.",
        "A backup older than a missing row's latest guarded revision may be unusable; safety against stale resurrection takes precedence over recovery availability."
      ],
      "unansweredQuestions": [
        "Prototype: What dimensional tolerance and handling criteria should govern a later physical review?",
        "Material: What PLA grade, label stock, label dimensions and attachment method are suitable?",
        "Physical data: Tag mass is unknown; no measured or calculated mass is claimed.",
        "Recovery: How would a production shop invalidate and replace a permanently lost marker?",
        "Privacy: Are the proposed 30-day content policy and lifetime non-personal guard metadata appropriate? Neither is validated.",
        "Backup: How should guard loss, whole-store loss and protection against rollback be handled beyond this fail-closed demo contract?",
        "Deletion: How would production systems address unmanaged copies, interrupted cleanup and deletion assurance?",
        "Time: What clock and timestamp controls would make retention age dependable outside the demo?",
        "Recovery after loss of the guard is outside this light draft.",
        "Prototype tolerance, mass, material suitability and label specification.",
        "The external shop verification process is deliberately unspecified.",
        "Items already handed to the wrong person require resolution outside this demo.",
        "Production retention approval, clock reliability, guard protection, whole-store recovery, unmanaged copies and deletion assurance."
      ],
      "risks": [
        "Possession of a numbered tag is mistaken for identity proof. — Require external shop verification and separate staff confirmation; display the locator-only warning.",
        "Invalid or reused action IDs make corrections ambiguous or leave dangling references. — Use durable monotonic allocation, atomic same-job earlier-target validation, complete retained histories and rejection of conflicting snapshot IDs. Delete a retiring job's history as a unit.",
        "An older snapshot or startup seed resurrects a deleted or expired fixture. — Keep the initialization latch, retirement flags and high-water marks outside restore rollback. Check current eligibility before restore; require the latest guarded revision when recovering a missing row; never reseed.",
        "The durable guard is lost or rolled back with the data. — Fail closed on initialization and restore rather than infer freshness from an old backup. Whole-store loss recovery remains unresolved; this is not a tamper-resistance claim.",
        "A restored record disagrees with physical reality. — Freeze actions, preserve eligible current data, compare histories and require category-specific staff reconciliation. Restore does not silently replace newer state or bypass R5.",
        "Cleanup is interrupted, copied snapshots remain, or the demo clock gives an incorrect age. — Retirement blocks reimport even if cleanup is incomplete; report pending managed-copy cleanup. Unmanaged copies, clock reliability and deletion assurance remain unvalidated.",
        "A lost tag cannot be safely replaced under the fixed-ID scope. — Keep the job held until the original is recovered and reconciled; leave replacement policy unresolved.",
        "PLA or label performance is unsuitable. — Treat material, attachment, cleaning and handling suitability as untested prototype questions."
      ],
      "acceptedRisks": [],
      "missingDecisionRequirementIds": [
        "R1",
        "R2",
        "R3",
        "R4",
        "R5",
        "R6"
      ],
      "pendingRequirementIds": [
        "R1",
        "R2",
        "R3",
        "R4",
        "R5",
        "R6"
      ],
      "hasUnavailablePrivateMaterial": true
    }
  },
  "evidence": [
    {
      "id": "repair-question",
      "kind": "question",
      "title": "Keep the job and the handoff together",
      "url": "",
      "sourceVersionId": null,
      "contentRevision": 1
    },
    {
      "id": "repair-samples",
      "kind": "observation",
      "title": "Three synthetic jobs and failure cases",
      "url": "",
      "sourceVersionId": null,
      "contentRevision": 1
    },
    {
      "id": "repair-kit",
      "kind": "idea",
      "title": "Three parts, one human-owned record",
      "url": "",
      "sourceVersionId": null,
      "contentRevision": 1
    }
  ],
  "investigationId": "cookbook-repair-shop",
  "runId": "cookbook-runner:repair-shop",
  "receiptId": "resp_0632a51eb1fc2739016abebc64ec6887d295399f39ffcbe1f9",
  "created": "2026-10-01T20:05:35.146Z"
}