diff --git a/README.md b/README.md index a1a0939..509cedc 100644 --- a/README.md +++ b/README.md @@ -740,6 +740,7 @@ docker-compose up - gRPC bridge guide: [`docs/guides/grpc-bridge-skeleton.md`](docs/guides/grpc-bridge-skeleton.md) - AutoGen interop fixtures guide: [`docs/guides/autogen-interop-fixtures.md`](docs/guides/autogen-interop-fixtures.md) - AgentSkill delegated authority fixtures guide: [`docs/guides/agentskill-authz-interop-fixtures.md`](docs/guides/agentskill-authz-interop-fixtures.md) +- Industrial humanoid shipyard safety pack: [`docs/guides/industrial-humanoid-shipyard-safety-pack.md`](docs/guides/industrial-humanoid-shipyard-safety-pack.md) - action_ref identity/explainability profile: [`docs/specs/action-ref-identity-explainability-profile.md`](docs/specs/action-ref-identity-explainability-profile.md) - Payment governance profile (Economic Layer v1): [`docs/specs/payment-governance-profile-v1.md`](docs/specs/payment-governance-profile-v1.md) - Agent commerce governance profile: [`docs/specs/agent-commerce-governance-profile-v1.md`](docs/specs/agent-commerce-governance-profile-v1.md) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index f09615b..612601f 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -49,6 +49,7 @@ export default defineConfig({ { text: "EU AI Act Conformity Pack", link: "/guides/eu-ai-act-conformity-pack" }, { text: "Multi-Vendor Fleet Governance", link: "/guides/multivendor-fleet-governance" }, { text: "Industrial Cell Safety Pack", link: "/guides/industrial-cell-safety-pack" }, + { text: "Industrial Humanoid Shipyard Safety", link: "/guides/industrial-humanoid-shipyard-safety-pack" }, { text: "Factory Action Pack Demo", link: "/guides/factory-action-pack-demo" }, { text: "Regulated Consent Extensions", link: "/guides/regulated-consent-extensions" }, { text: "Open-RMF Handoff Policy Receipts", link: "/guides/open-rmf-handoff-policy-receipts" }, @@ -84,6 +85,7 @@ export default defineConfig({ { text: "Discord Launch Kit", link: "/community/discord-launch-kit" }, { text: "External Contributor Onboarding", link: "/community/external-contributor-onboarding" }, { text: "Independent Maintainer Scorecard", link: "/community/independent-maintainer-scorecard" }, + { text: "Persona AI Shipyard Safety Brief", link: "/community/persona-ai-shipyard-safety-brief" }, { text: "Robotics Collaboration Outreach", link: "/community/robotics-collaboration-outreach-schedule" }, { text: "Sunnybotics Collaboration Brief", link: "/community/sunnybotics-collaboration-brief" }, { text: "Sunnybotics Outreach Drafts", link: "/community/sunnybotics-outreach-drafts" }, @@ -112,6 +114,7 @@ export default defineConfig({ { text: "Ecosystem Outreach 2026", link: "/roadmaps/ecosystem-outreach-2026" }, { text: "Factory Action Pack Upgrade Sprints", link: "/roadmaps/factory-action-pack-upgrade-sprints" }, { text: "Graph-First Coordination Upgrade", link: "/roadmaps/graph-first-coordination-upgrade-2026" }, + { text: "Industrial Humanoid Shipyard Safety Sprint", link: "/roadmaps/industrial-humanoid-shipyard-safety-sprint" }, { text: "Humanoid Robotics Integrations", link: "/roadmaps/humanoid-robotics-integrations-2026" }, { text: "Post-Quantum Crypto Agility", link: "/roadmaps/post-quantum-crypto-agility" }, { text: "Physical AI Governance", link: "/roadmaps/PHYSICAL_AI_GOVERNANCE_2026-2029" }, diff --git a/docs/community/persona-ai-shipyard-safety-brief.md b/docs/community/persona-ai-shipyard-safety-brief.md new file mode 100644 index 0000000..7d0cbf1 --- /dev/null +++ b/docs/community/persona-ai-shipyard-safety-brief.md @@ -0,0 +1,117 @@ +# Persona AI Shipyard Safety Brief + +Status: outreach-ready technical brief + +Persona AI is building industrial humanoid robots for heavy industry, including +shipyards, energy, construction, and manufacturing. Public materials emphasize +work such as welding, fabrication, inspection, supervisor coordination, +bystander awareness, and robot-to-robot collaboration. + +SINT can help by acting as the runtime governance and evidence layer between +Persona-style humanoid intent and physical execution. + +## Core Fit + +Persona's problem is not only making a humanoid move or weld. In production, +shipyards need to answer: + +1. Was this robot authorized to perform this action? +2. Were the right permits active? +3. Was the workspace safe for humans and other robots? +4. Was the welding or manipulation path reviewed before execution? +5. Can a supervisor, customer, or surveyor reconstruct what happened later? + +SINT is built for that boundary. + +## SINT Value for Persona-Style Deployments + +### 1. Shipyard Safety Policy Gateway + +Every high-consequence robot action can route through +`PolicyGateway.intercept()` before execution: + +- start welding arc +- start grinder +- enter confined space +- lift material +- move through shared work zone +- release robot-to-robot handoff +- execute emergency stop rollback + +### 2. Hot-Work and Welding Evidence + +SINT can bind a welding request to: + +- hot-work permit +- fire-watch readiness +- fume extraction status +- gas-monitor status +- weld procedure reference +- simulation receipt digest +- offline program hash +- supervisor approval + +### 3. ABS-Style Remote Survey Support + +SINT can export hash-chained evidence for: + +- policy decision and assigned tier +- safety-controller context +- robot and work-order identifiers +- sensor calibration references +- simulation receipt and program digest +- event hash and previous hash + +This supports review and incident reconstruction. It does not replace +classification society assessment or product approval. + +### 4. RaaS Fleet Governance + +For robot-as-a-service deployments, SINT can enforce customer/site policy: + +- per-site action limits +- operator approval rules +- tenant-specific permit requirements +- update and model-change gates +- evidence retention and export + +## Pack Built in This Repo + +Executable fixture: + +- `packages/conformance-tests/fixtures/industrial/industrial-humanoid-shipyard-safety-pack.v1.json` + +Guide: + +- `docs/guides/industrial-humanoid-shipyard-safety-pack.md` + +Sprint plan: + +- `docs/roadmaps/industrial-humanoid-shipyard-safety-sprint.md` + +## Proposed Message + +SINT does not compete with Persona's robot stack. It complements it as the +policy, approval, and evidence layer for industrial humanoid deployments. For +shipyard welding, SINT can prove that hot-work permits, safety-controller state, +simulation receipts, supervisor approvals, and operator evidence were present +before the robot acted. + +## Suggested Next Conversation + +Ask for one narrow integration surface: + +- one ROS 2 or controller action for weld start +- one safety PLC or permit signal +- one simulator receipt or offline program hash +- one supervisor approval event + +Then map that path into a SINT `request -> decision -> receipt -> execution` +trace. + +## Public References + +- Persona AI: `https://persona.ai/` +- Persona AI RaaS brochure: `https://persona.ai/wp-content/uploads/PAI-RaaS-Brocure-04-2026-v1.pdf` +- HD Hyundai / Persona AI shipbuilding automation announcement: `https://www.prnewswire.com/news-releases/hd-hyundai-and-persona-ai-sign-agreement-to-deploy-humanoid-welding-robots-for-shipbuilding-automation-302449258.html` +- ABS / Persona AI shipyard robotics announcement: `https://www.businesswire.com/news/home/20250923457571/en/ABS-and-Persona-AI-Partner-to-Bring-Humanoid-Robotics-to-Shipyards-Advancing-Safety-and-Productivity` diff --git a/docs/guides/industrial-humanoid-shipyard-safety-pack.md b/docs/guides/industrial-humanoid-shipyard-safety-pack.md new file mode 100644 index 0000000..205d141 --- /dev/null +++ b/docs/guides/industrial-humanoid-shipyard-safety-pack.md @@ -0,0 +1,121 @@ +# Industrial Humanoid Shipyard Safety Pack + +This guide defines a SINT safety and evidence pack for industrial humanoids +working in shipyards, with emphasis on welding, hot work, confined-space entry, +inspection, material handling, and remote survey evidence. + +The target deployment shape matches companies building humanoid robots for +heavy industry: a robot may inspect a hull block, enter a shared work zone, +start a welding arc, grind material, lift parts, or generate evidence for a +supervisor and surveyor. SINT sits before those actions as the policy gateway. + +Executable fixture: + +- `packages/conformance-tests/fixtures/industrial/industrial-humanoid-shipyard-safety-pack.v1.json` + +Conformance test: + +- `packages/conformance-tests/src/industrial-humanoid-shipyard-safety-pack-conformance.test.ts` + +## Scope + +The pack covers one shipyard block: + +- industrial humanoid welder +- welding supervisor +- fire watch +- safety PLC +- remote surveyor +- shipyard operator +- welding torch, grinder, inspection camera, and material gripper + +SINT does not certify welding procedures, shipyard safety, robot hardware, +classification-society acceptance, or OSHA compliance. It provides policy +decisions, receipts, and evidence records that can support those processes. + +## Policy Templates + +| Template | Resource | Default tier | +| --- | --- | --- | +| Hot-work welding | `humanoid://shipyard/robot/*/tool/welding-torch/*` | T3 | +| Confined-space entry | `humanoid://shipyard/robot/*/workspace/*/confined-space/enter` | T3 | +| Material handling | `humanoid://shipyard/robot/*/material/lift` | T2 | +| Visual inspection | `humanoid://shipyard/robot/*/inspection/*` | T0 | + +Hot-work welding requires: + +- hot-work permit +- fire-watch readiness +- fume extraction online +- safe gas-atmosphere context +- simulation receipt bound to the submitted welding program digest +- fresh safety-controller context + +## Required Scenarios + +The executable pack covers: + +- visual inspection allowed as T0 observe +- welding denied without a hot-work permit +- welding denied when fire watch is not ready +- welding denied when fume extraction is offline +- confined-space entry denied when gas atmosphere is unsafe +- bystander in weld zone escalates to T3 +- simulation receipt mismatch denied before arc start +- valid weld start escalates for supervisor approval +- material lift over envelope denied +- e-stop during weld rolls back unconditionally + +## ABS-Style Evidence Export + +The fixture defines an evidence export profile for remote survey, audit replay, +data-quality review, and incident reconstruction. Required fields include: + +- site and vessel block identifiers +- robot and work-order identifiers +- weld procedure specification reference +- hot-work permit and fire-watch operator identifiers +- gas monitor calibration reference +- fume extraction status +- simulation receipt digest +- policy decision and tier +- hash-chain fields: `eventHash`, `previousHash` + +Data quality rules require clock sync, calibrated sensors, and program digest +binding between simulation and execution. + +## Persona AI Fit + +Persona AI publicly describes industrial humanoids for shipyards, energy, +construction, and manufacturing, including human coworker safety and +supervisor/bystander coordination. This pack translates that operating model +into SINT controls: + +- every welding or confined-space action is pre-gated +- every denial/escalation has a receipt +- every simulation-to-execution drift case is blocked +- every incident can be reconstructed through hash-chained evidence +- every support claim stays inside evidence and runtime-governance boundaries + +## Verification + +Run the targeted pack: + +```bash +pnpm --filter @pshkv/conformance-tests exec vitest run src/industrial-humanoid-shipyard-safety-pack-conformance.test.ts +``` + +Run all fixture contracts: + +```bash +pnpm --filter @pshkv/conformance-tests test:fixtures +``` + +## Exit Criteria + +- Hot-work, fire-watch, fume extraction, atmosphere, bystander, simulation, + supervisor-approval, load-envelope, and e-stop cases are executable. +- FMEA rows reference executable scenario IDs. +- Evidence export includes data-quality rules. +- Certification language remains support-only unless a qualified assessor signs + off. diff --git a/docs/index.md b/docs/index.md index 152d4ed..fdc03a5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -54,12 +54,14 @@ limits, and tamper-evident audit evidence before execution. - Good-first-issues board: [Community/Starter Board](./community/good-first-issues-board.md) - Collaboration reply playbook: [Community/Replies](./community/open-source-collaboration-replies.md) - Physical AI runtime safety working group: [Community/Working Group](./community/physical-ai-runtime-safety-working-group.md) +- Industrial humanoid shipyard safety pack: [Guide](./guides/industrial-humanoid-shipyard-safety-pack.md) - OWASP Agentic Landscape submission packet: [Community/OWASP Packet](./community/owasp-agentic-landscape-submission.md) - EU AI Act mapping: [Compliance/EU AI Act](./compliance/eu-ai-act-mapping.md) - ISO 13482 alignment: [Compliance/ISO 13482](./compliance/iso-13482-alignment.md) - Formal threat model: [Security/Formal Threat Model](./security/formal-threat-model.md) - MITRE ATLAS candidate mappings: [Security/MITRE ATLAS](./security/mitre-atlas-agent-technique-mappings.md) - Agent commerce governance profile: [Spec](./specs/agent-commerce-governance-profile-v1.md) +- Persona AI shipyard safety brief: [Community Brief](./community/persona-ai-shipyard-safety-brief.md) - NIST submission bundle report: [Report](./reports/nist-submission-bundle.md) - Latest security bulletin: [May 2026](./security-bulletins/2026-05.md) diff --git a/docs/marketing-message-map.md b/docs/marketing-message-map.md index bf9bcfe..e593c9e 100644 --- a/docs/marketing-message-map.md +++ b/docs/marketing-message-map.md @@ -75,6 +75,13 @@ SINT can govern task-market and machine-payment workflows before work or money moves: task creation, bids, claims, benchmark proof submission, worker selection, settlement release, and x402-style payment permits. +### 7. Industrial humanoid safety evidence + +SINT can govern industrial humanoids before they weld, grind, lift, enter +confined spaces, or move through shared work zones. The message is not +"certification replacement"; it is "policy receipts and runtime evidence for +supervisors, safety teams, surveyors, and post-incident review." + ## Proof points to emphasize - Apache-2.0 licensed @@ -98,6 +105,9 @@ selection, settlement release, and x402-style payment permits. - "industrial AI safety" - "agent commerce governance" - "x402 policy enforcement" +- "industrial humanoid safety" +- "shipyard robotics governance" +- "hot-work policy receipts" - "tamper-evident evidence ledger" - "open protocol and reference stack" - "real-world consequences" diff --git a/docs/roadmaps/industrial-humanoid-shipyard-safety-sprint.md b/docs/roadmaps/industrial-humanoid-shipyard-safety-sprint.md new file mode 100644 index 0000000..c0b14a3 --- /dev/null +++ b/docs/roadmaps/industrial-humanoid-shipyard-safety-sprint.md @@ -0,0 +1,113 @@ +# Industrial Humanoid Shipyard Safety Sprint + +Status: Sprint 1 executable profile shipped in conformance fixtures + +This sprint turns the Persona-style industrial humanoid opportunity into a +SINT product lane: safety policy, certification evidence, and runtime receipts +for shipyard robots doing welding, inspection, confined-space, and material +handling work. + +## Sprint Goal + +Make SINT legible as the runtime safety and evidence layer for industrial +humanoid deployments in shipyards. + +The output is not a vendor integration. It is a vendor-neutral pack that a +Persona-style deployment, shipyard operator, classification society, or robotics +integrator can map onto their own controllers, simulators, and permit systems. + +## Why This Matters + +Industrial humanoids are moving from demos into heavy-industry tasks. The hard +problem is not only locomotion or manipulation. It is proving that a robot was +allowed to do a specific high-consequence action under the right permits, +constraints, simulation evidence, and human oversight. + +SINT is strongest at that boundary: + +- pre-action policy gate +- physical constraints in scoped authority +- T2/T3 approval routing +- e-stop rollback evidence +- append-only hash-chained ledger +- portable receipts for supervisors, surveyors, and incident review + +## Workstreams + +### S1. Policy Profile and Fixture Pack + +Deliverables: + +- shipyard policy templates for hot work, confined space, material handling, + and inspection +- scenario pack for welding permit, fire watch, fume extraction, gas monitor, + human proximity, load envelope, simulation receipt, and e-stop +- stable evidence events and policy violation codes + +Status: complete in +`packages/conformance-tests/fixtures/industrial/industrial-humanoid-shipyard-safety-pack.v1.json` + +### S2. Simulation and Program Binding + +Deliverables: + +- offline welding program digest binding +- simulation receipt digest binding +- mismatch denial scenario before arc start + +Status: complete in the `simulation-receipt-mismatch` scenario. + +### S3. Safety-Case Evidence + +Deliverables: + +- FMEA rows tied to executable scenarios +- ABS-style evidence export fields +- data-quality rules for clock sync, calibrated sensors, and program binding +- support-only claim boundaries + +Status: complete in the fixture and conformance test. + +### S4. Persona-Facing Outreach Pack + +Deliverables: + +- operator guide +- Persona fit brief +- verification commands +- next-step integration proposal + +Status: complete in: + +- `docs/guides/industrial-humanoid-shipyard-safety-pack.md` +- `docs/community/persona-ai-shipyard-safety-brief.md` + +## Sprint 2 Candidate + +The next build slice should create a bridge skeleton that maps real controller +events into this profile: + +- ROS 2 / MoveIt action mapping for humanoid manipulation +- OPC UA safety PLC permit and gas-monitor resource mapping +- Isaac Sim / weld-simulator receipt adapter +- dashboard card for hot-work approvals and evidence replay +- `sintctl shipyard evidence export` command + +## Validation + +Run: + +```bash +pnpm --filter @pshkv/conformance-tests exec vitest run src/industrial-humanoid-shipyard-safety-pack-conformance.test.ts +pnpm --filter @pshkv/conformance-tests test:fixtures +pnpm run docs:build +``` + +## Definition of Done + +- New fixture pack is executable. +- All scenarios have deterministic expected decisions. +- FMEA rows point to executable scenario IDs. +- ABS-style evidence fields are declared. +- Docs explain Persona fit without making certification claims. +- Full fixture suite remains green. diff --git a/packages/conformance-tests/fixtures/industrial/industrial-humanoid-shipyard-safety-pack.v1.json b/packages/conformance-tests/fixtures/industrial/industrial-humanoid-shipyard-safety-pack.v1.json new file mode 100644 index 0000000..fe00588 --- /dev/null +++ b/packages/conformance-tests/fixtures/industrial/industrial-humanoid-shipyard-safety-pack.v1.json @@ -0,0 +1,589 @@ +{ + "fixtureId": "industrial-humanoid-shipyard-safety-pack-v1", + "schemaVersion": "1.0.0", + "description": "Shipyard humanoid safety pack for welding, hot-work, confined-space, material-handling, inspection, and certification-evidence workflows.", + "scopeNote": "SINT provides runtime governance, policy receipts, and safety-case evidence support for industrial humanoid deployments. This fixture is not a shipyard certification, ABS product approval, welding procedure qualification, OSHA compliance determination, or replacement for a certified robot safety controller.", + "deployment": { + "siteId": "shipyard-demo-01", + "vesselBlockId": "hull-block-17", + "profile": "industrial-humanoid-shipyard", + "actors": [ + "industrial-humanoid-welder", + "welding-supervisor", + "fire-watch", + "safety-plc", + "abs-remote-surveyor", + "shipyard-operator" + ], + "robots": [ + { + "id": "welder-humanoid-01", + "kind": "humanoid", + "primaryTools": [ + "welding-torch", + "grinder", + "inspection-camera", + "material-gripper" + ] + } + ], + "resources": [ + "humanoid://shipyard/robot/welder-humanoid-01/tool/welding-torch/arc_start", + "humanoid://shipyard/robot/welder-humanoid-01/tool/grinder/start", + "humanoid://shipyard/robot/welder-humanoid-01/workspace/hull-block-17/confined-space/enter", + "humanoid://shipyard/robot/welder-humanoid-01/material/lift", + "humanoid://shipyard/robot/welder-humanoid-01/inspection/visual", + "humanoid://shipyard/robot/welder-humanoid-01/estop", + "opcua://safety-plc.shipyard.local/ns%3D2%3Bs%3DHotWork%2FPermit", + "opcua://safety-plc.shipyard.local/ns%3D2%3Bs%3DFireWatch%2FReady", + "opcua://safety-plc.shipyard.local/ns%3D2%3Bs%3DFumeExtraction%2FStatus", + "opcua://safety-plc.shipyard.local/ns%3D2%3Bs%3DGasMonitor%2FO2" + ] + }, + "policyTemplates": [ + { + "templateId": "shipyard-hot-work-welding", + "resourcePattern": "humanoid://shipyard/robot/*/tool/welding-torch/*", + "defaultTier": "T3_commit", + "requiredPermits": [ + "hotWorkPermit", + "fireWatchReady", + "fumeExtractionOnline", + "gasAtmosphereSafe", + "simulationReceipt" + ], + "requiredHardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "maxObservedAgeMs": 2500 + } + }, + { + "templateId": "shipyard-confined-space-entry", + "resourcePattern": "humanoid://shipyard/robot/*/workspace/*/confined-space/enter", + "defaultTier": "T3_commit", + "requiredPermits": [ + "confinedSpacePermit", + "gasAtmosphereSafe", + "attendantReady", + "commsLinkReady" + ], + "requiredHardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "maxObservedAgeMs": 2500 + } + }, + { + "templateId": "shipyard-material-handling", + "resourcePattern": "humanoid://shipyard/robot/*/material/lift", + "defaultTier": "T2_act", + "requiredPermits": [ + "liftPlanApproved", + "zoneClear", + "loadWithinEnvelope" + ], + "requiredHardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "maxObservedAgeMs": 2500 + } + }, + { + "templateId": "shipyard-visual-inspection", + "resourcePattern": "humanoid://shipyard/robot/*/inspection/*", + "defaultTier": "T0_observe", + "requiredPermits": [ + "zoneAccessLogged" + ], + "requiredHardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "maxObservedAgeMs": 5000 + } + } + ], + "shipyardScenarios": [ + { + "id": "visual-inspection-allowed", + "description": "Humanoid performs visual seam inspection in an authorized zone without physical actuation.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/inspection/visual", + "action": "observe", + "operation": "visual_inspection", + "permits": { + "zoneAccessLogged": true + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 120 + }, + "expectedDecision": "allow", + "expectedTier": "T0_observe", + "evidenceEvent": "shipyard.inspection.visual.allowed", + "receiptRequired": true + }, + { + "id": "weld-start-without-hot-work-permit", + "description": "Humanoid attempts to start arc welding without an active hot-work permit.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/tool/welding-torch/arc_start", + "action": "execute", + "operation": "arc_weld_start", + "permits": { + "hotWorkPermit": false, + "fireWatchReady": true, + "fumeExtractionOnline": true, + "gasAtmosphereSafe": true, + "simulationReceipt": true + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 80 + }, + "expectedDecision": "deny", + "expectedTier": "T3_commit", + "policyViolated": "HOT_WORK_PERMIT_REQUIRED", + "evidenceEvent": "shipyard.hotwork.permit.missing", + "receiptRequired": true + }, + { + "id": "weld-start-fire-watch-not-ready", + "description": "Humanoid attempts hot work while the assigned fire-watch station is not ready.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/tool/welding-torch/arc_start", + "action": "execute", + "operation": "arc_weld_start", + "permits": { + "hotWorkPermit": true, + "fireWatchReady": false, + "fumeExtractionOnline": true, + "gasAtmosphereSafe": true, + "simulationReceipt": true + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 75 + }, + "expectedDecision": "deny", + "expectedTier": "T3_commit", + "policyViolated": "FIRE_WATCH_REQUIRED", + "evidenceEvent": "shipyard.firewatch.not_ready", + "receiptRequired": true + }, + { + "id": "fume-extraction-offline", + "description": "Welding path is otherwise valid but fume extraction is offline.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/tool/welding-torch/arc_start", + "action": "execute", + "operation": "arc_weld_start", + "permits": { + "hotWorkPermit": true, + "fireWatchReady": true, + "fumeExtractionOnline": false, + "gasAtmosphereSafe": true, + "simulationReceipt": true + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 90 + }, + "expectedDecision": "deny", + "expectedTier": "T3_commit", + "policyViolated": "FUME_EXTRACTION_REQUIRED", + "evidenceEvent": "shipyard.fume_extraction.offline", + "receiptRequired": true + }, + { + "id": "unsafe-atmosphere-confined-space", + "description": "Robot requests confined-space entry while gas-monitor context is unsafe.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/workspace/hull-block-17/confined-space/enter", + "action": "enter", + "operation": "confined_space_entry", + "permits": { + "confinedSpacePermit": true, + "gasAtmosphereSafe": false, + "attendantReady": true, + "commsLinkReady": true + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 60 + }, + "expectedDecision": "deny", + "expectedTier": "T3_commit", + "policyViolated": "ATMOSPHERE_UNSAFE", + "evidenceEvent": "shipyard.gas_monitor.unsafe", + "receiptRequired": true + }, + { + "id": "bystander-in-weld-zone", + "description": "Bystander enters the weld envelope during a high-consequence welding request.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/tool/welding-torch/arc_start", + "action": "execute", + "operation": "arc_weld_start", + "permits": { + "hotWorkPermit": true, + "fireWatchReady": true, + "fumeExtractionOnline": true, + "gasAtmosphereSafe": true, + "simulationReceipt": true + }, + "physicalContext": { + "humanDetected": true, + "distanceToHumanM": 1.2 + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 70 + }, + "expectedDecision": "escalate", + "expectedTier": "T3_commit", + "policyViolated": "BYSTANDER_IN_WELD_ZONE", + "evidenceEvent": "shipyard.human.detected_in_weld_zone", + "receiptRequired": true + }, + { + "id": "simulation-receipt-mismatch", + "description": "Offline welding program hash does not match the simulation receipt bound to approval.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/tool/welding-torch/arc_start", + "action": "execute", + "operation": "arc_weld_start", + "permits": { + "hotWorkPermit": true, + "fireWatchReady": true, + "fumeExtractionOnline": true, + "gasAtmosphereSafe": true, + "simulationReceipt": false + }, + "simulation": { + "expectedProgramDigest": "sha256:1d5d2f257b67bb66f7a2f6c72d1c67f8aeafedec8bb8e9c1d12f962ef889d5b8", + "submittedProgramDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "receiptDigest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 95 + }, + "expectedDecision": "deny", + "expectedTier": "T3_commit", + "policyViolated": "SIMULATION_RECEIPT_MISMATCH", + "evidenceEvent": "shipyard.simulation.receipt_mismatch", + "receiptRequired": true + }, + { + "id": "valid-weld-start-requires-supervisor-approval", + "description": "All hot-work preconditions are satisfied; weld start still escalates to supervisor approval because arc welding is irreversible physical work.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/tool/welding-torch/arc_start", + "action": "execute", + "operation": "arc_weld_start", + "permits": { + "hotWorkPermit": true, + "fireWatchReady": true, + "fumeExtractionOnline": true, + "gasAtmosphereSafe": true, + "simulationReceipt": true + }, + "simulation": { + "expectedProgramDigest": "sha256:1d5d2f257b67bb66f7a2f6c72d1c67f8aeafedec8bb8e9c1d12f962ef889d5b8", + "submittedProgramDigest": "sha256:1d5d2f257b67bb66f7a2f6c72d1c67f8aeafedec8bb8e9c1d12f962ef889d5b8", + "receiptDigest": "sha256:9b8da3edcf3719892fd0ccf56b09256cf2ec0e16ad73e9dd3d232cc0bb10e6bd" + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 70 + }, + "expectedDecision": "escalate", + "expectedTier": "T3_commit", + "policyViolated": "SUPERVISOR_APPROVAL_REQUIRED", + "evidenceEvent": "shipyard.weld.supervisor_approval_required", + "receiptRequired": true + }, + { + "id": "material-lift-over-envelope", + "description": "Humanoid material lift exceeds the token load envelope for the workcell.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/material/lift", + "action": "execute", + "operation": "material_lift", + "constraints": { + "maxLoadKg": 18 + }, + "physicalContext": { + "currentLoadKg": 22 + }, + "permits": { + "liftPlanApproved": true, + "zoneClear": true, + "loadWithinEnvelope": false + }, + "hardwareSafety": { + "permitState": "granted", + "interlockState": "closed", + "estopState": "clear", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 85 + }, + "expectedDecision": "deny", + "expectedTier": "T2_act", + "policyViolated": "LOAD_LIMIT_EXCEEDED", + "evidenceEvent": "shipyard.material.load_limit_exceeded", + "receiptRequired": true + }, + { + "id": "estop-during-weld", + "description": "Emergency stop is triggered during a welding sequence.", + "resource": "humanoid://shipyard/robot/welder-humanoid-01/estop", + "action": "override", + "operation": "estop", + "hardwareSafety": { + "permitState": "denied", + "interlockState": "closed", + "estopState": "triggered", + "controllerId": "safety-plc-shipyard-01", + "observedAgeMs": 25 + }, + "expectedDecision": "rollback", + "expectedTier": "T3_commit", + "policyViolated": "ESTOP_UNCONDITIONAL", + "evidenceEvent": "shipyard.estop.triggered", + "rollbackTargetRef": "sint://action/welder-humanoid-01/hull-block-17/last-safe-state", + "receiptRequired": true + } + ], + "absEvidenceExport": { + "purpose": "Support remote survey, audit replay, data quality review, and incident reconstruction for shipyard humanoid work.", + "format": "json-lines", + "requiredFields": [ + "siteId", + "vesselBlockId", + "robotId", + "workOrderId", + "weldProcedureSpecId", + "hotWorkPermitId", + "fireWatchOperatorId", + "gasMonitorCalibrationRef", + "fumeExtractionStatus", + "simulationReceiptDigest", + "policyDecision", + "assignedTier", + "eventHash", + "previousHash", + "timestamp" + ], + "dataQualityRules": [ + { + "ruleId": "shipyard-evidence-clock-sync", + "description": "Robot, safety PLC, gateway, and survey export timestamps must share a bounded clock source.", + "maxSkewMs": 250 + }, + { + "ruleId": "shipyard-evidence-calibrated-sensors", + "description": "Gas monitor and proximity sensor evidence must include calibration references.", + "required": true + }, + { + "ruleId": "shipyard-evidence-program-binding", + "description": "Welding program digest must match the digest approved in the simulation receipt.", + "required": true + } + ] + }, + "fmeaExport": [ + { + "failureMode": "hot work without permit", + "sourceScenarioId": "weld-start-without-hot-work-permit", + "hazard": "unapproved ignition source in shipyard work area", + "sintDetection": "hotWorkPermit false", + "sintControl": "deny before arc start and emit shipyard.hotwork.permit.missing", + "severity": 10, + "occurrence": 3, + "detection": 2, + "requiredEvidence": [ + "hotWorkPermitId", + "policyViolated", + "eventHash", + "previousHash" + ] + }, + { + "failureMode": "fire watch missing", + "sourceScenarioId": "weld-start-fire-watch-not-ready", + "hazard": "delayed detection of ignition or slag fire", + "sintDetection": "fireWatchReady false", + "sintControl": "deny before arc start and require assigned fire watch", + "severity": 9, + "occurrence": 3, + "detection": 2, + "requiredEvidence": [ + "fireWatchOperatorId", + "policyViolated", + "eventHash" + ] + }, + { + "failureMode": "unsafe atmosphere in confined space", + "sourceScenarioId": "unsafe-atmosphere-confined-space", + "hazard": "oxygen deficiency or hazardous atmosphere exposure", + "sintDetection": "gasAtmosphereSafe false", + "sintControl": "deny confined-space entry before robot motion", + "severity": 10, + "occurrence": 2, + "detection": 2, + "requiredEvidence": [ + "gasMonitorCalibrationRef", + "policyViolated", + "eventHash" + ] + }, + { + "failureMode": "bystander inside weld envelope", + "sourceScenarioId": "bystander-in-weld-zone", + "hazard": "burn, flash, collision, or fume exposure", + "sintDetection": "physicalContext.humanDetected and distanceToHumanM below envelope threshold", + "sintControl": "escalate to T3 supervisor review or deny depending on site policy", + "severity": 9, + "occurrence": 4, + "detection": 3, + "requiredEvidence": [ + "physicalContext.humanDetected", + "distanceToHumanM", + "eventHash" + ] + }, + { + "failureMode": "simulation-to-execution drift", + "sourceScenarioId": "simulation-receipt-mismatch", + "hazard": "robot executes a program not reviewed in simulation", + "sintDetection": "submittedProgramDigest differs from expectedProgramDigest", + "sintControl": "deny before tool actuation and require fresh simulation receipt", + "severity": 9, + "occurrence": 2, + "detection": 2, + "requiredEvidence": [ + "expectedProgramDigest", + "submittedProgramDigest", + "simulationReceiptDigest", + "eventHash" + ] + }, + { + "failureMode": "e-stop during weld ignored", + "sourceScenarioId": "estop-during-weld", + "hazard": "continued welding after operator emergency stop", + "sintDetection": "estopState triggered", + "sintControl": "unconditional rollback to last safe state", + "severity": 10, + "occurrence": 2, + "detection": 1, + "requiredEvidence": [ + "incidentId", + "rollbackTargetRef", + "eventHash", + "previousHash" + ] + } + ], + "safetyCaseMapping": [ + { + "topic": "hot-work authorization", + "sintSupport": "Capability token scope, permit state, fire-watch state, fume extraction, gas monitor status, and simulation receipt are checked before arc start.", + "claimBoundary": "evidence support only; does not qualify welding procedure or certify hot-work safety" + }, + { + "topic": "remote survey and certification evidence", + "sintSupport": "ABS-style export fields bind policy decisions, permits, simulation receipts, sensor calibration references, and hash-chain continuity.", + "claimBoundary": "requires classification society or qualified assessor review" + }, + { + "topic": "human coworker safety", + "sintSupport": "Human detection in the weld envelope escalates to T3 and records the physical context that caused the decision.", + "claimBoundary": "does not replace physical guarding, trained spotters, or certified safety-rated sensors" + }, + { + "topic": "simulation-to-real execution control", + "sintSupport": "Offline program digest and simulator receipt digest are bound into the authorization decision.", + "claimBoundary": "simulator validity remains a deployment-owner responsibility" + } + ], + "sprintPlan": { + "duration": "2 weeks", + "goal": "Make SINT legible as the runtime safety and certification-evidence layer for industrial humanoid shipyard deployments.", + "workstreams": [ + { + "id": "S1", + "name": "Policy profile and fixture pack", + "deliverables": [ + "shipyard policy templates", + "welding and confined-space scenarios", + "ABS-style evidence export schema" + ] + }, + { + "id": "S2", + "name": "Simulation and program binding", + "deliverables": [ + "simulation receipt digest checks", + "offline program hash binding", + "drift-denial scenario" + ] + }, + { + "id": "S3", + "name": "Safety-case evidence", + "deliverables": [ + "FMEA rows tied to executable scenarios", + "data quality rules", + "support-only claim boundaries" + ] + }, + { + "id": "S4", + "name": "Outreach package", + "deliverables": [ + "Persona fit brief", + "operator guide", + "demo command and validation checklist" + ] + } + ] + }, + "successCriteria": { + "hotWorkPermitCovered": true, + "fireWatchCovered": true, + "fumeExtractionCovered": true, + "unsafeAtmosphereCovered": true, + "bystanderInWeldZoneCovered": true, + "simulationReceiptMismatchCovered": true, + "supervisorApprovalForWeldingCovered": true, + "loadEnvelopeCovered": true, + "estopRollbackCovered": true, + "absEvidenceExportHasDataQualityRules": true, + "fmeaRowsReferenceExecutableScenarios": true, + "claimsRemainSupportOnly": true + } +} diff --git a/packages/conformance-tests/package.json b/packages/conformance-tests/package.json index 38bb650..df7b4b7 100644 --- a/packages/conformance-tests/package.json +++ b/packages/conformance-tests/package.json @@ -7,7 +7,7 @@ "build": "echo 'no build needed'", "test": "vitest run", "test:watch": "vitest watch", - "test:fixtures": "vitest run src/canonical-fixtures-conformance.test.ts src/a2a-fixtures-conformance.test.ts src/security-iot-fixtures-conformance.test.ts src/economy-fixtures-conformance.test.ts src/autogen-interop-conformance.test.ts src/agentskill-authz-fixtures-conformance.test.ts src/action-ref-explainability-conformance.test.ts src/payment-governance-fixtures-conformance.test.ts src/agent-commerce-governance-conformance.test.ts src/physical-ai-runtime-safety-fixtures-conformance.test.ts src/post-quantum-crypto-agility-conformance.test.ts src/humanoid-profile-conformance.test.ts src/humanoid-warehouse-pilot-conformance.test.ts src/eu-ai-act-conformity-pack-conformance.test.ts src/humanoid-multivendor-fleet-conformance.test.ts src/open-rmf-handoff-policy-receipts-conformance.test.ts src/moveit-manipulation-policy-receipts-conformance.test.ts src/nav2-navigation-policy-receipts-conformance.test.ts src/px4-offboard-policy-receipts-conformance.test.ts src/lerobot-policy-actuation-receipts-conformance.test.ts src/solar-field-operations-policy-receipts-conformance.test.ts src/industrial-cell-safety-pack-conformance.test.ts src/factory-action-demo-conformance.test.ts src/sint-industrial-pack-conformance.test.ts src/regulated-consent-extensions-conformance.test.ts src/autonomy-supervisor-conformance.test.ts", + "test:fixtures": "vitest run src/canonical-fixtures-conformance.test.ts src/a2a-fixtures-conformance.test.ts src/security-iot-fixtures-conformance.test.ts src/economy-fixtures-conformance.test.ts src/autogen-interop-conformance.test.ts src/agentskill-authz-fixtures-conformance.test.ts src/action-ref-explainability-conformance.test.ts src/payment-governance-fixtures-conformance.test.ts src/agent-commerce-governance-conformance.test.ts src/physical-ai-runtime-safety-fixtures-conformance.test.ts src/post-quantum-crypto-agility-conformance.test.ts src/humanoid-profile-conformance.test.ts src/humanoid-warehouse-pilot-conformance.test.ts src/eu-ai-act-conformity-pack-conformance.test.ts src/humanoid-multivendor-fleet-conformance.test.ts src/open-rmf-handoff-policy-receipts-conformance.test.ts src/moveit-manipulation-policy-receipts-conformance.test.ts src/nav2-navigation-policy-receipts-conformance.test.ts src/px4-offboard-policy-receipts-conformance.test.ts src/lerobot-policy-actuation-receipts-conformance.test.ts src/solar-field-operations-policy-receipts-conformance.test.ts src/industrial-cell-safety-pack-conformance.test.ts src/industrial-humanoid-shipyard-safety-pack-conformance.test.ts src/factory-action-demo-conformance.test.ts src/sint-industrial-pack-conformance.test.ts src/regulated-consent-extensions-conformance.test.ts src/autonomy-supervisor-conformance.test.ts", "test:physical-ai-runtime": "vitest run src/physical-ai-runtime-safety-fixtures-conformance.test.ts", "test:factory-action": "vitest run src/factory-action-demo-conformance.test.ts", "test:ros2-loop": "vitest run src/ros2-control-loop-latency.test.ts" diff --git a/packages/conformance-tests/src/fixture-loader.ts b/packages/conformance-tests/src/fixture-loader.ts index 119d504..0d72869 100644 --- a/packages/conformance-tests/src/fixture-loader.ts +++ b/packages/conformance-tests/src/fixture-loader.ts @@ -1760,6 +1760,132 @@ export function loadIndustrialCellSafetyPackFixture(): IndustrialCellSafetyPackF ); } +export interface IndustrialHumanoidShipyardSafetyPackFixture { + readonly fixtureId: string; + readonly schemaVersion: string; + readonly description: string; + readonly scopeNote: string; + readonly deployment: { + readonly siteId: string; + readonly vesselBlockId: string; + readonly profile: "industrial-humanoid-shipyard"; + readonly actors: readonly string[]; + readonly robots: readonly Array<{ + readonly id: string; + readonly kind: "humanoid"; + readonly primaryTools: readonly string[]; + }>; + readonly resources: readonly string[]; + }; + readonly policyTemplates: readonly Array<{ + readonly templateId: string; + readonly resourcePattern: string; + readonly defaultTier: ApprovalTier; + readonly requiredPermits: readonly string[]; + readonly requiredHardwareSafety: { + readonly permitState: "granted"; + readonly interlockState: "closed"; + readonly estopState: "clear"; + readonly maxObservedAgeMs: number; + }; + }>; + readonly shipyardScenarios: readonly Array<{ + readonly id: string; + readonly description: string; + readonly resource: string; + readonly action: "observe" | "execute" | "enter" | "override"; + readonly operation: + | "visual_inspection" + | "arc_weld_start" + | "confined_space_entry" + | "material_lift" + | "estop"; + readonly permits?: Record; + readonly constraints?: { + readonly maxLoadKg?: number; + }; + readonly physicalContext?: { + readonly humanDetected?: boolean; + readonly distanceToHumanM?: number; + readonly currentLoadKg?: number; + }; + readonly simulation?: { + readonly expectedProgramDigest: string; + readonly submittedProgramDigest: string; + readonly receiptDigest: string; + }; + readonly hardwareSafety: { + readonly permitState: "granted" | "denied" | "unknown" | "stale"; + readonly interlockState: "closed" | "open" | "fault" | "unknown"; + readonly estopState: "clear" | "triggered" | "unknown"; + readonly controllerId: string; + readonly observedAgeMs: number; + }; + readonly expectedDecision: "allow" | "deny" | "escalate" | "rollback"; + readonly expectedTier: ApprovalTier; + readonly policyViolated?: string; + readonly evidenceEvent: string; + readonly rollbackTargetRef?: string; + readonly receiptRequired: boolean; + }>; + readonly absEvidenceExport: { + readonly purpose: string; + readonly format: "json-lines"; + readonly requiredFields: readonly string[]; + readonly dataQualityRules: readonly Array<{ + readonly ruleId: string; + readonly description: string; + readonly maxSkewMs?: number; + readonly required?: boolean; + }>; + }; + readonly fmeaExport: readonly Array<{ + readonly failureMode: string; + readonly sourceScenarioId: string; + readonly hazard: string; + readonly sintDetection: string; + readonly sintControl: string; + readonly severity: number; + readonly occurrence: number; + readonly detection: number; + readonly requiredEvidence: readonly string[]; + }>; + readonly safetyCaseMapping: readonly Array<{ + readonly topic: string; + readonly sintSupport: string; + readonly claimBoundary: string; + }>; + readonly sprintPlan: { + readonly duration: string; + readonly goal: string; + readonly workstreams: readonly Array<{ + readonly id: string; + readonly name: string; + readonly deliverables: readonly string[]; + }>; + }; + readonly successCriteria: { + readonly hotWorkPermitCovered: boolean; + readonly fireWatchCovered: boolean; + readonly fumeExtractionCovered: boolean; + readonly unsafeAtmosphereCovered: boolean; + readonly bystanderInWeldZoneCovered: boolean; + readonly simulationReceiptMismatchCovered: boolean; + readonly supervisorApprovalForWeldingCovered: boolean; + readonly loadEnvelopeCovered: boolean; + readonly estopRollbackCovered: boolean; + readonly absEvidenceExportHasDataQualityRules: boolean; + readonly fmeaRowsReferenceExecutableScenarios: boolean; + readonly claimsRemainSupportOnly: boolean; + }; +} + +export function loadIndustrialHumanoidShipyardSafetyPackFixture(): IndustrialHumanoidShipyardSafetyPackFixture { + return loadFixture( + "industrial/industrial-humanoid-shipyard-safety-pack.v1.json", + ); +} + export interface FactoryActionDemoFixture { readonly fixtureId: string; readonly schemaVersion: string; diff --git a/packages/conformance-tests/src/industrial-humanoid-shipyard-safety-pack-conformance.test.ts b/packages/conformance-tests/src/industrial-humanoid-shipyard-safety-pack-conformance.test.ts new file mode 100644 index 0000000..6df50e2 --- /dev/null +++ b/packages/conformance-tests/src/industrial-humanoid-shipyard-safety-pack-conformance.test.ts @@ -0,0 +1,200 @@ +/** + * Industrial humanoid shipyard safety pack conformance. + * + * This fixture makes the Persona-style use case executable without depending on + * Persona internals: shipyard humanoids, hot work, welding, confined spaces, + * bystander safety, simulation receipts, ABS-style evidence export, and + * support-only safety-case boundaries. + */ + +import { describe, expect, it } from "vitest"; +import { ApprovalTier } from "@pshkv/core"; +import { loadIndustrialHumanoidShipyardSafetyPackFixture } from "./fixture-loader.js"; + +function riskPriorityNumber(row: { + readonly severity: number; + readonly occurrence: number; + readonly detection: number; +}): number { + return row.severity * row.occurrence * row.detection; +} + +describe("Industrial humanoid shipyard safety pack fixture v1", () => { + const fixture = loadIndustrialHumanoidShipyardSafetyPackFixture(); + + it("declares the shipyard humanoid scope and keeps certification boundaries explicit", () => { + expect(fixture.fixtureId).toBe("industrial-humanoid-shipyard-safety-pack-v1"); + expect(fixture.deployment.profile).toBe("industrial-humanoid-shipyard"); + expect(fixture.deployment.actors).toEqual( + expect.arrayContaining(["fire-watch", "abs-remote-surveyor", "safety-plc"]), + ); + expect(fixture.scopeNote).toContain("not a shipyard certification"); + expect(fixture.scopeNote).toContain("not"); + expect(fixture.successCriteria.claimsRemainSupportOnly).toBe(true); + }); + + it("defines shipyard policy templates for hot work, confined spaces, material handling, and inspection", () => { + expect(fixture.policyTemplates.map((template) => template.templateId)).toEqual([ + "shipyard-hot-work-welding", + "shipyard-confined-space-entry", + "shipyard-material-handling", + "shipyard-visual-inspection", + ]); + + const hotWork = fixture.policyTemplates.find( + (template) => template.templateId === "shipyard-hot-work-welding", + ); + expect(hotWork?.defaultTier).toBe(ApprovalTier.T3_COMMIT); + expect(hotWork?.requiredPermits).toEqual( + expect.arrayContaining([ + "hotWorkPermit", + "fireWatchReady", + "fumeExtractionOnline", + "gasAtmosphereSafe", + "simulationReceipt", + ]), + ); + + for (const template of fixture.policyTemplates) { + expect(template.requiredHardwareSafety).toEqual( + expect.objectContaining({ + permitState: "granted", + interlockState: "closed", + estopState: "clear", + }), + ); + expect(template.requiredHardwareSafety.maxObservedAgeMs).toBeLessThanOrEqual(5000); + } + }); + + it("covers the minimum shipyard hazard scenarios with deterministic decisions", () => { + const byId = new Map(fixture.shipyardScenarios.map((scenario) => [scenario.id, scenario])); + + expect([...byId.keys()]).toEqual([ + "visual-inspection-allowed", + "weld-start-without-hot-work-permit", + "weld-start-fire-watch-not-ready", + "fume-extraction-offline", + "unsafe-atmosphere-confined-space", + "bystander-in-weld-zone", + "simulation-receipt-mismatch", + "valid-weld-start-requires-supervisor-approval", + "material-lift-over-envelope", + "estop-during-weld", + ]); + + expect(byId.get("visual-inspection-allowed")?.expectedTier).toBe(ApprovalTier.T0_OBSERVE); + expect(byId.get("visual-inspection-allowed")?.expectedDecision).toBe("allow"); + + expect(byId.get("weld-start-without-hot-work-permit")?.policyViolated).toBe( + "HOT_WORK_PERMIT_REQUIRED", + ); + expect(byId.get("weld-start-fire-watch-not-ready")?.policyViolated).toBe( + "FIRE_WATCH_REQUIRED", + ); + expect(byId.get("fume-extraction-offline")?.policyViolated).toBe( + "FUME_EXTRACTION_REQUIRED", + ); + expect(byId.get("unsafe-atmosphere-confined-space")?.policyViolated).toBe( + "ATMOSPHERE_UNSAFE", + ); + expect(byId.get("bystander-in-weld-zone")?.expectedDecision).toBe("escalate"); + expect(byId.get("bystander-in-weld-zone")?.physicalContext?.humanDetected).toBe(true); + expect(byId.get("simulation-receipt-mismatch")?.policyViolated).toBe( + "SIMULATION_RECEIPT_MISMATCH", + ); + expect(byId.get("valid-weld-start-requires-supervisor-approval")?.expectedTier).toBe( + ApprovalTier.T3_COMMIT, + ); + expect(byId.get("material-lift-over-envelope")?.policyViolated).toBe( + "LOAD_LIMIT_EXCEEDED", + ); + expect(byId.get("estop-during-weld")?.expectedDecision).toBe("rollback"); + expect(byId.get("estop-during-weld")?.rollbackTargetRef).toMatch(/^sint:\/\/action\//); + }); + + it("requires receipts for every shipyard outcome and high-consequence action", () => { + for (const scenario of fixture.shipyardScenarios) { + expect(scenario.receiptRequired, scenario.id).toBe(true); + expect(scenario.hardwareSafety.controllerId, scenario.id).toContain("safety-plc"); + expect(scenario.hardwareSafety.observedAgeMs, scenario.id).toBeLessThanOrEqual(2500); + + if (scenario.operation === "arc_weld_start") { + expect(scenario.expectedTier, scenario.id).toBe(ApprovalTier.T3_COMMIT); + } + + if (scenario.expectedDecision !== "allow") { + expect(scenario.policyViolated, scenario.id).toBeDefined(); + } + } + }); + + it("binds simulation receipts to offline welding program digests", () => { + const drift = fixture.shipyardScenarios.find( + (scenario) => scenario.id === "simulation-receipt-mismatch", + ); + const valid = fixture.shipyardScenarios.find( + (scenario) => scenario.id === "valid-weld-start-requires-supervisor-approval", + ); + + expect(drift?.simulation?.expectedProgramDigest).not.toBe( + drift?.simulation?.submittedProgramDigest, + ); + expect(drift?.expectedDecision).toBe("deny"); + expect(valid?.simulation?.expectedProgramDigest).toBe( + valid?.simulation?.submittedProgramDigest, + ); + expect(valid?.expectedDecision).toBe("escalate"); + }); + + it("defines ABS-style evidence export fields and data quality rules", () => { + expect(fixture.absEvidenceExport.format).toBe("json-lines"); + expect(fixture.absEvidenceExport.requiredFields).toEqual( + expect.arrayContaining([ + "siteId", + "vesselBlockId", + "robotId", + "workOrderId", + "weldProcedureSpecId", + "hotWorkPermitId", + "gasMonitorCalibrationRef", + "simulationReceiptDigest", + "policyDecision", + "eventHash", + "previousHash", + ]), + ); + + expect(fixture.absEvidenceExport.dataQualityRules.map((rule) => rule.ruleId)).toEqual([ + "shipyard-evidence-clock-sync", + "shipyard-evidence-calibrated-sensors", + "shipyard-evidence-program-binding", + ]); + expect(fixture.successCriteria.absEvidenceExportHasDataQualityRules).toBe(true); + }); + + it("exports FMEA rows tied to executable scenarios", () => { + const scenarioIds = new Set(fixture.shipyardScenarios.map((scenario) => scenario.id)); + expect(fixture.fmeaExport.length).toBeGreaterThanOrEqual(6); + + for (const row of fixture.fmeaExport) { + expect(scenarioIds.has(row.sourceScenarioId), row.failureMode).toBe(true); + expect(riskPriorityNumber(row), row.failureMode).toBeGreaterThan(0); + expect(row.requiredEvidence, row.failureMode).toContain("eventHash"); + expect(row.sintControl.length, row.failureMode).toBeGreaterThan(0); + } + }); + + it("keeps the sprint plan complete enough for execution tracking", () => { + expect(fixture.sprintPlan.duration).toBe("2 weeks"); + expect(fixture.sprintPlan.workstreams.map((stream) => stream.id)).toEqual([ + "S1", + "S2", + "S3", + "S4", + ]); + for (const stream of fixture.sprintPlan.workstreams) { + expect(stream.deliverables.length, stream.name).toBeGreaterThanOrEqual(3); + } + }); +});