@aria_asi/cli 0.2.39 → 0.2.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aria.js +236 -34
- package/dist/aria-connector/src/action-ledger-core.d.ts +387 -0
- package/dist/aria-connector/src/action-ledger-core.d.ts.map +1 -0
- package/dist/aria-connector/src/action-ledger-core.js +638 -0
- package/dist/aria-connector/src/action-ledger-core.js.map +1 -0
- package/dist/aria-connector/src/chat.d.ts.map +1 -1
- package/dist/aria-connector/src/chat.js +5 -6
- package/dist/aria-connector/src/chat.js.map +1 -1
- package/dist/aria-connector/src/codebase-scanner.d.ts +1 -1
- package/dist/aria-connector/src/codebase-scanner.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/claude-code.d.ts +1 -0
- package/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/claude-code.js +152 -14
- package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
- package/dist/aria-connector/src/connectors/codebase-awareness.d.ts +10 -0
- package/dist/aria-connector/src/connectors/codebase-awareness.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/codebase-awareness.js +276 -27
- package/dist/aria-connector/src/connectors/codebase-awareness.js.map +1 -1
- package/dist/aria-connector/src/connectors/codex.d.ts +3 -1
- package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/codex.js +1271 -40
- package/dist/aria-connector/src/connectors/codex.js.map +1 -1
- package/dist/aria-connector/src/connectors/cursor.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/cursor.js +7 -0
- package/dist/aria-connector/src/connectors/cursor.js.map +1 -1
- package/dist/aria-connector/src/connectors/governed-adapter.d.ts +30 -0
- package/dist/aria-connector/src/connectors/governed-adapter.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/governed-adapter.js +132 -0
- package/dist/aria-connector/src/connectors/governed-adapter.js.map +1 -0
- package/dist/aria-connector/src/connectors/opencode.d.ts +3 -1
- package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/opencode.js +18 -2
- package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
- package/dist/aria-connector/src/connectors/repo-guard.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/repo-guard.js +25 -14
- package/dist/aria-connector/src/connectors/repo-guard.js.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.js +92 -2
- package/dist/aria-connector/src/connectors/runtime.js.map +1 -1
- package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/shell.js +123 -7
- package/dist/aria-connector/src/connectors/shell.js.map +1 -1
- package/dist/aria-connector/src/cross-cli-hive-binding.d.ts +63 -0
- package/dist/aria-connector/src/cross-cli-hive-binding.d.ts.map +1 -0
- package/dist/aria-connector/src/cross-cli-hive-binding.js +205 -0
- package/dist/aria-connector/src/cross-cli-hive-binding.js.map +1 -0
- package/dist/aria-connector/src/garden-control-plane.d.ts +6 -1
- package/dist/aria-connector/src/garden-control-plane.d.ts.map +1 -1
- package/dist/aria-connector/src/garden-control-plane.js +8 -2
- package/dist/aria-connector/src/garden-control-plane.js.map +1 -1
- package/dist/aria-connector/src/governed-surface-runner.d.ts +189 -0
- package/dist/aria-connector/src/governed-surface-runner.d.ts.map +1 -0
- package/dist/aria-connector/src/governed-surface-runner.js +1022 -0
- package/dist/aria-connector/src/governed-surface-runner.js.map +1 -0
- package/dist/aria-connector/src/index.d.ts +10 -1
- package/dist/aria-connector/src/index.d.ts.map +1 -1
- package/dist/aria-connector/src/index.js +5 -0
- package/dist/aria-connector/src/index.js.map +1 -1
- package/dist/aria-connector/src/task-runner.d.ts +3 -0
- package/dist/aria-connector/src/task-runner.d.ts.map +1 -0
- package/dist/aria-connector/src/task-runner.js +3526 -0
- package/dist/aria-connector/src/task-runner.js.map +1 -0
- package/dist/aria-web/src/lib/codebase-scanner.d.ts +21 -2
- package/dist/aria-web/src/lib/codebase-scanner.d.ts.map +1 -1
- package/dist/aria-web/src/lib/codebase-scanner.js +59 -14
- package/dist/aria-web/src/lib/codebase-scanner.js.map +1 -1
- package/dist/assets/hooks/README.md +58 -0
- package/dist/assets/hooks/aria-agent-handoff.mjs +147 -2
- package/dist/assets/hooks/aria-agent-ledger-merge.mjs +31 -7
- package/dist/assets/hooks/aria-architect-fallback.mjs +10 -2
- package/dist/assets/hooks/aria-claim-evidence-stop-gate.mjs +240 -0
- package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +84 -10
- package/dist/assets/hooks/aria-first-class-coach.mjs +305 -10
- package/dist/assets/hooks/aria-harness-via-sdk.mjs +93 -16
- package/dist/assets/hooks/aria-import-resolution-gate.mjs +106 -20
- package/dist/assets/hooks/aria-outcome-record.mjs +56 -20
- package/dist/assets/hooks/aria-pre-emit-autoload.mjs +1809 -0
- package/dist/assets/hooks/aria-pre-emit-autoload.mjs.before-orchestration-redesign +1400 -0
- package/dist/assets/hooks/aria-pre-emit-dryrun.mjs +22 -3
- package/dist/assets/hooks/aria-pre-text-gate.mjs +11 -2
- package/dist/assets/hooks/aria-pre-tool-gate.mjs +516 -92
- package/dist/assets/hooks/aria-pre-tool-use.mjs +70 -6
- package/dist/assets/hooks/aria-preprompt-consult.mjs +23 -4
- package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +29 -3
- package/dist/assets/hooks/aria-stop-gate.mjs +585 -76
- package/dist/assets/hooks/aria-trigger-autolearn.mjs +17 -3
- package/dist/assets/hooks/aria-universal-turn-packet.mjs +1165 -0
- package/dist/assets/hooks/aria-userprompt-abandon-detect.mjs +9 -1
- package/dist/assets/hooks/canonical-settings-block.json +172 -0
- package/dist/assets/hooks/codex-native/aria-harness-ticker-sidecar.mjs +92 -0
- package/dist/assets/hooks/codex-native/aria-hive-wal-consumer.mjs +86 -0
- package/dist/assets/hooks/codex-native/aria-live-ticker.mjs +38 -0
- package/dist/assets/hooks/codex-native/aria-post-tool-use.mjs +236 -0
- package/dist/assets/hooks/codex-native/aria-pre-tool-use.mjs +362 -0
- package/dist/assets/hooks/codex-native/aria-stop.mjs +691 -0
- package/dist/assets/hooks/codex-native/aria-userprompt-submit.mjs +623 -0
- package/dist/assets/hooks/codex-native/atlas-session-context.mjs +121 -0
- package/dist/assets/hooks/codex-native/lib/evaluate-with-kernel.mjs +257 -0
- package/dist/assets/hooks/codex-native/lib/hive-wal-consumer.mjs +452 -0
- package/dist/assets/hooks/codex-native/lib/kernel/deterministic-cognitive-kernel.mjs +914 -0
- package/dist/assets/hooks/codex-native/lib/project-boundary-cognition.mjs +143 -0
- package/dist/assets/hooks/codex-native/lib/runtime-client.mjs +3567 -0
- package/dist/assets/hooks/codex-native/lib/task-project-ledger.mjs +294 -0
- package/dist/assets/hooks/doctrine_trigger_map.json +236 -25
- package/dist/assets/hooks/doctrine_trigger_map.schema.json +46 -0
- package/dist/assets/hooks/install.sh +84 -0
- package/dist/assets/hooks/lib/action-ledger-core.mjs +269 -0
- package/dist/assets/hooks/lib/aria-gate-ledger.mjs +143 -0
- package/dist/assets/hooks/lib/ast-stub-shape-detector.mjs +107 -0
- package/dist/assets/hooks/lib/atlas-dossier-client.mjs +151 -0
- package/dist/assets/hooks/lib/atlas-orchestrator-postwire.mjs +221 -0
- package/dist/assets/hooks/lib/canonical-lenses.mjs +83 -6
- package/dist/assets/hooks/lib/coach-intent-classifier.mjs +248 -0
- package/dist/assets/hooks/lib/cognitive-block-parser.mjs +111 -0
- package/dist/assets/hooks/lib/doctrine-trigger-map-loader.mjs +137 -0
- package/dist/assets/hooks/lib/domain-output-quality.mjs +132 -3
- package/dist/assets/hooks/lib/empty-catch-scanner.mjs +91 -0
- package/dist/assets/hooks/lib/end-phase-qa-autofire.mjs +426 -0
- package/dist/assets/hooks/lib/evaluate-with-kernel.mjs +133 -0
- package/dist/assets/hooks/lib/first-class-coach.mjs +454 -19
- package/dist/assets/hooks/lib/gate-audit.mjs +12 -2
- package/dist/assets/hooks/lib/gate-loop-state.mjs +11 -2
- package/dist/assets/hooks/lib/goal-contract-quality.mjs +302 -0
- package/dist/assets/hooks/lib/hook-message-window.mjs +101 -9
- package/dist/assets/hooks/lib/invocation-required-verifier.mjs +184 -0
- package/dist/assets/hooks/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
- package/dist/assets/hooks/lib/obligation-ledger.mjs +147 -0
- package/dist/assets/hooks/lib/orchestration-manifest-extract.mjs +217 -0
- package/dist/assets/hooks/lib/owner-authorizations.mjs +269 -0
- package/dist/assets/hooks/lib/probe-discipline-scanner.mjs +142 -0
- package/dist/assets/hooks/lib/project-boundary-cognition.mjs +143 -0
- package/dist/assets/hooks/lib/recovery-context.mjs +151 -0
- package/dist/assets/hooks/lib/recovery-template-loader.mjs +154 -0
- package/dist/assets/hooks/lib/self-doctrine-check.mjs +321 -0
- package/dist/assets/hooks/lib/sensitive-shape-detector.mjs +64 -0
- package/dist/assets/hooks/lib/skill-autoload-gate-impl.mjs +226 -1
- package/dist/assets/hooks/lib/stop-hook-protocol.mjs +166 -0
- package/dist/assets/hooks/lib/surface-caught.mjs +94 -0
- package/dist/assets/hooks/recovery-templates/force-reauthor.md +67 -0
- package/dist/assets/hooks/recovery-templates/handoff-recovery.md +25 -0
- package/dist/assets/hooks/scripts/check-hard-risk-prefix.mjs +99 -0
- package/dist/assets/hooks/skills/aria-conversational-doctrine-discipline/SKILL.md +101 -0
- package/dist/assets/hooks/test-aria-preturn-memory-gate.mjs +2 -2
- package/dist/assets/hooks/test-tier-lens-labeling.mjs +14 -3
- package/dist/assets/opencode-plugins/harness-context/index.js +39 -6
- package/dist/assets/opencode-plugins/harness-context/task-project-ledger.mjs +5 -1
- package/dist/assets/opencode-plugins/harness-gate/index.js +36 -0
- package/dist/assets/opencode-plugins/harness-gate/lib/atlas-dossier-client.js +1 -0
- package/dist/assets/opencode-plugins/harness-gate/lib/recovery-grants.js +79 -0
- package/dist/assets/opencode-plugins/harness-outcome/index.js +12 -0
- package/dist/assets/opencode-plugins/harness-stop/index.js +97 -2
- package/dist/assets/opencode-plugins/harness-stop/lib/atlas-dossier-client.js +1 -0
- package/dist/assets/opencode-plugins/harness-stop/lib/domain-output-quality.js +15 -2
- package/dist/assets/opencode-plugins/lib/coach.js +148 -0
- package/dist/runtime/coach-kernel.mjs +144 -7
- package/dist/runtime/codex-bridge.mjs +254 -8
- package/dist/runtime/discipline/doctrine_trigger_map.json +236 -25
- package/dist/runtime/discipline/skills/aria-cognition/34-frameworks-unified/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-cognitives/SKILL.md +128 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-intra-phase/SKILL.md +99 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-post-phase/SKILL.md +118 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-pre-phase/SKILL.md +117 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-axioms-first-principles/SKILL.md +202 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-axioms-first-principles/agents/openai.yaml +4 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-axioms-first-principles/references/source-map.md +130 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-backend-architect/SKILL.md +124 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-backend-architect/references/backend-cookbook.md +417 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-business-audit/SKILL.md +133 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-business-audit/references/audit-cookbook.md +247 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-business-frame/SKILL.md +138 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-business-frame/references/business-cookbook.md +154 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-chat/SKILL.md +84 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-chat/scripts/aria-chat.sh +57 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-cognition-autofire/SKILL.md +137 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-cognition-batch/SKILL.md +264 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-decision-mizan/SKILL.md +136 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-decision-mizan/references/decision-frameworks.md +287 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-first-class-operating-contract/SKILL.md +104 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-frontend-architect/SKILL.md +123 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-frontend-architect/references/frontend-cookbook.md +358 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-fullstack-orchestrator/SKILL.md +127 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-fullstack-orchestrator/references/fullstack-cookbook.md +383 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-gtm-architect/SKILL.md +126 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-gtm-architect/references/gtm-cookbook.md +235 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-harness-deploy/SKILL.md +145 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-harness-no-stripping/SKILL.md +135 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-harness-onboarding/SKILL.md +130 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-harness-output-discipline/SKILL.md +120 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-harness-substrate-binding/SKILL.md +139 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-http-harness-client/SKILL.md +85 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-http-harness-client/scripts/smoke.mjs +47 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-k8s-deploy/SKILL.md +174 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-k8s-deploy/agents/openai.yaml +3 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-ladduniframe/SKILL.md +60 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-ledger-fleet-execution/SKILL.md +126 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-live-ops/SKILL.md +54 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-mac-ssh-ops/SKILL.md +100 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-memory-index/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-noor-cognitives/SKILL.md +120 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-ops/SKILL.md +60 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-ops/references/live-endpoints.md +59 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-quality-audit/SKILL.md +133 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-readable-output/SKILL.md +239 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-readable-output/references/layout-cookbook.md +366 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-reasoning/SKILL.md +67 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-reasoning/references/core-principles.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-repo-audit/SKILL.md +135 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-repo-audit/references/repo-audit-cookbook.md +375 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-research-orchestrator/SKILL.md +138 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-research-orchestrator/references/research-patterns.md +270 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-retention-engine/SKILL.md +120 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-retention-engine/references/retention-cookbook.md +271 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-revenue-engine/SKILL.md +128 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-revenue-engine/references/revenue-cookbook.md +227 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-audit/SKILL.md +233 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-audit/references/audit-checklist.md +369 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-cookbook/SKILL.md +288 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-cookbook/references/engineering-cookbook.md +489 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-soul-principles/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-task-codex-executor/SKILL.md +86 -0
- package/dist/runtime/discipline/skills/aria-cognition/aristotle-engine/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/cross-domain-24/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/deepsoul-emotional/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/fitrah-guard/SKILL.md +78 -0
- package/dist/runtime/discipline/skills/aria-cognition/ghazali-8lens/SKILL.md +227 -29
- package/dist/runtime/discipline/skills/aria-cognition/ghazali-8lens/references/ghazali-8lens-cookbook.md +797 -0
- package/dist/runtime/discipline/skills/aria-cognition/ijtihad-novel/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/ilham-intuition/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/never-guess/SKILL.md +77 -0
- package/dist/runtime/discipline/skills/aria-cognition/noor-recognition/SKILL.md +45 -0
- package/dist/runtime/discipline/skills/aria-cognition/qiyas-analogy/SKILL.md +174 -14
- package/dist/runtime/discipline/skills/aria-cognition/ruh-basis/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/tadabbur/SKILL.md +506 -0
- package/dist/runtime/discipline/skills/aria-cognition/tadabbur/references/tadabbur-cookbook.md +921 -0
- package/dist/runtime/discipline/skills/aria-cognition/tadabbur-ops/SKILL.md +42 -0
- package/dist/runtime/discipline/skills/aria-cognition/tafakkur/SKILL.md +104 -0
- package/dist/runtime/doctrine_trigger_map.json +236 -25
- package/dist/runtime/embedded-public-key.mjs +27 -0
- package/dist/runtime/gated-ledger.mjs +41 -14
- package/dist/runtime/harness-daemon.mjs +85 -10
- package/dist/runtime/hive-wal-publisher.mjs +292 -0
- package/dist/runtime/hooks/README.md +58 -0
- package/dist/runtime/hooks/aria-agent-handoff.mjs +147 -2
- package/dist/runtime/hooks/aria-agent-ledger-merge.mjs +31 -7
- package/dist/runtime/hooks/aria-architect-fallback.mjs +10 -2
- package/dist/runtime/hooks/aria-claim-evidence-stop-gate.mjs +240 -0
- package/dist/runtime/hooks/aria-cognition-substrate-binding.mjs +84 -10
- package/dist/runtime/hooks/aria-first-class-coach.mjs +305 -10
- package/dist/runtime/hooks/aria-harness-via-sdk.mjs +93 -16
- package/dist/runtime/hooks/aria-import-resolution-gate.mjs +106 -20
- package/dist/runtime/hooks/aria-outcome-record.mjs +56 -20
- package/dist/runtime/hooks/aria-pre-emit-autoload.mjs +1809 -0
- package/dist/runtime/hooks/aria-pre-emit-autoload.mjs.before-orchestration-redesign +1400 -0
- package/dist/runtime/hooks/aria-pre-emit-dryrun.mjs +22 -3
- package/dist/runtime/hooks/aria-pre-text-gate.mjs +11 -2
- package/dist/runtime/hooks/aria-pre-tool-gate.mjs +516 -92
- package/dist/runtime/hooks/aria-pre-tool-use.mjs +70 -6
- package/dist/runtime/hooks/aria-preprompt-consult.mjs +23 -4
- package/dist/runtime/hooks/aria-repo-doctrine-gate.mjs +29 -3
- package/dist/runtime/hooks/aria-stop-gate.mjs +585 -76
- package/dist/runtime/hooks/aria-trigger-autolearn.mjs +17 -3
- package/dist/runtime/hooks/aria-universal-turn-packet.mjs +1165 -0
- package/dist/runtime/hooks/aria-userprompt-abandon-detect.mjs +9 -1
- package/dist/runtime/hooks/canonical-settings-block.json +172 -0
- package/dist/runtime/hooks/codex-native/aria-harness-ticker-sidecar.mjs +92 -0
- package/dist/runtime/hooks/codex-native/aria-hive-wal-consumer.mjs +86 -0
- package/dist/runtime/hooks/codex-native/aria-live-ticker.mjs +38 -0
- package/dist/runtime/hooks/codex-native/aria-post-tool-use.mjs +236 -0
- package/dist/runtime/hooks/codex-native/aria-pre-tool-use.mjs +362 -0
- package/dist/runtime/hooks/codex-native/aria-stop.mjs +691 -0
- package/dist/runtime/hooks/codex-native/aria-userprompt-submit.mjs +623 -0
- package/dist/runtime/hooks/codex-native/atlas-session-context.mjs +121 -0
- package/dist/runtime/hooks/codex-native/lib/evaluate-with-kernel.mjs +257 -0
- package/dist/runtime/hooks/codex-native/lib/hive-wal-consumer.mjs +452 -0
- package/dist/runtime/hooks/codex-native/lib/kernel/deterministic-cognitive-kernel.mjs +914 -0
- package/dist/runtime/hooks/codex-native/lib/project-boundary-cognition.mjs +143 -0
- package/dist/runtime/hooks/codex-native/lib/runtime-client.mjs +3567 -0
- package/dist/runtime/hooks/codex-native/lib/task-project-ledger.mjs +294 -0
- package/dist/runtime/hooks/doctrine_trigger_map.json +236 -25
- package/dist/runtime/hooks/doctrine_trigger_map.schema.json +46 -0
- package/dist/runtime/hooks/install.sh +84 -0
- package/dist/runtime/hooks/lib/action-ledger-core.mjs +269 -0
- package/dist/runtime/hooks/lib/aria-gate-ledger.mjs +143 -0
- package/dist/runtime/hooks/lib/ast-stub-shape-detector.mjs +107 -0
- package/dist/runtime/hooks/lib/atlas-dossier-client.mjs +151 -0
- package/dist/runtime/hooks/lib/atlas-orchestrator-postwire.mjs +221 -0
- package/dist/runtime/hooks/lib/canonical-lenses.mjs +83 -6
- package/dist/runtime/hooks/lib/coach-intent-classifier.mjs +248 -0
- package/dist/runtime/hooks/lib/cognitive-block-parser.mjs +111 -0
- package/dist/runtime/hooks/lib/doctrine-trigger-map-loader.mjs +137 -0
- package/dist/runtime/hooks/lib/domain-output-quality.mjs +132 -3
- package/dist/runtime/hooks/lib/empty-catch-scanner.mjs +91 -0
- package/dist/runtime/hooks/lib/end-phase-qa-autofire.mjs +426 -0
- package/dist/runtime/hooks/lib/evaluate-with-kernel.mjs +133 -0
- package/dist/runtime/hooks/lib/first-class-coach.mjs +454 -19
- package/dist/runtime/hooks/lib/gate-audit.mjs +12 -2
- package/dist/runtime/hooks/lib/gate-loop-state.mjs +11 -2
- package/dist/runtime/hooks/lib/goal-contract-quality.mjs +302 -0
- package/dist/runtime/hooks/lib/hook-message-window.mjs +101 -9
- package/dist/runtime/hooks/lib/invocation-required-verifier.mjs +184 -0
- package/dist/runtime/hooks/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
- package/dist/runtime/hooks/lib/obligation-ledger.mjs +147 -0
- package/dist/runtime/hooks/lib/orchestration-manifest-extract.mjs +217 -0
- package/dist/runtime/hooks/lib/owner-authorizations.mjs +269 -0
- package/dist/runtime/hooks/lib/probe-discipline-scanner.mjs +142 -0
- package/dist/runtime/hooks/lib/project-boundary-cognition.mjs +143 -0
- package/dist/runtime/hooks/lib/recovery-context.mjs +151 -0
- package/dist/runtime/hooks/lib/recovery-template-loader.mjs +154 -0
- package/dist/runtime/hooks/lib/self-doctrine-check.mjs +321 -0
- package/dist/runtime/hooks/lib/sensitive-shape-detector.mjs +64 -0
- package/dist/runtime/hooks/lib/skill-autoload-gate-impl.mjs +226 -1
- package/dist/runtime/hooks/lib/stop-hook-protocol.mjs +166 -0
- package/dist/runtime/hooks/lib/surface-caught.mjs +94 -0
- package/dist/runtime/hooks/recovery-templates/force-reauthor.md +67 -0
- package/dist/runtime/hooks/recovery-templates/handoff-recovery.md +25 -0
- package/dist/runtime/hooks/scripts/check-hard-risk-prefix.mjs +99 -0
- package/dist/runtime/hooks/skills/aria-conversational-doctrine-discipline/SKILL.md +101 -0
- package/dist/runtime/hooks/test-aria-preturn-memory-gate.mjs +2 -2
- package/dist/runtime/hooks/test-tier-lens-labeling.mjs +14 -3
- package/dist/runtime/lib/evaluate-with-kernel.mjs +133 -0
- package/dist/runtime/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
- package/dist/runtime/local-phase.mjs +10 -5
- package/dist/runtime/manifest.json +8 -8
- package/dist/runtime/packet-verifier.mjs +166 -0
- package/dist/runtime/provider-proxy.mjs +13 -0
- package/dist/runtime/quality-enforcer.mjs +40 -23
- package/dist/runtime/runtime-rails/registry.mjs +252 -0
- package/dist/runtime/sdk/BUNDLED.json +2 -2
- package/dist/runtime/sdk/index.d.ts +119 -4
- package/dist/runtime/sdk/index.js +138 -12
- package/dist/runtime/sdk/index.js.map +1 -1
- package/dist/runtime/service.mjs +8036 -764
- package/dist/runtime/sub-agent-enforcer.mjs +201 -0
- package/dist/runtime/task-project-ledger.mjs +5 -1
- package/dist/sdk/BUNDLED.json +2 -2
- package/dist/sdk/index.d.ts +119 -4
- package/dist/sdk/index.js +138 -12
- package/dist/sdk/index.js.map +1 -1
- package/hooks/README.md +58 -0
- package/hooks/aria-agent-handoff.mjs +147 -2
- package/hooks/aria-agent-ledger-merge.mjs +31 -7
- package/hooks/aria-architect-fallback.mjs +10 -2
- package/hooks/aria-claim-evidence-stop-gate.mjs +240 -0
- package/hooks/aria-cognition-substrate-binding.mjs +84 -10
- package/hooks/aria-first-class-coach.mjs +305 -10
- package/hooks/aria-harness-via-sdk.mjs +93 -16
- package/hooks/aria-import-resolution-gate.mjs +106 -20
- package/hooks/aria-outcome-record.mjs +56 -20
- package/hooks/aria-pre-emit-autoload.mjs +1809 -0
- package/hooks/aria-pre-emit-autoload.mjs.before-orchestration-redesign +1400 -0
- package/hooks/aria-pre-emit-dryrun.mjs +22 -3
- package/hooks/aria-pre-text-gate.mjs +11 -2
- package/hooks/aria-pre-tool-gate.mjs +516 -92
- package/hooks/aria-pre-tool-use.mjs +70 -6
- package/hooks/aria-preprompt-consult.mjs +23 -4
- package/hooks/aria-repo-doctrine-gate.mjs +29 -3
- package/hooks/aria-stop-gate.mjs +585 -76
- package/hooks/aria-trigger-autolearn.mjs +17 -3
- package/hooks/aria-universal-turn-packet.mjs +1165 -0
- package/hooks/aria-userprompt-abandon-detect.mjs +9 -1
- package/hooks/canonical-settings-block.json +172 -0
- package/hooks/codex-native/aria-harness-ticker-sidecar.mjs +92 -0
- package/hooks/codex-native/aria-hive-wal-consumer.mjs +86 -0
- package/hooks/codex-native/aria-live-ticker.mjs +38 -0
- package/hooks/codex-native/aria-post-tool-use.mjs +236 -0
- package/hooks/codex-native/aria-pre-tool-use.mjs +362 -0
- package/hooks/codex-native/aria-stop.mjs +691 -0
- package/hooks/codex-native/aria-userprompt-submit.mjs +623 -0
- package/hooks/codex-native/atlas-session-context.mjs +121 -0
- package/hooks/codex-native/lib/evaluate-with-kernel.mjs +257 -0
- package/hooks/codex-native/lib/hive-wal-consumer.mjs +452 -0
- package/hooks/codex-native/lib/kernel/deterministic-cognitive-kernel.mjs +914 -0
- package/hooks/codex-native/lib/project-boundary-cognition.mjs +143 -0
- package/hooks/codex-native/lib/runtime-client.mjs +3567 -0
- package/hooks/codex-native/lib/task-project-ledger.mjs +294 -0
- package/hooks/doctrine_trigger_map.json +236 -25
- package/hooks/doctrine_trigger_map.schema.json +46 -0
- package/hooks/install.sh +84 -0
- package/hooks/lib/action-ledger-core.mjs +269 -0
- package/hooks/lib/aria-gate-ledger.mjs +143 -0
- package/hooks/lib/ast-stub-shape-detector.mjs +107 -0
- package/hooks/lib/atlas-dossier-client.mjs +151 -0
- package/hooks/lib/atlas-orchestrator-postwire.mjs +221 -0
- package/hooks/lib/canonical-lenses.mjs +83 -6
- package/hooks/lib/coach-intent-classifier.mjs +248 -0
- package/hooks/lib/cognitive-block-parser.mjs +111 -0
- package/hooks/lib/doctrine-trigger-map-loader.mjs +137 -0
- package/hooks/lib/domain-output-quality.mjs +132 -3
- package/hooks/lib/empty-catch-scanner.mjs +91 -0
- package/hooks/lib/end-phase-qa-autofire.mjs +426 -0
- package/hooks/lib/evaluate-with-kernel.mjs +133 -0
- package/hooks/lib/first-class-coach.mjs +454 -19
- package/hooks/lib/gate-audit.mjs +12 -2
- package/hooks/lib/gate-loop-state.mjs +11 -2
- package/hooks/lib/goal-contract-quality.mjs +302 -0
- package/hooks/lib/hook-message-window.mjs +101 -9
- package/hooks/lib/invocation-required-verifier.mjs +184 -0
- package/hooks/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
- package/hooks/lib/obligation-ledger.mjs +147 -0
- package/hooks/lib/orchestration-manifest-extract.mjs +217 -0
- package/hooks/lib/owner-authorizations.mjs +269 -0
- package/hooks/lib/probe-discipline-scanner.mjs +142 -0
- package/hooks/lib/project-boundary-cognition.mjs +143 -0
- package/hooks/lib/recovery-context.mjs +151 -0
- package/hooks/lib/recovery-template-loader.mjs +154 -0
- package/hooks/lib/self-doctrine-check.mjs +321 -0
- package/hooks/lib/sensitive-shape-detector.mjs +64 -0
- package/hooks/lib/skill-autoload-gate-impl.mjs +226 -1
- package/hooks/lib/stop-hook-protocol.mjs +166 -0
- package/hooks/lib/surface-caught.mjs +94 -0
- package/hooks/recovery-templates/force-reauthor.md +67 -0
- package/hooks/recovery-templates/handoff-recovery.md +25 -0
- package/hooks/scripts/check-hard-risk-prefix.mjs +99 -0
- package/hooks/skills/aria-conversational-doctrine-discipline/SKILL.md +101 -0
- package/hooks/test-aria-preturn-memory-gate.mjs +2 -2
- package/hooks/test-tier-lens-labeling.mjs +14 -3
- package/opencode-plugins/harness-context/index.js +39 -6
- package/opencode-plugins/harness-context/task-project-ledger.mjs +5 -1
- package/opencode-plugins/harness-gate/index.js +36 -0
- package/opencode-plugins/harness-gate/lib/atlas-dossier-client.js +1 -0
- package/opencode-plugins/harness-gate/lib/recovery-grants.js +79 -0
- package/opencode-plugins/harness-outcome/index.js +12 -0
- package/opencode-plugins/harness-stop/index.js +97 -2
- package/opencode-plugins/harness-stop/lib/atlas-dossier-client.js +1 -0
- package/opencode-plugins/harness-stop/lib/domain-output-quality.js +15 -2
- package/opencode-plugins/lib/coach.js +148 -0
- package/package.json +71 -5
- package/runtime-src/coach-kernel.mjs +144 -7
- package/runtime-src/codex-bridge.mjs +254 -8
- package/runtime-src/embedded-public-key.mjs +27 -0
- package/runtime-src/gated-ledger.mjs +41 -14
- package/runtime-src/harness-daemon.mjs +85 -10
- package/runtime-src/hive-wal-publisher.mjs +292 -0
- package/runtime-src/lib/evaluate-with-kernel.mjs +133 -0
- package/runtime-src/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
- package/runtime-src/local-phase.mjs +10 -5
- package/runtime-src/packet-verifier.mjs +166 -0
- package/runtime-src/provider-proxy.mjs +13 -0
- package/runtime-src/quality-enforcer.mjs +40 -23
- package/runtime-src/runtime-rails/registry.mjs +252 -0
- package/runtime-src/service.mjs +8036 -764
- package/runtime-src/sub-agent-enforcer.mjs +201 -0
- package/scripts/aria-ledger-append.mjs +337 -0
- package/scripts/aria-task-cheap-worker-dispatch.mjs +234 -0
- package/scripts/audit-of-audit-prior-tasks.mjs +194 -0
- package/scripts/audit-of-audit-this-turn.mjs +116 -0
- package/scripts/bundle-sdk.mjs +31 -5
- package/scripts/check-cli-wrapper-provider-contract.mjs +160 -0
- package/scripts/check-client-compatibility.mjs +15 -5
- package/scripts/check-client-smoke.mjs +297 -0
- package/scripts/check-codex-orchestrator-adoption.mjs +150 -0
- package/scripts/check-glm-env-wired.mjs +131 -0
- package/scripts/check-hive-local-storage-contract.mjs +91 -0
- package/scripts/check-hook-mirror.mjs +150 -0
- package/scripts/check-install-sh-drift.mjs +152 -0
- package/scripts/check-kernel-sync.mjs +101 -0
- package/scripts/check-package-artifact.mjs +152 -0
- package/scripts/check-registry-mirror.mjs +71 -0
- package/scripts/drain-owner-airtable-sync-queue.mjs +287 -0
- package/scripts/export-owner-status-sheets.mjs +589 -0
- package/scripts/live-sidecar-receipt-canary.mjs +347 -0
- package/scripts/qiyas-tadabbur-model-matrix.mjs +970 -0
- package/scripts/quality-ab-live-provider.mjs +913 -0
- package/scripts/self-test-action-ledger-core.mjs +190 -0
- package/scripts/self-test-approval-receipt-binding.mjs +122 -0
- package/scripts/self-test-autofire-quality-output.mjs +110 -0
- package/scripts/self-test-claude-code-action-ledger.mjs +132 -0
- package/scripts/self-test-claude-code-mechanical-autofire-hive.mjs +138 -0
- package/scripts/self-test-claude-code-mechanical-autofire.mjs +234 -0
- package/scripts/self-test-codebase-awareness-atlas-delta.mjs +159 -0
- package/scripts/self-test-codebase-awareness-delta-ingest.mjs +179 -0
- package/scripts/self-test-codex-live-hook-parity.mjs +84 -0
- package/scripts/self-test-codex-native-action-ledger.mjs +167 -0
- package/scripts/self-test-codex-native-hook-json-contract.mjs +74 -0
- package/scripts/self-test-codex-orchestrator-continuity.mjs +113 -0
- package/scripts/self-test-codex-readable-recovery.mjs +94 -0
- package/scripts/self-test-codex-self-harness.mjs +538 -0
- package/scripts/self-test-compiled-workunit.mjs +214 -0
- package/scripts/self-test-continuation-output-smoke.mjs +101 -0
- package/scripts/self-test-cross-cli-fleet-ticker.mjs +85 -0
- package/scripts/self-test-cross-cli-hive-adoption.mjs +125 -0
- package/scripts/self-test-cross-cli-hive-learning.mjs +146 -0
- package/scripts/self-test-cross-phase-tool-failure.mjs +110 -0
- package/scripts/self-test-cross-surface-action-ledger.mjs +149 -0
- package/scripts/self-test-end-of-phase-qa-court.mjs +616 -0
- package/scripts/self-test-evaluate-with-kernel.mjs +111 -0
- package/scripts/self-test-first-class-output-delta-proof.mjs +307 -0
- package/scripts/self-test-goal-contract-output-qa.mjs +73 -0
- package/scripts/self-test-goal-contract.mjs +35 -0
- package/scripts/self-test-governed-adapters.mjs +105 -0
- package/scripts/self-test-governed-surface-runner.mjs +198 -0
- package/scripts/self-test-harness-gates.mjs +15 -12
- package/scripts/self-test-harness-ticker-sidecar.mjs +153 -0
- package/scripts/self-test-hive-org-kernel.mjs +233 -0
- package/scripts/self-test-hive-session-coordination.mjs +156 -0
- package/scripts/self-test-hive-wal-consumer.mjs +111 -0
- package/scripts/self-test-kernel-a3-a4-selection.mjs +179 -0
- package/scripts/self-test-ledger-append.mjs +175 -0
- package/scripts/self-test-live-codex-posttool-packet-smoke.mjs +111 -0
- package/scripts/self-test-live-codex-pretool-packet-smoke.mjs +101 -0
- package/scripts/self-test-live-codex-stop-qa-kernel-smoke.mjs +43 -0
- package/scripts/self-test-live-wrapper-substrate-inventory.mjs +149 -0
- package/scripts/self-test-local-main-sync-script.mjs +47 -0
- package/scripts/self-test-mechanical-autofire-resolver.mjs +296 -0
- package/scripts/self-test-no-consult-cognitive-skills-output.mjs +135 -0
- package/scripts/self-test-owner-airtable-sync-queue.mjs +196 -0
- package/scripts/self-test-owner-airtable-sync.mjs +181 -0
- package/scripts/self-test-owner-sheets-action-ledger.mjs +100 -0
- package/scripts/self-test-production-preflight.mjs +78 -0
- package/scripts/self-test-project-boundary-cognition.mjs +79 -0
- package/scripts/self-test-qa-exec-kernel.mjs +34 -0
- package/scripts/self-test-qa-recovery-learning-loop.mjs +113 -0
- package/scripts/self-test-qiyas-label-alignment.mjs +94 -0
- package/scripts/self-test-recovery-context.mjs +110 -0
- package/scripts/self-test-repo-guard.mjs +10 -0
- package/scripts/self-test-runtime-health-self-heal.mjs +161 -0
- package/scripts/self-test-runtime-postcondition.mjs +70 -0
- package/scripts/self-test-soul-precommit-hook.mjs +39 -0
- package/scripts/self-test-stop-gate-kernel-guards.mjs +185 -0
- package/scripts/self-test-stop-gate.mjs +128 -0
- package/scripts/self-test-substrate-kernel-execution-receipt.mjs +130 -0
- package/scripts/self-test-substrate-open-skill-floor.mjs +87 -0
- package/scripts/self-test-substrate-output-quality-eval.mjs +171 -0
- package/scripts/self-test-task-closeout-drift.mjs +97 -0
- package/scripts/self-test-task-project-ledger-readiness.mjs +43 -0
- package/scripts/self-test-task-runner-phase-consumer.mjs +134 -0
- package/scripts/self-test-task-worker-lane.mjs +256 -0
- package/scripts/self-test-turn-substrate-qa-kernel.mjs +188 -0
- package/scripts/self-test-universal-action-capture.mjs +153 -0
- package/scripts/self-test-universal-turn-packet-entrypoints.mjs +252 -0
- package/scripts/self-test-universal-turn-packet.mjs +320 -0
- package/scripts/session-quality-backfill.mjs +253 -0
- package/scripts/smoke-autofire-100-prompts.mjs +481 -0
- package/scripts/sync-local-main-on-task-complete.mjs +278 -0
- package/scripts/sync-owner-status-airtable.mjs +1158 -0
- package/scripts/validate-skill-prompts.mjs +12 -1
- package/scripts/verify-codex-native-mirror.mjs +262 -0
- package/skills/34-frameworks-unified/SKILL.md +42 -0
- package/skills/api-design/SKILL.md +123 -0
- package/skills/architecture-decision/SKILL.md +105 -0
- package/skills/aria-aristotle-cognitives/SKILL.md +128 -0
- package/skills/aria-aristotle-intra-phase/SKILL.md +99 -0
- package/skills/aria-aristotle-post-phase/SKILL.md +116 -0
- package/skills/aria-aristotle-pre-phase/SKILL.md +117 -0
- package/skills/aria-axioms-first-principles/SKILL.md +202 -0
- package/skills/aria-axioms-first-principles/agents/openai.yaml +4 -0
- package/skills/aria-axioms-first-principles/references/source-map.md +130 -0
- package/skills/aria-chat/SKILL.md +84 -0
- package/skills/aria-chat/scripts/aria-chat.sh +57 -0
- package/skills/aria-cognition/34-frameworks-unified/SKILL.md +42 -0
- package/skills/aria-cognition/aria-aristotle-cognitives/SKILL.md +128 -0
- package/skills/aria-cognition/aria-aristotle-intra-phase/SKILL.md +99 -0
- package/skills/aria-cognition/aria-aristotle-post-phase/SKILL.md +118 -0
- package/skills/aria-cognition/aria-aristotle-pre-phase/SKILL.md +117 -0
- package/skills/aria-cognition/aria-axioms-first-principles/SKILL.md +202 -0
- package/skills/aria-cognition/aria-axioms-first-principles/agents/openai.yaml +4 -0
- package/skills/aria-cognition/aria-axioms-first-principles/references/source-map.md +130 -0
- package/skills/aria-cognition/aria-backend-architect/SKILL.md +124 -0
- package/skills/aria-cognition/aria-backend-architect/references/backend-cookbook.md +417 -0
- package/skills/aria-cognition/aria-business-audit/SKILL.md +133 -0
- package/skills/aria-cognition/aria-business-audit/references/audit-cookbook.md +247 -0
- package/skills/aria-cognition/aria-business-frame/SKILL.md +138 -0
- package/skills/aria-cognition/aria-business-frame/references/business-cookbook.md +154 -0
- package/skills/aria-cognition/aria-chat/SKILL.md +84 -0
- package/skills/aria-cognition/aria-chat/scripts/aria-chat.sh +57 -0
- package/skills/aria-cognition/aria-cognition-autofire/SKILL.md +137 -0
- package/skills/aria-cognition/aria-cognition-batch/SKILL.md +264 -0
- package/skills/aria-cognition/aria-decision-mizan/SKILL.md +136 -0
- package/skills/aria-cognition/aria-decision-mizan/references/decision-frameworks.md +287 -0
- package/skills/aria-cognition/aria-first-class-operating-contract/SKILL.md +104 -0
- package/skills/aria-cognition/aria-frontend-architect/SKILL.md +123 -0
- package/skills/aria-cognition/aria-frontend-architect/references/frontend-cookbook.md +358 -0
- package/skills/aria-cognition/aria-fullstack-orchestrator/SKILL.md +127 -0
- package/skills/aria-cognition/aria-fullstack-orchestrator/references/fullstack-cookbook.md +383 -0
- package/skills/aria-cognition/aria-gtm-architect/SKILL.md +126 -0
- package/skills/aria-cognition/aria-gtm-architect/references/gtm-cookbook.md +235 -0
- package/skills/aria-cognition/aria-harness-deploy/SKILL.md +145 -0
- package/skills/aria-cognition/aria-harness-no-stripping/SKILL.md +135 -0
- package/skills/aria-cognition/aria-harness-onboarding/SKILL.md +130 -0
- package/skills/aria-cognition/aria-harness-output-discipline/SKILL.md +120 -0
- package/skills/aria-cognition/aria-harness-substrate-binding/SKILL.md +139 -0
- package/skills/aria-cognition/aria-http-harness-client/SKILL.md +85 -0
- package/skills/aria-cognition/aria-http-harness-client/scripts/smoke.mjs +47 -0
- package/skills/aria-cognition/aria-k8s-deploy/SKILL.md +174 -0
- package/skills/aria-cognition/aria-k8s-deploy/agents/openai.yaml +3 -0
- package/skills/aria-cognition/aria-ladduniframe/SKILL.md +60 -0
- package/skills/aria-cognition/aria-ledger-fleet-execution/SKILL.md +126 -0
- package/skills/aria-cognition/aria-live-ops/SKILL.md +54 -0
- package/skills/aria-cognition/aria-mac-ssh-ops/SKILL.md +100 -0
- package/skills/aria-cognition/aria-memory-index/SKILL.md +42 -0
- package/skills/aria-cognition/aria-noor-cognitives/SKILL.md +120 -0
- package/skills/aria-cognition/aria-ops/SKILL.md +60 -0
- package/skills/aria-cognition/aria-ops/references/live-endpoints.md +59 -0
- package/skills/aria-cognition/aria-quality-audit/SKILL.md +133 -0
- package/skills/aria-cognition/aria-readable-output/SKILL.md +239 -0
- package/skills/aria-cognition/aria-readable-output/references/layout-cookbook.md +366 -0
- package/skills/aria-cognition/aria-reasoning/SKILL.md +67 -0
- package/skills/aria-cognition/aria-reasoning/references/core-principles.md +42 -0
- package/skills/aria-cognition/aria-repo-audit/SKILL.md +135 -0
- package/skills/aria-cognition/aria-repo-audit/references/repo-audit-cookbook.md +375 -0
- package/skills/aria-cognition/aria-research-orchestrator/SKILL.md +138 -0
- package/skills/aria-cognition/aria-research-orchestrator/references/research-patterns.md +270 -0
- package/skills/aria-cognition/aria-retention-engine/SKILL.md +120 -0
- package/skills/aria-cognition/aria-retention-engine/references/retention-cookbook.md +271 -0
- package/skills/aria-cognition/aria-revenue-engine/SKILL.md +128 -0
- package/skills/aria-cognition/aria-revenue-engine/references/revenue-cookbook.md +227 -0
- package/skills/aria-cognition/aria-senior-code-audit/SKILL.md +233 -0
- package/skills/aria-cognition/aria-senior-code-audit/references/audit-checklist.md +369 -0
- package/skills/aria-cognition/aria-senior-code-cookbook/SKILL.md +288 -0
- package/skills/aria-cognition/aria-senior-code-cookbook/references/engineering-cookbook.md +489 -0
- package/skills/aria-cognition/aria-soul-principles/SKILL.md +42 -0
- package/skills/aria-cognition/aria-task-codex-executor/SKILL.md +86 -0
- package/skills/aria-cognition/aristotle-engine/SKILL.md +42 -0
- package/skills/aria-cognition/cross-domain-24/SKILL.md +42 -0
- package/skills/aria-cognition/deepsoul-emotional/SKILL.md +42 -0
- package/skills/aria-cognition/fitrah-guard/SKILL.md +78 -0
- package/skills/aria-cognition/ghazali-8lens/SKILL.md +227 -29
- package/skills/aria-cognition/ghazali-8lens/references/ghazali-8lens-cookbook.md +797 -0
- package/skills/aria-cognition/ijtihad-novel/SKILL.md +42 -0
- package/skills/aria-cognition/ilham-intuition/SKILL.md +42 -0
- package/skills/aria-cognition/never-guess/SKILL.md +77 -0
- package/skills/aria-cognition/noor-recognition/SKILL.md +45 -0
- package/skills/aria-cognition/qiyas-analogy/SKILL.md +174 -14
- package/skills/aria-cognition/ruh-basis/SKILL.md +42 -0
- package/skills/aria-cognition/tadabbur/SKILL.md +506 -0
- package/skills/aria-cognition/tadabbur/references/tadabbur-cookbook.md +921 -0
- package/skills/aria-cognition/tadabbur-ops/SKILL.md +42 -0
- package/skills/aria-cognition/tafakkur/SKILL.md +104 -0
- package/skills/aria-cognition-autofire/SKILL.md +109 -0
- package/skills/aria-cognition-batch/SKILL.md +264 -0
- package/skills/aria-conversational-doctrine-discipline/SKILL.md +125 -0
- package/skills/aria-essence/SKILL.md +81 -0
- package/skills/aria-essence/references/domain-matrix.md +80 -0
- package/skills/aria-essence/references/evolution-loop.md +30 -0
- package/skills/aria-essence/references/readable-cognition.md +27 -0
- package/skills/aria-first-class-operating-contract/SKILL.md +104 -0
- package/skills/aria-forge-guardrails/SKILL.md +53 -0
- package/skills/aria-forge-guardrails/references/checklist.md +31 -0
- package/skills/aria-harness-deploy/SKILL.md +145 -0
- package/skills/aria-harness-no-stripping/SKILL.md +135 -0
- package/skills/aria-harness-onboarding/SKILL.md +130 -0
- package/skills/aria-harness-output-discipline/SKILL.md +120 -0
- package/skills/aria-harness-substrate-binding/SKILL.md +139 -0
- package/skills/aria-http-harness-client/SKILL.md +85 -0
- package/skills/aria-http-harness-client/scripts/smoke.mjs +47 -0
- package/skills/aria-k8s-deploy/SKILL.md +174 -0
- package/skills/aria-k8s-deploy/agents/openai.yaml +3 -0
- package/skills/aria-ladduniframe/SKILL.md +60 -0
- package/skills/aria-ledger-fleet-execution/SKILL.md +126 -0
- package/skills/aria-live-ops/SKILL.md +54 -0
- package/skills/aria-mac-ssh-ops/SKILL.md +100 -0
- package/skills/aria-memory-index/SKILL.md +42 -0
- package/skills/aria-noor-cognitives/SKILL.md +120 -0
- package/skills/aria-ops/SKILL.md +60 -0
- package/skills/aria-ops/references/live-endpoints.md +59 -0
- package/skills/aria-quality-audit/SKILL.md +133 -0
- package/skills/aria-reasoning/SKILL.md +67 -0
- package/skills/aria-reasoning/references/core-principles.md +42 -0
- package/skills/aria-repo-doctrine/SKILL.md +57 -0
- package/skills/aria-soul-principles/SKILL.md +42 -0
- package/skills/aria-task-codex-executor/SKILL.md +86 -0
- package/skills/aristotle-engine/SKILL.md +42 -0
- package/skills/ci-cd-pipeline/SKILL.md +116 -0
- package/skills/code-review/SKILL.md +131 -0
- package/skills/cross-domain-24/SKILL.md +42 -0
- package/skills/database-design/SKILL.md +124 -0
- package/skills/deepsoul-emotional/SKILL.md +42 -0
- package/skills/deno-kv-raft-pubsub/SKILL.md +561 -0
- package/skills/deno-kv-raft-pubsub/reference/maelstrom-integration.md +393 -0
- package/skills/deno-kv-raft-pubsub/reference/pubsub-api.md +376 -0
- package/skills/deno-kv-raft-pubsub/reference/raft-spec.md +402 -0
- package/skills/deno-kv-raft-pubsub/reference/state-machine.md +182 -0
- package/skills/error-handling/SKILL.md +159 -0
- package/skills/firecrawl/SKILL.md +165 -0
- package/skills/firecrawl/rules/install.md +82 -0
- package/skills/firecrawl/rules/security.md +26 -0
- package/skills/firecrawl-agent/SKILL.md +86 -0
- package/skills/firecrawl-build-interact/SKILL.md +96 -0
- package/skills/firecrawl-build-onboarding/SKILL.md +131 -0
- package/skills/firecrawl-build-onboarding/references/auth-flow.md +39 -0
- package/skills/firecrawl-build-onboarding/references/project-setup.md +20 -0
- package/skills/firecrawl-build-onboarding/references/sdk-installation.md +17 -0
- package/skills/firecrawl-build-scrape/SKILL.md +97 -0
- package/skills/firecrawl-build-search/SKILL.md +97 -0
- package/skills/firecrawl-clone/SKILL.md +419 -0
- package/skills/firecrawl-crawl/SKILL.md +87 -0
- package/skills/firecrawl-download/SKILL.md +98 -0
- package/skills/firecrawl-interact/SKILL.md +112 -0
- package/skills/firecrawl-map/SKILL.md +79 -0
- package/skills/firecrawl-scrape/SKILL.md +97 -0
- package/skills/firecrawl-search/SKILL.md +88 -0
- package/skills/fitrah-guard/SKILL.md +78 -0
- package/skills/forge-quality-rules/SKILL.md +61 -0
- package/skills/ghazali-8lens/SKILL.md +56 -0
- package/skills/ijtihad-novel/SKILL.md +42 -0
- package/skills/ilham-intuition/SKILL.md +42 -0
- package/skills/imagegen/LICENSE.txt +201 -0
- package/skills/imagegen/SKILL.md +374 -0
- package/skills/imagegen/agents/openai.yaml +6 -0
- package/skills/imagegen/assets/imagegen-small.svg +5 -0
- package/skills/imagegen/assets/imagegen.png +0 -0
- package/skills/imagegen/references/cli.md +242 -0
- package/skills/imagegen/references/codex-network.md +33 -0
- package/skills/imagegen/references/image-api.md +90 -0
- package/skills/imagegen/references/prompting.md +118 -0
- package/skills/imagegen/references/sample-prompts.md +433 -0
- package/skills/imagegen/scripts/image_gen.py +995 -0
- package/skills/imagegen/scripts/remove_chroma_key.py +440 -0
- package/skills/istiqra-induction/SKILL.md +44 -0
- package/skills/ladunni-22/SKILL.md +53 -0
- package/skills/mizan/SKILL.md +90 -0
- package/skills/nadia/SKILL.md +56 -0
- package/skills/nadia-psi/SKILL.md +56 -0
- package/skills/never-guess/SKILL.md +75 -0
- package/skills/noor-recognition/SKILL.md +45 -0
- package/skills/observability/SKILL.md +133 -0
- package/skills/openai-docs/LICENSE.txt +201 -0
- package/skills/openai-docs/SKILL.md +100 -0
- package/skills/openai-docs/agents/openai.yaml +14 -0
- package/skills/openai-docs/assets/openai-small.svg +3 -0
- package/skills/openai-docs/assets/openai.png +0 -0
- package/skills/openai-docs/references/latest-model.md +37 -0
- package/skills/openai-docs/references/prompting-guide.md +244 -0
- package/skills/openai-docs/references/upgrade-guide.md +181 -0
- package/skills/openai-docs/scripts/resolve-latest-model-info.js +147 -0
- package/skills/pdf/LICENSE.txt +201 -0
- package/skills/pdf/SKILL.md +85 -0
- package/skills/pdf/agents/openai.yaml +5 -0
- package/skills/pdf/assets/pdf.png +0 -0
- package/skills/playwright/LICENSE.txt +201 -0
- package/skills/playwright/NOTICE.txt +14 -0
- package/skills/playwright/SKILL.md +165 -0
- package/skills/playwright/agents/openai.yaml +6 -0
- package/skills/playwright/assets/playwright-small.svg +3 -0
- package/skills/playwright/assets/playwright.png +0 -0
- package/skills/playwright/references/cli.md +116 -0
- package/skills/playwright/references/workflows.md +95 -0
- package/skills/playwright/scripts/playwright_cli.sh +25 -0
- package/skills/plugin-creator/SKILL.md +178 -0
- package/skills/plugin-creator/agents/openai.yaml +6 -0
- package/skills/plugin-creator/assets/plugin-creator-small.svg +3 -0
- package/skills/plugin-creator/assets/plugin-creator.png +0 -0
- package/skills/plugin-creator/references/plugin-json-spec.md +170 -0
- package/skills/plugin-creator/scripts/create_basic_plugin.py +301 -0
- package/skills/predictor/SKILL.md +43 -0
- package/skills/qiyas-analogy/SKILL.md +204 -0
- package/skills/refactoring/SKILL.md +137 -0
- package/skills/ruh-basis/SKILL.md +42 -0
- package/skills/security-review/SKILL.md +129 -0
- package/skills/skill-creator/SKILL.md +434 -0
- package/skills/skill-creator/agents/openai.yaml +5 -0
- package/skills/skill-creator/assets/skill-creator-small.svg +3 -0
- package/skills/skill-creator/assets/skill-creator.png +0 -0
- package/skills/skill-creator/license.txt +202 -0
- package/skills/skill-creator/references/openai_yaml.md +49 -0
- package/skills/skill-creator/scripts/generate_openai_yaml.py +226 -0
- package/skills/skill-creator/scripts/init_skill.py +400 -0
- package/skills/skill-creator/scripts/quick_validate.py +101 -0
- package/skills/skill-installer/LICENSE.txt +202 -0
- package/skills/skill-installer/SKILL.md +76 -0
- package/skills/skill-installer/agents/openai.yaml +5 -0
- package/skills/skill-installer/assets/skill-installer-small.svg +3 -0
- package/skills/skill-installer/assets/skill-installer.png +0 -0
- package/skills/skill-installer/scripts/github_utils.py +21 -0
- package/skills/skill-installer/scripts/install-skill-from-github.py +308 -0
- package/skills/skill-installer/scripts/list-skills.py +107 -0
- package/skills/skills-and-hooks-reference/SKILL.md +196 -0
- package/skills/soul-domains/SKILL.md +43 -0
- package/skills/tadabbur/SKILL.md +232 -0
- package/skills/tadabbur-ops/SKILL.md +42 -0
- package/skills/tafakkur/SKILL.md +104 -0
- package/skills/testing-strategy/SKILL.md +122 -0
- package/src/action-ledger-core.ts +1054 -0
- package/src/chat.ts +5 -6
- package/src/codebase-scanner.ts +2 -0
- package/src/connectors/claude-code.ts +149 -12
- package/src/connectors/codebase-awareness.ts +325 -25
- package/src/connectors/codex.ts +1273 -40
- package/src/connectors/cursor.ts +8 -0
- package/src/connectors/governed-adapter.ts +174 -0
- package/src/connectors/opencode.ts +18 -2
- package/src/connectors/repo-guard.ts +24 -12
- package/src/connectors/runtime.ts +99 -2
- package/src/connectors/shell.ts +125 -7
- package/src/cross-cli-hive-binding.ts +290 -0
- package/src/garden-control-plane.ts +24 -1
- package/src/governed-surface-runner.ts +1227 -0
- package/src/index.ts +104 -1
- package/src/task-runner.ts +3794 -0
- package/dist/aria-connector/src/install-hooks.d.ts +0 -18
- package/dist/aria-connector/src/install-hooks.d.ts.map +0 -1
- package/dist/aria-connector/src/install-hooks.js +0 -224
- package/dist/aria-connector/src/install-hooks.js.map +0 -1
- package/dist/aria-connector/src/onboarding-wizard.d.ts +0 -5
- package/dist/aria-connector/src/onboarding-wizard.d.ts.map +0 -1
- package/dist/aria-connector/src/onboarding-wizard.js +0 -188
- package/dist/aria-connector/src/onboarding-wizard.js.map +0 -1
- package/dist/cli-0.2.38.tgz +0 -0
- package/dist/install.sh +0 -13
- package/src/__tests__/anthropic-oauth.test.ts +0 -186
- package/src/__tests__/auth-commands.test.ts +0 -132
- package/src/__tests__/owner-login.test.ts +0 -311
|
@@ -0,0 +1,3526 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, appendFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { compiledWorkUnitSummary, persistCompiledWorkUnit, projectActionLedger, readActionLedgerEvents, recordActionEventLocal, validateCompiledWorkUnitForExecution, } from './action-ledger-core.js';
|
|
7
|
+
import { UNIVERSAL_TURN_PACKET_CORRECTION_SKILL_FLOOR, UNIVERSAL_TURN_PACKET_HIVE_OBSERVER_FLOOR, UNIVERSAL_TURN_PACKET_HIVE_SIBLING_BROADCAST_FLOOR, UNIVERSAL_TURN_PACKET_HIVE_SOURCE_FLOOR, UNIVERSAL_TURN_PACKET_MAPPING_FLOOR, UNIVERSAL_TURN_PACKET_PHASES, UNIVERSAL_TURN_PACKET_PRIMITIVE_FLOOR, UNIVERSAL_TURN_PACKET_QA_SKILL_FLOOR, UNIVERSAL_TURN_PACKET_RUNTIME_FLOOR, UNIVERSAL_TURN_PACKET_SKILL_FLOOR, UNIVERSAL_TURN_PACKET_SKILLS, } from './governed-surface-runner.js';
|
|
8
|
+
const HOME = process.env.ARIA_HOME || process.env.HOME || homedir();
|
|
9
|
+
const USER_HOME = process.env.HOME || homedir();
|
|
10
|
+
const TASK_ROOT = path.join(HOME, '.aria', 'cli-tasks');
|
|
11
|
+
const RUNTIME_URL = process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319';
|
|
12
|
+
const TASK_RUNTIME_GET_TIMEOUT_MS = Number(process.env.ARIA_TASK_RUNTIME_GET_TIMEOUT_MS || 3000);
|
|
13
|
+
export const ARIA_CLI_TASK_SKILLS = Object.freeze([
|
|
14
|
+
...UNIVERSAL_TURN_PACKET_SKILLS,
|
|
15
|
+
'aria-forge-guardrails',
|
|
16
|
+
'aria-decision-mizan',
|
|
17
|
+
'aria-repo-audit',
|
|
18
|
+
'aria-live-ops',
|
|
19
|
+
'aria-memory-index',
|
|
20
|
+
'aria-ops',
|
|
21
|
+
'cross-domain-24',
|
|
22
|
+
'ladunni-22',
|
|
23
|
+
'ijtihad-novel',
|
|
24
|
+
'ilham-intuition',
|
|
25
|
+
'noor-recognition',
|
|
26
|
+
'aria-fullstack-orchestrator',
|
|
27
|
+
'aria-harness-deploy',
|
|
28
|
+
].filter((skill, index, skills) => skills.indexOf(skill) === index));
|
|
29
|
+
const ARIA_FOCUSED_PREFLIGHT_SKILLS = Object.freeze([
|
|
30
|
+
'aria-axioms-first-principles',
|
|
31
|
+
'aria-cognition-autofire',
|
|
32
|
+
'aria-first-class-operating-contract',
|
|
33
|
+
'aria-quality-audit',
|
|
34
|
+
'aria-repo-doctrine',
|
|
35
|
+
'aria-http-harness-client',
|
|
36
|
+
'aria-harness-substrate-binding',
|
|
37
|
+
'never-guess',
|
|
38
|
+
'tadabbur',
|
|
39
|
+
'qiyas-analogy',
|
|
40
|
+
'mizan',
|
|
41
|
+
]);
|
|
42
|
+
const RUN_LOOP_STEPS = Object.freeze([
|
|
43
|
+
'runtime-health-and-forced-skill-refire',
|
|
44
|
+
'claim-or-resume-cli-phase',
|
|
45
|
+
'pre-phase-ledger-receipt',
|
|
46
|
+
'mid-phase-ledger-receipt',
|
|
47
|
+
'post-phase-qiyas-tadabbur-qa',
|
|
48
|
+
'recovery-correction-enhancement-hardening-cycle',
|
|
49
|
+
'finish-phase-and-advance-or-close',
|
|
50
|
+
]);
|
|
51
|
+
const QIYAS_15 = Object.freeze([
|
|
52
|
+
'Owner-Hamza-tomorrow',
|
|
53
|
+
'operator-client',
|
|
54
|
+
'investor',
|
|
55
|
+
'LLM-consumer',
|
|
56
|
+
'human-end-user',
|
|
57
|
+
'skeptic',
|
|
58
|
+
'compliance',
|
|
59
|
+
'engineering-quality',
|
|
60
|
+
'cognitive-load',
|
|
61
|
+
'scale',
|
|
62
|
+
'Islamic-scholar',
|
|
63
|
+
'clinical-scholar',
|
|
64
|
+
'red-team-attacker',
|
|
65
|
+
'1-week-future-self',
|
|
66
|
+
'1-year-future-self',
|
|
67
|
+
]);
|
|
68
|
+
const TADABBUR_12 = Object.freeze([
|
|
69
|
+
'EMBED',
|
|
70
|
+
'EXCAVATE',
|
|
71
|
+
'ROOT TRACE',
|
|
72
|
+
'MULTI-LENS',
|
|
73
|
+
'PATTERN',
|
|
74
|
+
'CONSEQUENCE',
|
|
75
|
+
'DWELLING',
|
|
76
|
+
'COLLAPSE',
|
|
77
|
+
'PRINCIPLE',
|
|
78
|
+
'INVERSION',
|
|
79
|
+
'PERSONAL',
|
|
80
|
+
'VOICE',
|
|
81
|
+
]);
|
|
82
|
+
function ensureTaskRoot() {
|
|
83
|
+
mkdirSync(TASK_ROOT, { recursive: true, mode: 0o700 });
|
|
84
|
+
}
|
|
85
|
+
function taskPath(taskId) {
|
|
86
|
+
ensureTaskRoot();
|
|
87
|
+
return path.join(TASK_ROOT, `${sanitizeTaskId(taskId)}.json`);
|
|
88
|
+
}
|
|
89
|
+
function codexPromptPath(taskId) {
|
|
90
|
+
ensureTaskRoot();
|
|
91
|
+
return path.join(TASK_ROOT, `${sanitizeTaskId(taskId)}.codex-prompt.md`);
|
|
92
|
+
}
|
|
93
|
+
function workerPacketPath(taskId, phaseId, executor) {
|
|
94
|
+
ensureTaskRoot();
|
|
95
|
+
return path.join(TASK_ROOT, `${sanitizeTaskId(taskId)}.${sanitizePhaseId(phaseId)}.${sanitizeTaskId(executor)}.worker-packet.json`);
|
|
96
|
+
}
|
|
97
|
+
function workerIngestPath(taskId, receiptId) {
|
|
98
|
+
ensureTaskRoot();
|
|
99
|
+
return path.join(TASK_ROOT, `${sanitizeTaskId(taskId)}.${sanitizeTaskId(receiptId)}.worker-ingest.json`);
|
|
100
|
+
}
|
|
101
|
+
function workerOutputPath(taskId, phaseId, executor) {
|
|
102
|
+
ensureTaskRoot();
|
|
103
|
+
return path.join(TASK_ROOT, `${sanitizeTaskId(taskId)}.${sanitizePhaseId(phaseId)}.${sanitizeTaskId(executor)}.worker-output.json`);
|
|
104
|
+
}
|
|
105
|
+
function eventPath(taskId) {
|
|
106
|
+
ensureTaskRoot();
|
|
107
|
+
return path.join(TASK_ROOT, `${sanitizeTaskId(taskId)}.events.jsonl`);
|
|
108
|
+
}
|
|
109
|
+
function runtimePublishOutboxPath(taskId) {
|
|
110
|
+
ensureTaskRoot();
|
|
111
|
+
return path.join(TASK_ROOT, `${sanitizeTaskId(taskId)}.runtime-publish-outbox.jsonl`);
|
|
112
|
+
}
|
|
113
|
+
function readRuntimePublishOutbox(taskId) {
|
|
114
|
+
const file = runtimePublishOutboxPath(taskId);
|
|
115
|
+
if (!existsSync(file))
|
|
116
|
+
return [];
|
|
117
|
+
return readFileSync(file, 'utf8')
|
|
118
|
+
.split(/\r?\n/)
|
|
119
|
+
.map((line) => line.trim())
|
|
120
|
+
.filter(Boolean)
|
|
121
|
+
.map((line) => JSON.parse(line));
|
|
122
|
+
}
|
|
123
|
+
function writeRuntimePublishOutbox(taskId, entries) {
|
|
124
|
+
const file = runtimePublishOutboxPath(taskId);
|
|
125
|
+
const body = entries.length ? `${entries.map((entry) => JSON.stringify(entry)).join('\n')}\n` : '';
|
|
126
|
+
writeFileSync(file, body, { mode: 0o600 });
|
|
127
|
+
}
|
|
128
|
+
function sanitizeTaskId(taskId) {
|
|
129
|
+
return String(taskId || '').replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'task';
|
|
130
|
+
}
|
|
131
|
+
function sanitizePhaseId(title) {
|
|
132
|
+
const base = String(title || '').toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
133
|
+
return base || `phase-${randomUUID().slice(0, 8)}`;
|
|
134
|
+
}
|
|
135
|
+
function nowIso() {
|
|
136
|
+
return new Date().toISOString();
|
|
137
|
+
}
|
|
138
|
+
function sha256(value) {
|
|
139
|
+
return createHash('sha256').update(value).digest('hex');
|
|
140
|
+
}
|
|
141
|
+
function sha256Json(value) {
|
|
142
|
+
return sha256(typeof value === 'string' ? value : JSON.stringify(value));
|
|
143
|
+
}
|
|
144
|
+
function actionLedgerStatusForPhase(phase) {
|
|
145
|
+
if (/blocked|failed/i.test(phase))
|
|
146
|
+
return 'blocked';
|
|
147
|
+
if (/complete|completed|verified/i.test(phase))
|
|
148
|
+
return 'completed';
|
|
149
|
+
if (/qa_failed/i.test(phase))
|
|
150
|
+
return 'failed';
|
|
151
|
+
if (/recover|recovery/i.test(phase))
|
|
152
|
+
return 'repaired';
|
|
153
|
+
return 'active';
|
|
154
|
+
}
|
|
155
|
+
function actionLedgerLifecycleForPhase(phase) {
|
|
156
|
+
if (/task_start/i.test(phase))
|
|
157
|
+
return 'task_start';
|
|
158
|
+
if (/qa/i.test(phase))
|
|
159
|
+
return 'task_qa';
|
|
160
|
+
if (/recover|recovery/i.test(phase))
|
|
161
|
+
return 'task_recovery';
|
|
162
|
+
if (/complete|completed/i.test(phase))
|
|
163
|
+
return 'task_complete';
|
|
164
|
+
return 'task_phase';
|
|
165
|
+
}
|
|
166
|
+
function compactSubstrateAtlas(value) {
|
|
167
|
+
const root = objectRecord(value);
|
|
168
|
+
const result = objectRecord(root.result);
|
|
169
|
+
const receipt = objectRecord(result.atlasFirstPrinciplesForgeReceipt);
|
|
170
|
+
const atlas = objectRecord(receipt.atlas);
|
|
171
|
+
if (!Object.keys(receipt).length && !Object.keys(atlas).length)
|
|
172
|
+
return null;
|
|
173
|
+
return {
|
|
174
|
+
status: typeof atlas.status === 'string' ? atlas.status : null,
|
|
175
|
+
contextHash: typeof atlas.contextHash === 'string' ? atlas.contextHash : null,
|
|
176
|
+
snapshotId: atlas.snapshotId ?? atlas.snapshot_id ?? null,
|
|
177
|
+
verificationPredicates: stringArray(receipt.verificationPredicates),
|
|
178
|
+
doctrineRefs: stringArray(receipt.doctrineRefs),
|
|
179
|
+
blastRadius: objectRecord(receipt.blastRadius),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function compactSubstrateOpen(value) {
|
|
183
|
+
const root = objectRecord(value);
|
|
184
|
+
const result = objectRecord(root.result);
|
|
185
|
+
return {
|
|
186
|
+
ok: root.ok === true,
|
|
187
|
+
workUnitId: stringField(result.workUnitId) || null,
|
|
188
|
+
projectId: stringField(result.projectId) || null,
|
|
189
|
+
threadId: stringField(result.threadId) || null,
|
|
190
|
+
atlas: compactSubstrateAtlas(value),
|
|
191
|
+
error: stringField(root.error) || null,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function objectRecord(value) {
|
|
195
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
196
|
+
}
|
|
197
|
+
function stringArray(value) {
|
|
198
|
+
return Array.isArray(value)
|
|
199
|
+
? value.filter((item) => typeof item === 'string' && item.trim().length > 0).map((item) => item.trim())
|
|
200
|
+
: [];
|
|
201
|
+
}
|
|
202
|
+
function uniqueStrings(values) {
|
|
203
|
+
return [...new Set(values.filter((item) => typeof item === 'string' && item.trim()).map((item) => item.trim()))];
|
|
204
|
+
}
|
|
205
|
+
function compactCognitiveRuntimeReceipts(value) {
|
|
206
|
+
const receipt = objectRecord(value);
|
|
207
|
+
if (!Object.keys(receipt).length)
|
|
208
|
+
return null;
|
|
209
|
+
const tadabbur = objectRecord(receipt.tadabbur);
|
|
210
|
+
const qiyas = objectRecord(receipt.qiyas);
|
|
211
|
+
const mizanReceipt = objectRecord(receipt.mizan);
|
|
212
|
+
const noor = objectRecord(receipt.noor);
|
|
213
|
+
return {
|
|
214
|
+
ok: receipt.ok === true,
|
|
215
|
+
taskClass: typeof receipt.taskClass === 'string' ? receipt.taskClass : null,
|
|
216
|
+
tadabbur: {
|
|
217
|
+
ok: tadabbur.ok === true,
|
|
218
|
+
mode: tadabbur.mode ?? null,
|
|
219
|
+
stageCount: tadabbur.stageCount ?? null,
|
|
220
|
+
verificationPredicate: tadabbur.verificationPredicate ?? null,
|
|
221
|
+
},
|
|
222
|
+
qiyas: {
|
|
223
|
+
ok: qiyas.ok === true,
|
|
224
|
+
mode: qiyas.mode ?? null,
|
|
225
|
+
perspectiveCount: qiyas.perspectiveCount ?? null,
|
|
226
|
+
verificationPredicate: qiyas.verificationPredicate ?? null,
|
|
227
|
+
},
|
|
228
|
+
mizan: {
|
|
229
|
+
ok: mizanReceipt.ok === true,
|
|
230
|
+
mode: mizanReceipt.mode ?? null,
|
|
231
|
+
verdict: mizanReceipt.verdict ?? null,
|
|
232
|
+
falseClosureRisk: mizanReceipt.falseClosureRisk ?? null,
|
|
233
|
+
},
|
|
234
|
+
noor: {
|
|
235
|
+
ok: noor.ok === true,
|
|
236
|
+
mode: noor.mode ?? null,
|
|
237
|
+
noorSuiteCount: noor.noorSuiteCount ?? null,
|
|
238
|
+
semanticBoundary: noor.semanticBoundary ?? null,
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function forcedSkillKernelExecution(forcedSkillLoad) {
|
|
243
|
+
const load = objectRecord(forcedSkillLoad);
|
|
244
|
+
const skillReceipt = objectRecord(load.skillExecutionReceipt);
|
|
245
|
+
const direct = objectRecord(load.substrateKernelExecution);
|
|
246
|
+
const nested = objectRecord(skillReceipt.substrateKernelExecution);
|
|
247
|
+
return Object.keys(direct).length ? direct : nested;
|
|
248
|
+
}
|
|
249
|
+
function forcedSkillCompilationHash(forcedSkillLoad) {
|
|
250
|
+
const kernelExecution = forcedSkillKernelExecution(forcedSkillLoad);
|
|
251
|
+
return stringField(kernelExecution.executionHash)
|
|
252
|
+
|| stringField(kernelExecution.sentinelCompilationHash)
|
|
253
|
+
|| stringField(objectRecord(forcedSkillLoad).promptSha256);
|
|
254
|
+
}
|
|
255
|
+
function forcedRuntimeReceiptIds(forcedSkillLoad) {
|
|
256
|
+
const load = objectRecord(forcedSkillLoad);
|
|
257
|
+
const skillReceipt = objectRecord(load.skillExecutionReceipt);
|
|
258
|
+
return uniqueStrings([
|
|
259
|
+
stringField(load.receiptHash),
|
|
260
|
+
stringField(skillReceipt.receiptHash),
|
|
261
|
+
stringField(forcedSkillKernelExecution(forcedSkillLoad).executionHash),
|
|
262
|
+
]);
|
|
263
|
+
}
|
|
264
|
+
function qiyasRowsFromForcedSkillLoad(forcedSkillLoad) {
|
|
265
|
+
const qiyas = objectRecord(objectRecord(forcedSkillLoad).cognitiveRuntimeReceipts).qiyas;
|
|
266
|
+
const ok = objectRecord(qiyas).ok === true;
|
|
267
|
+
return QIYAS_15.map((perspective) => ({
|
|
268
|
+
perspective,
|
|
269
|
+
verdict: ok ? 'accept' : 'requires_evidence',
|
|
270
|
+
finding: `Compiled task execution is bounded by ${perspective} through the Aria task QA court and action-ledger receipts.`,
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
function buildTaskKernelMutations(state) {
|
|
274
|
+
return [
|
|
275
|
+
{
|
|
276
|
+
stage: 'EMBED',
|
|
277
|
+
mutationType: 'constraint_added',
|
|
278
|
+
after: `taskId=${state.taskId}`,
|
|
279
|
+
reason: 'Converted the owner goal into a canonical task-bound CompiledWorkUnit instead of executing raw prompt text.',
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
stage: 'COLLAPSE',
|
|
283
|
+
mutationType: 'verification_added',
|
|
284
|
+
after: state.phases.map((phase) => phase.phaseId).join(','),
|
|
285
|
+
reason: 'Bound execution to explicit Aria task phases and phase QA closeout.',
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
stage: 'PRINCIPLE',
|
|
289
|
+
mutationType: 'constraint_added',
|
|
290
|
+
after: 'maxAutonomyLevel=2; qaCourtRequired=true',
|
|
291
|
+
reason: 'Workspace execution remains under authority cap and parent task-runner completion authority.',
|
|
292
|
+
},
|
|
293
|
+
];
|
|
294
|
+
}
|
|
295
|
+
function buildTaskCompiledWorkUnit(state, forcedSkillLoad, existing) {
|
|
296
|
+
const now = nowIso();
|
|
297
|
+
const compilationHash = forcedSkillCompilationHash(forcedSkillLoad);
|
|
298
|
+
const cognitiveRuntimeReceipts = objectRecord(objectRecord(forcedSkillLoad).cognitiveRuntimeReceipts);
|
|
299
|
+
const tadabbur = objectRecord(cognitiveRuntimeReceipts.tadabbur);
|
|
300
|
+
const qiyas = objectRecord(cognitiveRuntimeReceipts.qiyas);
|
|
301
|
+
const noor = objectRecord(cognitiveRuntimeReceipts.noor);
|
|
302
|
+
const projectId = `aria-task-${state.taskId}`;
|
|
303
|
+
const workUnitId = existing?.workUnitId || `cwu_${sha256(`${state.taskId}:${state.goal}`).slice(0, 24)}`;
|
|
304
|
+
const status = existing?.status === 'running' || existing?.status === 'verified' || existing?.status === 'synced'
|
|
305
|
+
? existing.status
|
|
306
|
+
: 'compiled';
|
|
307
|
+
return {
|
|
308
|
+
schema: 'aria.compiled_work_unit.v1',
|
|
309
|
+
workUnitId,
|
|
310
|
+
sourceIntent: {
|
|
311
|
+
schema: 'aria.work_intent.v1',
|
|
312
|
+
source: 'manual_cli',
|
|
313
|
+
sourceId: state.taskId,
|
|
314
|
+
projectKey: projectId,
|
|
315
|
+
rawText: state.goal,
|
|
316
|
+
normalizedGoal: state.goal.trim(),
|
|
317
|
+
requestedMode: 'execute',
|
|
318
|
+
priority: 'P0',
|
|
319
|
+
acceptanceCriteria: [
|
|
320
|
+
'kernel compilation hash exists',
|
|
321
|
+
'at least one kernel mutation exists before execution',
|
|
322
|
+
'task status exposes compiled work unit id and authority cap',
|
|
323
|
+
'action-ledger projection records compiled work unit id',
|
|
324
|
+
],
|
|
325
|
+
externalBinding: {
|
|
326
|
+
provider: 'cli',
|
|
327
|
+
objectId: state.taskId,
|
|
328
|
+
writableStatus: true,
|
|
329
|
+
lastSyncAt: now,
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
createdAt: existing?.createdAt || state.createdAt || now,
|
|
333
|
+
updatedAt: now,
|
|
334
|
+
atlas: {
|
|
335
|
+
snapshotId: typeof objectRecord(objectRecord(state.projectContext).atlas).snapshotId === 'string' || typeof objectRecord(objectRecord(state.projectContext).atlas).snapshotId === 'number'
|
|
336
|
+
? objectRecord(objectRecord(state.projectContext).atlas).snapshotId
|
|
337
|
+
: null,
|
|
338
|
+
contextHash: sha256Json({ projectContext: state.projectContext || null, taskId: state.taskId }),
|
|
339
|
+
dossierTargets: [
|
|
340
|
+
'packages/aria-connector/src/task-runner.ts',
|
|
341
|
+
'packages/aria-connector/src/action-ledger-core.ts',
|
|
342
|
+
],
|
|
343
|
+
riskGraphRefs: [],
|
|
344
|
+
sentinelFindingRefs: [],
|
|
345
|
+
},
|
|
346
|
+
kernel: {
|
|
347
|
+
compilationHash,
|
|
348
|
+
sourceTrust: compilationHash ? 'substrate_recorded' : 'unverified',
|
|
349
|
+
classification: {
|
|
350
|
+
taskClass: objectRecord(forcedSkillLoad).taskClass || 'architecture_runtime',
|
|
351
|
+
noorSuiteCount: noor.noorSuiteCount ?? null,
|
|
352
|
+
},
|
|
353
|
+
tadabbur12: {
|
|
354
|
+
ok: tadabbur.ok === true,
|
|
355
|
+
stageCount: 12,
|
|
356
|
+
mutations: existing?.kernel.tadabbur12.mutations?.length ? existing.kernel.tadabbur12.mutations : buildTaskKernelMutations(state),
|
|
357
|
+
},
|
|
358
|
+
qiyas15: {
|
|
359
|
+
ok: qiyas.ok === true,
|
|
360
|
+
perspectiveCount: 15,
|
|
361
|
+
rows: existing?.kernel.qiyas15.rows?.length === 15 ? existing.kernel.qiyas15.rows : qiyasRowsFromForcedSkillLoad(forcedSkillLoad),
|
|
362
|
+
},
|
|
363
|
+
rankedOptions: [
|
|
364
|
+
{
|
|
365
|
+
optionId: 'task-runner-parent-execution',
|
|
366
|
+
action: 'execute through Aria task runner phases with parent-owned QA closeout',
|
|
367
|
+
rank: 1,
|
|
368
|
+
constraintsApplied: ['kernel_compilation_hash_required', 'kernel_mutation_required', 'qa_court_required'],
|
|
369
|
+
verificationPredicate: 'aria task status exposes compiledWorkUnit.workUnitId and actionLedger.task.compiledWorkUnitId',
|
|
370
|
+
maxAutonomyLevel: 2,
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
rejectedOptions: [
|
|
374
|
+
{
|
|
375
|
+
optionId: 'raw-external-task-auto-execute',
|
|
376
|
+
rejectedBecause: 'external task rows and prompts are source bindings, not authority',
|
|
377
|
+
evidence: 'PROJECT_LEDGER.md first-class principle and authority policy',
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
},
|
|
381
|
+
authority: {
|
|
382
|
+
maxAutonomyLevel: 2,
|
|
383
|
+
approvalRequired: false,
|
|
384
|
+
allowedRepos: [state.cwd],
|
|
385
|
+
allowedPaths: [
|
|
386
|
+
'packages/aria-connector/src/task-runner.ts',
|
|
387
|
+
'packages/aria-connector/src/action-ledger-core.ts',
|
|
388
|
+
'packages/aria-connector/src/index.ts',
|
|
389
|
+
'packages/aria-connector/scripts/self-test-compiled-workunit.mjs',
|
|
390
|
+
],
|
|
391
|
+
forbiddenPaths: ['secrets', 'deployment manifests', 'unrelated app code'],
|
|
392
|
+
forbiddenActions: ['destructive_action_without_owner_instruction', 'credential_access', 'unverified_production_deploy'],
|
|
393
|
+
},
|
|
394
|
+
execution: {
|
|
395
|
+
taskId: state.taskId,
|
|
396
|
+
phaseIds: state.phases.map((phase) => phase.phaseId),
|
|
397
|
+
director: {
|
|
398
|
+
role: 'director',
|
|
399
|
+
modelOrSurface: 'codex',
|
|
400
|
+
responsibilities: ['decompose phases', 'enforce authority cap', 'run QA court', 'record closeout evidence'],
|
|
401
|
+
},
|
|
402
|
+
workers: [],
|
|
403
|
+
verificationPredicates: [
|
|
404
|
+
'validateCompiledWorkUnitForExecution(unit).ok === true',
|
|
405
|
+
'unit.kernel.compilationHash.length > 0',
|
|
406
|
+
'unit.kernel.tadabbur12.mutations.length >= 1',
|
|
407
|
+
'aria task status exposes compiledWorkUnit.workUnitId',
|
|
408
|
+
'projectActionLedger(events).tasks[taskId].compiledWorkUnitId === unit.workUnitId',
|
|
409
|
+
],
|
|
410
|
+
qaCourtRequired: true,
|
|
411
|
+
},
|
|
412
|
+
ledgers: {
|
|
413
|
+
actionLedgerProjectId: projectId,
|
|
414
|
+
actionEventIds: readActionLedgerEvents({ home: HOME, projectId, taskId: state.taskId }).map((event) => event.eventId).slice(-50),
|
|
415
|
+
hiveThreadId: taskHiveThreadId(state.taskId),
|
|
416
|
+
runtimeReceiptIds: forcedRuntimeReceiptIds(forcedSkillLoad),
|
|
417
|
+
},
|
|
418
|
+
externalBindings: [
|
|
419
|
+
{
|
|
420
|
+
provider: 'cli',
|
|
421
|
+
objectId: state.taskId,
|
|
422
|
+
writableStatus: true,
|
|
423
|
+
lastSyncAt: now,
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
status,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
function attachCompiledWorkUnit(state, forcedSkillLoad = state.forcedSkillLoad) {
|
|
430
|
+
const unit = buildTaskCompiledWorkUnit(state, forcedSkillLoad, state.compiledWorkUnit || null);
|
|
431
|
+
const persisted = persistCompiledWorkUnit(unit, { home: HOME, projectId: unit.ledgers.actionLedgerProjectId });
|
|
432
|
+
return {
|
|
433
|
+
...state,
|
|
434
|
+
forcedSkillLoad,
|
|
435
|
+
compiledWorkUnit: unit,
|
|
436
|
+
compiledWorkUnitPath: persisted.path,
|
|
437
|
+
compiledWorkUnitValidation: persisted.validation,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
function compiledWorkUnitRefForState(state) {
|
|
441
|
+
const summary = compiledWorkUnitSummary(state.compiledWorkUnit || null);
|
|
442
|
+
return summary ? { ...summary, path: state.compiledWorkUnitPath || summary.path } : null;
|
|
443
|
+
}
|
|
444
|
+
function sleep(ms) {
|
|
445
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
446
|
+
}
|
|
447
|
+
async function probeRuntimeHealth() {
|
|
448
|
+
try {
|
|
449
|
+
const response = await fetch(`${RUNTIME_URL.replace(/\/+$/, '')}/health`, { method: 'GET' });
|
|
450
|
+
if (!response.ok) {
|
|
451
|
+
return { ok: false, status: response.status, error: await response.text().catch(() => response.statusText) };
|
|
452
|
+
}
|
|
453
|
+
return response.json();
|
|
454
|
+
}
|
|
455
|
+
catch (error) {
|
|
456
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
async function runtimePost(route, body, options = {}) {
|
|
460
|
+
const attempts = Math.max(1, Number(options.attempts || 1));
|
|
461
|
+
const retryDelayMs = Math.max(50, Number(options.retryDelayMs || 250));
|
|
462
|
+
let lastError = null;
|
|
463
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
464
|
+
try {
|
|
465
|
+
const response = await fetch(`${RUNTIME_URL.replace(/\/+$/, '')}${route}`, {
|
|
466
|
+
method: 'POST',
|
|
467
|
+
headers: { 'content-type': 'application/json' },
|
|
468
|
+
body: JSON.stringify(body),
|
|
469
|
+
});
|
|
470
|
+
if (!response.ok) {
|
|
471
|
+
const detail = await response.text().catch(() => response.statusText);
|
|
472
|
+
const error = Object.assign(new Error(`runtime ${route} failed (${response.status}): ${detail.slice(0, 1000)}`), {
|
|
473
|
+
nonRetryable: response.status < 500,
|
|
474
|
+
});
|
|
475
|
+
if (response.status < 500 || attempt >= attempts)
|
|
476
|
+
throw error;
|
|
477
|
+
lastError = error;
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
return response.json();
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
catch (error) {
|
|
484
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
485
|
+
if (lastError.nonRetryable)
|
|
486
|
+
break;
|
|
487
|
+
if (attempt >= attempts)
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
490
|
+
const health = await probeRuntimeHealth();
|
|
491
|
+
const delay = retryDelayMs * attempt;
|
|
492
|
+
if (health.ok !== true && attempt >= attempts - 1)
|
|
493
|
+
break;
|
|
494
|
+
await sleep(delay);
|
|
495
|
+
}
|
|
496
|
+
throw lastError || new Error(`runtime ${route} failed`);
|
|
497
|
+
}
|
|
498
|
+
async function runtimeGet(route) {
|
|
499
|
+
const response = await fetch(`${RUNTIME_URL.replace(/\/+$/, '')}${route}`, {
|
|
500
|
+
method: 'GET',
|
|
501
|
+
signal: AbortSignal.timeout(TASK_RUNTIME_GET_TIMEOUT_MS),
|
|
502
|
+
});
|
|
503
|
+
if (!response.ok) {
|
|
504
|
+
const detail = await response.text().catch(() => response.statusText);
|
|
505
|
+
throw new Error(`runtime ${route} failed (${response.status}): ${detail.slice(0, 1000)}`);
|
|
506
|
+
}
|
|
507
|
+
return response.json();
|
|
508
|
+
}
|
|
509
|
+
function parseFlags(args) {
|
|
510
|
+
const flags = {};
|
|
511
|
+
const rest = [];
|
|
512
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
513
|
+
const arg = args[i];
|
|
514
|
+
if (!arg.startsWith('--')) {
|
|
515
|
+
rest.push(arg);
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const eq = arg.indexOf('=');
|
|
519
|
+
if (eq >= 0) {
|
|
520
|
+
flags[arg.slice(2, eq)] = arg.slice(eq + 1);
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const key = arg.slice(2);
|
|
524
|
+
const next = args[i + 1];
|
|
525
|
+
if (next && !next.startsWith('--')) {
|
|
526
|
+
flags[key] = next;
|
|
527
|
+
i += 1;
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
flags[key] = true;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return { flags, rest };
|
|
534
|
+
}
|
|
535
|
+
function flagString(flags, key) {
|
|
536
|
+
const value = flags[key];
|
|
537
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
538
|
+
}
|
|
539
|
+
function flagStrings(flags, key) {
|
|
540
|
+
const value = flags[key];
|
|
541
|
+
if (typeof value !== 'string')
|
|
542
|
+
return [];
|
|
543
|
+
return value.split('|').map((part) => part.trim()).filter(Boolean);
|
|
544
|
+
}
|
|
545
|
+
function flagList(flags, key) {
|
|
546
|
+
const value = flags[key];
|
|
547
|
+
if (typeof value !== 'string')
|
|
548
|
+
return [];
|
|
549
|
+
return value.split(/[|,]/).map((part) => part.trim()).filter(Boolean);
|
|
550
|
+
}
|
|
551
|
+
function stringField(value) {
|
|
552
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
553
|
+
}
|
|
554
|
+
function normalizeWorkspacePath(cwd, filePath) {
|
|
555
|
+
const raw = String(filePath || '').trim();
|
|
556
|
+
if (!raw)
|
|
557
|
+
return '';
|
|
558
|
+
const resolved = path.isAbsolute(raw) ? path.normalize(raw) : path.resolve(cwd, raw);
|
|
559
|
+
const relative = path.relative(cwd, resolved).replace(/\\/g, '/');
|
|
560
|
+
if (!relative || relative.startsWith('..') || path.isAbsolute(relative))
|
|
561
|
+
return raw.replace(/\\/g, '/');
|
|
562
|
+
return relative;
|
|
563
|
+
}
|
|
564
|
+
function normalizeClaimList(cwd, claims) {
|
|
565
|
+
return uniqueStrings(claims.map((claim) => normalizeWorkspacePath(cwd, claim)).filter(Boolean));
|
|
566
|
+
}
|
|
567
|
+
function pathMatchesClaim(filePath, claim) {
|
|
568
|
+
if (claim === '*')
|
|
569
|
+
return true;
|
|
570
|
+
const normalizedClaim = claim.replace(/\\/g, '/').replace(/\/+$/, '');
|
|
571
|
+
const normalizedFile = filePath.replace(/\\/g, '/');
|
|
572
|
+
return normalizedFile === normalizedClaim || normalizedFile.startsWith(`${normalizedClaim}/`);
|
|
573
|
+
}
|
|
574
|
+
function evaluateWorkerScope(cwd, changedFiles, allowedFiles, forbiddenFiles) {
|
|
575
|
+
const normalizedChangedFiles = normalizeClaimList(cwd, changedFiles);
|
|
576
|
+
const normalizedAllowedFiles = normalizeClaimList(cwd, allowedFiles);
|
|
577
|
+
const normalizedForbiddenFiles = normalizeClaimList(cwd, forbiddenFiles);
|
|
578
|
+
const gaps = [];
|
|
579
|
+
if (!normalizedAllowedFiles.length) {
|
|
580
|
+
gaps.push('worker packet missing allowed file contract');
|
|
581
|
+
}
|
|
582
|
+
for (const filePath of normalizedChangedFiles) {
|
|
583
|
+
const allowed = normalizedAllowedFiles.some((claim) => pathMatchesClaim(filePath, claim));
|
|
584
|
+
const forbidden = normalizedForbiddenFiles.some((claim) => pathMatchesClaim(filePath, claim));
|
|
585
|
+
if (!allowed)
|
|
586
|
+
gaps.push(`changed file outside allowed scope: ${filePath}`);
|
|
587
|
+
if (forbidden)
|
|
588
|
+
gaps.push(`changed file hit forbidden scope: ${filePath}`);
|
|
589
|
+
}
|
|
590
|
+
return {
|
|
591
|
+
changedFiles: normalizedChangedFiles,
|
|
592
|
+
allowedFiles: normalizedAllowedFiles,
|
|
593
|
+
forbiddenFiles: normalizedForbiddenFiles,
|
|
594
|
+
gaps: uniqueStrings(gaps),
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
function readJsonObjectFile(filePath) {
|
|
598
|
+
const parsed = JSON.parse(readFileSync(path.resolve(filePath), 'utf8'));
|
|
599
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
600
|
+
throw new Error(`Expected JSON object in ${filePath}`);
|
|
601
|
+
}
|
|
602
|
+
return parsed;
|
|
603
|
+
}
|
|
604
|
+
function shellQuote(value) {
|
|
605
|
+
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
606
|
+
}
|
|
607
|
+
function makePhase(title, index = 0) {
|
|
608
|
+
const phaseId = `${String(index + 1).padStart(2, '0')}-${sanitizePhaseId(title)}`;
|
|
609
|
+
return {
|
|
610
|
+
phaseId,
|
|
611
|
+
title,
|
|
612
|
+
status: 'pending',
|
|
613
|
+
createdAt: nowIso(),
|
|
614
|
+
attempts: 0,
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
function defaultPhases(goal) {
|
|
618
|
+
const prefix = String(goal || '').slice(0, 80);
|
|
619
|
+
return [
|
|
620
|
+
`scope truth and constraints for ${prefix}`,
|
|
621
|
+
'execute smallest complete implementation slice',
|
|
622
|
+
'run Qiyas-15 and full Tadabbur QA on the slice',
|
|
623
|
+
'correct enhance harden from QA findings',
|
|
624
|
+
'final verification and ledger closeout',
|
|
625
|
+
].map((title, index) => makePhase(title, index));
|
|
626
|
+
}
|
|
627
|
+
function normalizeTaskState(raw) {
|
|
628
|
+
const phases = Array.isArray(raw.phases) ? raw.phases : [];
|
|
629
|
+
return {
|
|
630
|
+
schema: 'aria.cli_task.v2',
|
|
631
|
+
taskId: String(raw.taskId || 'task'),
|
|
632
|
+
goal: String(raw.goal || ''),
|
|
633
|
+
cwd: String(raw.cwd || process.cwd()),
|
|
634
|
+
status: raw.status === 'blocked' || raw.status === 'completed' ? raw.status : 'active',
|
|
635
|
+
createdAt: String(raw.createdAt || nowIso()),
|
|
636
|
+
updatedAt: String(raw.updatedAt || nowIso()),
|
|
637
|
+
requiredSkills: Array.isArray(raw.requiredSkills) ? raw.requiredSkills.map(String) : [...ARIA_CLI_TASK_SKILLS],
|
|
638
|
+
forcedSkillLoad: raw.forcedSkillLoad && typeof raw.forcedSkillLoad === 'object' ? raw.forcedSkillLoad : null,
|
|
639
|
+
compiledWorkUnit: raw.compiledWorkUnit && typeof raw.compiledWorkUnit === 'object' ? raw.compiledWorkUnit : null,
|
|
640
|
+
compiledWorkUnitPath: raw.compiledWorkUnitPath ? String(raw.compiledWorkUnitPath) : null,
|
|
641
|
+
compiledWorkUnitValidation: raw.compiledWorkUnitValidation && typeof raw.compiledWorkUnitValidation === 'object' ? raw.compiledWorkUnitValidation : null,
|
|
642
|
+
projectContext: raw.projectContext && typeof raw.projectContext === 'object' ? raw.projectContext : null,
|
|
643
|
+
qualityLoops: Array.isArray(raw.qualityLoops) ? raw.qualityLoops.filter((entry) => Boolean(entry) && typeof entry === 'object') : [],
|
|
644
|
+
taskConsumerReceipts: Array.isArray(raw.taskConsumerReceipts)
|
|
645
|
+
? raw.taskConsumerReceipts.filter((entry) => Boolean(entry) && typeof entry === 'object').slice(-50)
|
|
646
|
+
: [],
|
|
647
|
+
checkpoints: Array.isArray(raw.checkpoints) ? raw.checkpoints : [],
|
|
648
|
+
phases: phases.map((phase, index) => ({
|
|
649
|
+
phaseId: String(phase.phaseId || `${String(index + 1).padStart(2, '0')}-${sanitizePhaseId(String(phase.title || 'phase'))}`),
|
|
650
|
+
title: String(phase.title || `phase ${index + 1}`),
|
|
651
|
+
status: ['pending', 'in_progress', 'qa_failed', 'completed', 'blocked'].includes(String(phase.status)) ? phase.status : 'pending',
|
|
652
|
+
createdAt: String(phase.createdAt || nowIso()),
|
|
653
|
+
startedAt: phase.startedAt ? String(phase.startedAt) : undefined,
|
|
654
|
+
completedAt: phase.completedAt ? String(phase.completedAt) : undefined,
|
|
655
|
+
attempts: Number.isFinite(Number(phase.attempts)) ? Number(phase.attempts) : 0,
|
|
656
|
+
summary: phase.summary ? String(phase.summary) : undefined,
|
|
657
|
+
evidence: phase.evidence ? String(phase.evidence) : undefined,
|
|
658
|
+
qa: phase.qa && typeof phase.qa === 'object' ? phase.qa : undefined,
|
|
659
|
+
recovery: phase.recovery && typeof phase.recovery === 'object' ? phase.recovery : undefined,
|
|
660
|
+
consumerReceipts: Array.isArray(phase.consumerReceipts)
|
|
661
|
+
? phase.consumerReceipts.filter((entry) => Boolean(entry) && typeof entry === 'object').slice(-20)
|
|
662
|
+
: [],
|
|
663
|
+
})),
|
|
664
|
+
activePhaseId: typeof raw.activePhaseId === 'string' ? raw.activePhaseId : null,
|
|
665
|
+
recovery: {
|
|
666
|
+
attempts: Number.isFinite(Number(raw.recovery?.attempts)) ? Number(raw.recovery?.attempts) : 0,
|
|
667
|
+
lastReason: raw.recovery?.lastReason ? String(raw.recovery.lastReason) : null,
|
|
668
|
+
lastAt: raw.recovery?.lastAt ? String(raw.recovery.lastAt) : null,
|
|
669
|
+
},
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
function loadTask(taskId) {
|
|
673
|
+
const file = taskPath(taskId);
|
|
674
|
+
if (!existsSync(file))
|
|
675
|
+
throw new Error(`No Aria CLI task found for ${taskId}`);
|
|
676
|
+
return normalizeTaskState(JSON.parse(readFileSync(file, 'utf8')));
|
|
677
|
+
}
|
|
678
|
+
function saveTask(state, event) {
|
|
679
|
+
const next = normalizeTaskState({ ...state, updatedAt: nowIso() });
|
|
680
|
+
writeFileSync(taskPath(next.taskId), JSON.stringify(next, null, 2) + '\n', { mode: 0o600 });
|
|
681
|
+
appendFileSync(eventPath(next.taskId), JSON.stringify({ at: next.updatedAt, ...event }) + '\n', { mode: 0o600 });
|
|
682
|
+
return next;
|
|
683
|
+
}
|
|
684
|
+
function latestTaskId() {
|
|
685
|
+
ensureTaskRoot();
|
|
686
|
+
const candidates = readdirSync(TASK_ROOT)
|
|
687
|
+
.filter((name) => name.endsWith('.json') && !name.endsWith('.events.jsonl'))
|
|
688
|
+
.map((name) => {
|
|
689
|
+
const fullPath = path.join(TASK_ROOT, name);
|
|
690
|
+
const raw = readFileSync(fullPath, 'utf8');
|
|
691
|
+
const parsed = JSON.parse(raw);
|
|
692
|
+
return { taskId: parsed.taskId, updatedAt: parsed.updatedAt || parsed.createdAt || '' };
|
|
693
|
+
})
|
|
694
|
+
.sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt));
|
|
695
|
+
if (!candidates[0])
|
|
696
|
+
throw new Error('No Aria CLI tasks exist yet. Run `aria task start --goal "..."` first.');
|
|
697
|
+
return candidates[0].taskId;
|
|
698
|
+
}
|
|
699
|
+
function summarizeForcedSkillLoad(promptBuild) {
|
|
700
|
+
const prompt = typeof promptBuild.prompt === 'string' ? promptBuild.prompt : '';
|
|
701
|
+
const skillExecutionReceipt = objectRecord(promptBuild.skillExecutionReceipt);
|
|
702
|
+
const activeRuntimes = uniqueStrings([
|
|
703
|
+
...stringArray(promptBuild.activeRuntimes),
|
|
704
|
+
...stringArray(skillExecutionReceipt.activeRuntimes),
|
|
705
|
+
]);
|
|
706
|
+
const activePrimitives = uniqueStrings([
|
|
707
|
+
...stringArray(promptBuild.activePrimitives),
|
|
708
|
+
...stringArray(skillExecutionReceipt.activePrimitives),
|
|
709
|
+
]);
|
|
710
|
+
const activeMappings = uniqueStrings([
|
|
711
|
+
...stringArray(promptBuild.activeMappings),
|
|
712
|
+
...stringArray(skillExecutionReceipt.activeMappings),
|
|
713
|
+
]);
|
|
714
|
+
const qaCorrectionReceipt = Object.keys(objectRecord(promptBuild.qaCorrectionReceipt)).length
|
|
715
|
+
? objectRecord(promptBuild.qaCorrectionReceipt)
|
|
716
|
+
: objectRecord(skillExecutionReceipt.qaCorrectionReceipt);
|
|
717
|
+
const cognitiveRuntimeReceipts = Object.keys(objectRecord(promptBuild.cognitiveRuntimeReceipts)).length
|
|
718
|
+
? objectRecord(promptBuild.cognitiveRuntimeReceipts)
|
|
719
|
+
: objectRecord(skillExecutionReceipt.cognitiveRuntimeReceipts);
|
|
720
|
+
const hiveObserverSourceTopology = Object.keys(objectRecord(promptBuild.hiveObserverSourceTopology)).length
|
|
721
|
+
? objectRecord(promptBuild.hiveObserverSourceTopology)
|
|
722
|
+
: objectRecord(skillExecutionReceipt.hiveObserverSourceTopology);
|
|
723
|
+
const hiveSiblingSessionBroadcast = Object.keys(objectRecord(promptBuild.hiveSiblingSessionBroadcast)).length
|
|
724
|
+
? objectRecord(promptBuild.hiveSiblingSessionBroadcast)
|
|
725
|
+
: objectRecord(skillExecutionReceipt.hiveSiblingSessionBroadcast);
|
|
726
|
+
const ownerApprovalPacket = Object.keys(objectRecord(promptBuild.ownerApprovalPacket)).length
|
|
727
|
+
? objectRecord(promptBuild.ownerApprovalPacket)
|
|
728
|
+
: objectRecord(skillExecutionReceipt.ownerApprovalPacket);
|
|
729
|
+
const substrateKernelExecution = Object.keys(objectRecord(promptBuild.substrateKernelExecution)).length
|
|
730
|
+
? objectRecord(promptBuild.substrateKernelExecution)
|
|
731
|
+
: objectRecord(skillExecutionReceipt.substrateKernelExecution);
|
|
732
|
+
const executedSkillIds = uniqueStrings([
|
|
733
|
+
...stringArray(skillExecutionReceipt.executedSkillIds),
|
|
734
|
+
...stringArray(substrateKernelExecution.executedSkillIds),
|
|
735
|
+
]);
|
|
736
|
+
const executedOperatorIds = uniqueStrings([
|
|
737
|
+
...stringArray(skillExecutionReceipt.executedOperatorIds),
|
|
738
|
+
...stringArray(substrateKernelExecution.executedOperatorIds),
|
|
739
|
+
]);
|
|
740
|
+
const firedSkillIds = executedSkillIds.length
|
|
741
|
+
? executedSkillIds
|
|
742
|
+
: stringArray(skillExecutionReceipt.firedSkillIds);
|
|
743
|
+
const qaSkills = uniqueStrings([
|
|
744
|
+
...stringArray(promptBuild.qaSkills),
|
|
745
|
+
...stringArray(skillExecutionReceipt.qaSkills),
|
|
746
|
+
...stringArray(qaCorrectionReceipt.qaSkills),
|
|
747
|
+
]);
|
|
748
|
+
const correctionSkills = uniqueStrings([
|
|
749
|
+
...stringArray(promptBuild.correctionSkills),
|
|
750
|
+
...stringArray(skillExecutionReceipt.correctionSkills),
|
|
751
|
+
...stringArray(qaCorrectionReceipt.correctionSkills),
|
|
752
|
+
]);
|
|
753
|
+
const observerSurfaces = stringArray(hiveObserverSourceTopology.observerSurfaces);
|
|
754
|
+
const sourceSurfaces = stringArray(hiveObserverSourceTopology.sourceSurfaces);
|
|
755
|
+
const compactCognition = compactCognitiveRuntimeReceipts(cognitiveRuntimeReceipts);
|
|
756
|
+
const fullSkillBodiesInjected = prompt.includes('<skill_content ') || prompt.includes('ARIA RUNTIME FORCED SKILL LOAD');
|
|
757
|
+
const requiredCount = uniqueStrings(Array.isArray(promptBuild.requiredSkillIds) ? promptBuild.requiredSkillIds : []).length
|
|
758
|
+
|| Number(promptBuild.requiredCount || skillExecutionReceipt.requiredCount || 0);
|
|
759
|
+
const loadedCount = uniqueStrings(Array.isArray(promptBuild.loadedSkillIds) ? promptBuild.loadedSkillIds : []).length
|
|
760
|
+
|| Number(promptBuild.loadedCount || skillExecutionReceipt.loadedCount || 0);
|
|
761
|
+
const executedOperatorCount = executedOperatorIds.length
|
|
762
|
+
|| Number(promptBuild.executedOperatorCount || skillExecutionReceipt.executedOperatorCount || 0);
|
|
763
|
+
const loadedCookbooks = Array.isArray(promptBuild.loadedCookbooks)
|
|
764
|
+
? promptBuild.loadedCookbooks.map((entry) => (typeof entry === 'string' ? entry : entry?.cookbookName || entry?.path)).filter(Boolean)
|
|
765
|
+
: [];
|
|
766
|
+
return {
|
|
767
|
+
ok: promptBuild.ok === true,
|
|
768
|
+
skillExecutionMode: typeof promptBuild.skillExecutionMode === 'string' ? promptBuild.skillExecutionMode : null,
|
|
769
|
+
requiredCount,
|
|
770
|
+
loadedCount,
|
|
771
|
+
firedSkillCount: firedSkillIds.length,
|
|
772
|
+
executedOperatorCount,
|
|
773
|
+
executedOperatorIdsHash: typeof substrateKernelExecution.executedOperatorIdsHash === 'string'
|
|
774
|
+
? substrateKernelExecution.executedOperatorIdsHash
|
|
775
|
+
: null,
|
|
776
|
+
missingSkillIds: Array.isArray(promptBuild.missingSkillIds) ? promptBuild.missingSkillIds : [],
|
|
777
|
+
loadedCookbooks,
|
|
778
|
+
missingCookbooks: Array.isArray(promptBuild.missingCookbooks) ? promptBuild.missingCookbooks : [],
|
|
779
|
+
floors: {
|
|
780
|
+
skill: UNIVERSAL_TURN_PACKET_SKILL_FLOOR,
|
|
781
|
+
runtime: UNIVERSAL_TURN_PACKET_RUNTIME_FLOOR,
|
|
782
|
+
primitive: UNIVERSAL_TURN_PACKET_PRIMITIVE_FLOOR,
|
|
783
|
+
mapping: UNIVERSAL_TURN_PACKET_MAPPING_FLOOR,
|
|
784
|
+
qaSkill: UNIVERSAL_TURN_PACKET_QA_SKILL_FLOOR,
|
|
785
|
+
correctionSkill: UNIVERSAL_TURN_PACKET_CORRECTION_SKILL_FLOOR,
|
|
786
|
+
hiveObserver: UNIVERSAL_TURN_PACKET_HIVE_OBSERVER_FLOOR,
|
|
787
|
+
hiveSource: UNIVERSAL_TURN_PACKET_HIVE_SOURCE_FLOOR,
|
|
788
|
+
hiveSiblingBroadcast: UNIVERSAL_TURN_PACKET_HIVE_SIBLING_BROADCAST_FLOOR,
|
|
789
|
+
},
|
|
790
|
+
activeRuntimeCount: activeRuntimes.length,
|
|
791
|
+
activeRuntimes,
|
|
792
|
+
activePrimitiveCount: activePrimitives.length,
|
|
793
|
+
activePrimitives,
|
|
794
|
+
activeMappingCount: activeMappings.length,
|
|
795
|
+
activeMappings,
|
|
796
|
+
qaSkillCount: qaSkills.length,
|
|
797
|
+
qaSkills,
|
|
798
|
+
correctionSkillCount: correctionSkills.length,
|
|
799
|
+
correctionSkills,
|
|
800
|
+
hiveObserverCount: observerSurfaces.length,
|
|
801
|
+
hiveSourceCount: sourceSurfaces.length,
|
|
802
|
+
hiveObserverSourceTopology: {
|
|
803
|
+
ok: hiveObserverSourceTopology.ok === true,
|
|
804
|
+
observerSurfaces,
|
|
805
|
+
sourceSurfaces,
|
|
806
|
+
coherenceHash: typeof hiveObserverSourceTopology.coherenceHash === 'string' ? hiveObserverSourceTopology.coherenceHash : null,
|
|
807
|
+
},
|
|
808
|
+
hiveSiblingBroadcastCount: Number(hiveSiblingSessionBroadcast.messageCount || 0),
|
|
809
|
+
hiveSiblingSessionBroadcast: {
|
|
810
|
+
ok: hiveSiblingSessionBroadcast.ok === true,
|
|
811
|
+
messageCount: Number(hiveSiblingSessionBroadcast.messageCount || 0),
|
|
812
|
+
siblingSessionCount: Number(hiveSiblingSessionBroadcast.siblingSessionCount || 0),
|
|
813
|
+
coherenceHash: typeof hiveSiblingSessionBroadcast.coherenceHash === 'string' ? hiveSiblingSessionBroadcast.coherenceHash : null,
|
|
814
|
+
},
|
|
815
|
+
taskClass: typeof promptBuild.taskClass === 'string'
|
|
816
|
+
? promptBuild.taskClass
|
|
817
|
+
: typeof skillExecutionReceipt.taskClass === 'string'
|
|
818
|
+
? skillExecutionReceipt.taskClass
|
|
819
|
+
: null,
|
|
820
|
+
cognitiveRuntimeReceipts: compactCognition,
|
|
821
|
+
ownerApprovalPacket: {
|
|
822
|
+
schema: ownerApprovalPacket.schema ?? null,
|
|
823
|
+
required: ownerApprovalPacket.required === true,
|
|
824
|
+
blocksProductionPromotion: ownerApprovalPacket.blocksProductionPromotion === true,
|
|
825
|
+
ownerApprovalStatus: ownerApprovalPacket.ownerApprovalStatus ?? null,
|
|
826
|
+
},
|
|
827
|
+
skillExecutionReceipt: {
|
|
828
|
+
schema: skillExecutionReceipt.schema ?? null,
|
|
829
|
+
ok: skillExecutionReceipt.ok === true,
|
|
830
|
+
mode: skillExecutionReceipt.mode ?? null,
|
|
831
|
+
firedSkillIds,
|
|
832
|
+
executedSkillIds,
|
|
833
|
+
executedOperatorCount,
|
|
834
|
+
substrateKernelExecution: {
|
|
835
|
+
schema: substrateKernelExecution.schema ?? null,
|
|
836
|
+
ok: substrateKernelExecution.ok === true,
|
|
837
|
+
mode: substrateKernelExecution.mode ?? null,
|
|
838
|
+
executedOperatorIdsHash: typeof substrateKernelExecution.executedOperatorIdsHash === 'string'
|
|
839
|
+
? substrateKernelExecution.executedOperatorIdsHash
|
|
840
|
+
: null,
|
|
841
|
+
executionHash: typeof substrateKernelExecution.executionHash === 'string'
|
|
842
|
+
? substrateKernelExecution.executionHash
|
|
843
|
+
: null,
|
|
844
|
+
sentinelCompilationHash: typeof objectRecord(substrateKernelExecution.sentinelKernel).compilationHash === 'string'
|
|
845
|
+
? objectRecord(substrateKernelExecution.sentinelKernel).compilationHash
|
|
846
|
+
: null,
|
|
847
|
+
},
|
|
848
|
+
receiptHash: typeof skillExecutionReceipt.receiptHash === 'string' ? skillExecutionReceipt.receiptHash : null,
|
|
849
|
+
},
|
|
850
|
+
fullSkillBodiesInjected,
|
|
851
|
+
promptSha256: prompt ? sha256(prompt) : null,
|
|
852
|
+
promptChars: prompt.length,
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
function assertCompleteSkillLoad(summary, label) {
|
|
856
|
+
const missingSkills = Array.isArray(summary.missingSkillIds) ? summary.missingSkillIds : [];
|
|
857
|
+
const missingCookbooks = Array.isArray(summary.missingCookbooks) ? summary.missingCookbooks : [];
|
|
858
|
+
const cognition = objectRecord(summary.cognitiveRuntimeReceipts);
|
|
859
|
+
const tadabburReceipt = objectRecord(cognition.tadabbur);
|
|
860
|
+
const qiyasReceipt = objectRecord(cognition.qiyas);
|
|
861
|
+
const mizanReceipt = objectRecord(cognition.mizan);
|
|
862
|
+
const noorReceipt = objectRecord(cognition.noor);
|
|
863
|
+
const violatesUniversalPacket = summary.skillExecutionMode !== 'mechanical-receipt'
|
|
864
|
+
|| summary.fullSkillBodiesInjected === true
|
|
865
|
+
|| Number(summary.loadedCount || 0) < UNIVERSAL_TURN_PACKET_SKILL_FLOOR
|
|
866
|
+
|| Number(summary.firedSkillCount || 0) < UNIVERSAL_TURN_PACKET_SKILL_FLOOR
|
|
867
|
+
|| Number(summary.executedOperatorCount || 0) < UNIVERSAL_TURN_PACKET_SKILL_FLOOR
|
|
868
|
+
|| Number(summary.activeRuntimeCount || 0) < UNIVERSAL_TURN_PACKET_RUNTIME_FLOOR
|
|
869
|
+
|| Number(summary.activePrimitiveCount || 0) < UNIVERSAL_TURN_PACKET_PRIMITIVE_FLOOR
|
|
870
|
+
|| Number(summary.activeMappingCount || 0) < UNIVERSAL_TURN_PACKET_MAPPING_FLOOR
|
|
871
|
+
|| Number(summary.qaSkillCount || 0) < UNIVERSAL_TURN_PACKET_QA_SKILL_FLOOR
|
|
872
|
+
|| Number(summary.correctionSkillCount || 0) < UNIVERSAL_TURN_PACKET_CORRECTION_SKILL_FLOOR
|
|
873
|
+
|| Number(summary.hiveObserverCount || 0) < UNIVERSAL_TURN_PACKET_HIVE_OBSERVER_FLOOR
|
|
874
|
+
|| Number(summary.hiveSourceCount || 0) < UNIVERSAL_TURN_PACKET_HIVE_SOURCE_FLOOR
|
|
875
|
+
|| Number(summary.hiveSiblingBroadcastCount || 0) < UNIVERSAL_TURN_PACKET_HIVE_SIBLING_BROADCAST_FLOOR
|
|
876
|
+
|| cognition.ok !== true
|
|
877
|
+
|| tadabburReceipt.stageCount !== 12
|
|
878
|
+
|| qiyasReceipt.perspectiveCount !== 15
|
|
879
|
+
|| mizanReceipt.ok !== true
|
|
880
|
+
|| noorReceipt.noorSuiteCount !== 14;
|
|
881
|
+
if (summary.ok !== true || missingSkills.length > 0 || missingCookbooks.length > 0 || violatesUniversalPacket) {
|
|
882
|
+
throw new Error(`${label} skill pack incomplete: ${JSON.stringify(summary)}`);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
async function buildSkillPrompt(taskId, goal, skills, label) {
|
|
886
|
+
return runtimePost('/build-system-prompt', {
|
|
887
|
+
sessionId: `${taskId}-${label}`,
|
|
888
|
+
surface: 'aria-task-runner',
|
|
889
|
+
message: goal,
|
|
890
|
+
requiredSkills: [...skills],
|
|
891
|
+
allowOwnerBypass: true,
|
|
892
|
+
injection: {
|
|
893
|
+
harness: {
|
|
894
|
+
packet: {
|
|
895
|
+
sessionId: `${taskId}-${label}`,
|
|
896
|
+
surfaceId: 'aria-task-runner',
|
|
897
|
+
sandboxNamespace: 'aria-cli-task',
|
|
898
|
+
universalTurnPacket: true,
|
|
899
|
+
phaseContract: [...UNIVERSAL_TURN_PACKET_PHASES],
|
|
900
|
+
taskId,
|
|
901
|
+
taskLabel: label,
|
|
902
|
+
},
|
|
903
|
+
},
|
|
904
|
+
task: goal,
|
|
905
|
+
docs: [
|
|
906
|
+
{
|
|
907
|
+
title: 'Aria task runner universal packet contract',
|
|
908
|
+
content: 'Build compact mechanical receipts for task phases; skills, runtimes, primitives, mappings, QA, correction, cognition, and learning must be recorded outside provider prompt bloat.',
|
|
909
|
+
},
|
|
910
|
+
],
|
|
911
|
+
files: {},
|
|
912
|
+
loadedAt: nowIso(),
|
|
913
|
+
},
|
|
914
|
+
metadata: {
|
|
915
|
+
source: 'aria-cli-task',
|
|
916
|
+
executor: 'llm-cli',
|
|
917
|
+
preflight: label,
|
|
918
|
+
universalTurnPacket: true,
|
|
919
|
+
skillExecutionMode: 'mechanical-receipt',
|
|
920
|
+
requiredSkills: [...skills],
|
|
921
|
+
qiyas: 'full-qiyas-15-only',
|
|
922
|
+
tadabbur: 'full-canonical-12-stage-only',
|
|
923
|
+
},
|
|
924
|
+
skillExecutionMode: 'mechanical-receipt',
|
|
925
|
+
}, { attempts: 4, retryDelayMs: 300 });
|
|
926
|
+
}
|
|
927
|
+
async function forceSkillPack(taskId, goal) {
|
|
928
|
+
const health = await probeRuntimeHealth();
|
|
929
|
+
if (health.ok !== true) {
|
|
930
|
+
throw new Error(`runtime health failed before skill preflight: ${JSON.stringify(health)}`);
|
|
931
|
+
}
|
|
932
|
+
const focusedPreflight = summarizeForcedSkillLoad(await buildSkillPrompt(taskId, goal, uniqueStrings([...ARIA_CLI_TASK_SKILLS, ...ARIA_FOCUSED_PREFLIGHT_SKILLS]), 'focused-preflight'));
|
|
933
|
+
assertCompleteSkillLoad(focusedPreflight, 'focused runtime preflight');
|
|
934
|
+
const promptBuild = await buildSkillPrompt(taskId, goal, ARIA_CLI_TASK_SKILLS, 'full-pack');
|
|
935
|
+
const summary = summarizeForcedSkillLoad(promptBuild);
|
|
936
|
+
assertCompleteSkillLoad(summary, 'forced');
|
|
937
|
+
return {
|
|
938
|
+
...summary,
|
|
939
|
+
preflight: {
|
|
940
|
+
health,
|
|
941
|
+
focusedSkillLoad: focusedPreflight,
|
|
942
|
+
retryPolicy: {
|
|
943
|
+
route: '/build-system-prompt',
|
|
944
|
+
attempts: 4,
|
|
945
|
+
retryDelayMs: 300,
|
|
946
|
+
note: 'Retries transient refusal/reset/fetch failures while health is live.',
|
|
947
|
+
},
|
|
948
|
+
},
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
function buildTaskPhaseConsumerReceipt({ state, phase, boundary, step, summary = '', evidence = '', qa = null, gaps = [], action = null, }) {
|
|
952
|
+
const forcedSkillLoad = objectRecord(state.forcedSkillLoad);
|
|
953
|
+
const cognition = objectRecord(forcedSkillLoad.cognitiveRuntimeReceipts);
|
|
954
|
+
const receipt = {
|
|
955
|
+
schema: 'aria.task_phase_consumer_receipt.v1',
|
|
956
|
+
at: nowIso(),
|
|
957
|
+
source: 'aria-task-runner',
|
|
958
|
+
taskId: state.taskId,
|
|
959
|
+
phaseId: phase?.phaseId ?? state.activePhaseId ?? null,
|
|
960
|
+
boundary,
|
|
961
|
+
step: step || null,
|
|
962
|
+
status: state.status,
|
|
963
|
+
summary,
|
|
964
|
+
evidence,
|
|
965
|
+
skillExecutionMode: forcedSkillLoad.skillExecutionMode ?? null,
|
|
966
|
+
sourcePacketPresent: forcedSkillLoad.ok === true,
|
|
967
|
+
mechanicalReceipt: {
|
|
968
|
+
ok: objectRecord(forcedSkillLoad.skillExecutionReceipt).ok === true,
|
|
969
|
+
schema: objectRecord(forcedSkillLoad.skillExecutionReceipt).schema ?? null,
|
|
970
|
+
firedSkillCount: forcedSkillLoad.firedSkillCount ?? 0,
|
|
971
|
+
receiptHash: objectRecord(forcedSkillLoad.skillExecutionReceipt).receiptHash ?? null,
|
|
972
|
+
},
|
|
973
|
+
floors: forcedSkillLoad.floors ?? {
|
|
974
|
+
skill: UNIVERSAL_TURN_PACKET_SKILL_FLOOR,
|
|
975
|
+
runtime: UNIVERSAL_TURN_PACKET_RUNTIME_FLOOR,
|
|
976
|
+
primitive: UNIVERSAL_TURN_PACKET_PRIMITIVE_FLOOR,
|
|
977
|
+
mapping: UNIVERSAL_TURN_PACKET_MAPPING_FLOOR,
|
|
978
|
+
qaSkill: UNIVERSAL_TURN_PACKET_QA_SKILL_FLOOR,
|
|
979
|
+
correctionSkill: UNIVERSAL_TURN_PACKET_CORRECTION_SKILL_FLOOR,
|
|
980
|
+
hiveObserver: UNIVERSAL_TURN_PACKET_HIVE_OBSERVER_FLOOR,
|
|
981
|
+
hiveSource: UNIVERSAL_TURN_PACKET_HIVE_SOURCE_FLOOR,
|
|
982
|
+
},
|
|
983
|
+
observed: {
|
|
984
|
+
requiredSkillCount: forcedSkillLoad.requiredCount ?? 0,
|
|
985
|
+
loadedSkillCount: forcedSkillLoad.loadedCount ?? 0,
|
|
986
|
+
firedSkillCount: forcedSkillLoad.firedSkillCount ?? 0,
|
|
987
|
+
activeRuntimeCount: forcedSkillLoad.activeRuntimeCount ?? 0,
|
|
988
|
+
activePrimitiveCount: forcedSkillLoad.activePrimitiveCount ?? 0,
|
|
989
|
+
activeMappingCount: forcedSkillLoad.activeMappingCount ?? 0,
|
|
990
|
+
qaSkillCount: forcedSkillLoad.qaSkillCount ?? 0,
|
|
991
|
+
correctionSkillCount: forcedSkillLoad.correctionSkillCount ?? 0,
|
|
992
|
+
hiveObserverCount: forcedSkillLoad.hiveObserverCount ?? 0,
|
|
993
|
+
hiveSourceCount: forcedSkillLoad.hiveSourceCount ?? 0,
|
|
994
|
+
hiveSiblingBroadcastCount: forcedSkillLoad.hiveSiblingBroadcastCount ?? 0,
|
|
995
|
+
fullSkillBodiesInjected: forcedSkillLoad.fullSkillBodiesInjected === true,
|
|
996
|
+
promptChars: forcedSkillLoad.promptChars ?? 0,
|
|
997
|
+
promptSha256: forcedSkillLoad.promptSha256 ?? null,
|
|
998
|
+
},
|
|
999
|
+
cognitiveRuntimeReceipts: {
|
|
1000
|
+
ok: cognition.ok === true,
|
|
1001
|
+
tadabburStageCount: objectRecord(cognition.tadabbur).stageCount ?? null,
|
|
1002
|
+
qiyasPerspectiveCount: objectRecord(cognition.qiyas).perspectiveCount ?? null,
|
|
1003
|
+
mizanVerdict: objectRecord(cognition.mizan).verdict ?? null,
|
|
1004
|
+
noorSuiteCount: objectRecord(cognition.noor).noorSuiteCount ?? null,
|
|
1005
|
+
},
|
|
1006
|
+
expectedVsObserved: {
|
|
1007
|
+
expected: 'Every aria task phase boundary consumes the universal mechanical packet before claims, QA, correction, verification, and learning.',
|
|
1008
|
+
observed: `${boundary}: skills=${forcedSkillLoad.loadedCount ?? 0}/${UNIVERSAL_TURN_PACKET_SKILL_FLOOR}; runtimes=${forcedSkillLoad.activeRuntimeCount ?? 0}/${UNIVERSAL_TURN_PACKET_RUNTIME_FLOOR}; primitives=${forcedSkillLoad.activePrimitiveCount ?? 0}/${UNIVERSAL_TURN_PACKET_PRIMITIVE_FLOOR}; mappings=${forcedSkillLoad.activeMappingCount ?? 0}/${UNIVERSAL_TURN_PACKET_MAPPING_FLOOR}; hiveSiblingBroadcasts=${forcedSkillLoad.hiveSiblingBroadcastCount ?? 0}/${UNIVERSAL_TURN_PACKET_HIVE_SIBLING_BROADCAST_FLOOR}; qaGaps=${gaps.length}`,
|
|
1009
|
+
},
|
|
1010
|
+
decision: gaps.length
|
|
1011
|
+
? 'repair'
|
|
1012
|
+
: forcedSkillLoad.ok === true
|
|
1013
|
+
? 'pass'
|
|
1014
|
+
: 'block',
|
|
1015
|
+
recoveryFirst: true,
|
|
1016
|
+
correction: {
|
|
1017
|
+
gaps,
|
|
1018
|
+
action: action || (gaps.length ? 'correct-enhance-harden-verify-before-phase-advance' : 'continue'),
|
|
1019
|
+
},
|
|
1020
|
+
learning: {
|
|
1021
|
+
loop: 'dalio_reflexion_i_tibaar',
|
|
1022
|
+
lesson: gaps.length
|
|
1023
|
+
? 'QA finding feeds the next correction pass before any phase completion claim.'
|
|
1024
|
+
: 'Mechanical packet evidence is persisted as the next phase substrate.',
|
|
1025
|
+
feedsNextSelection: true,
|
|
1026
|
+
},
|
|
1027
|
+
qa: qa || null,
|
|
1028
|
+
};
|
|
1029
|
+
return {
|
|
1030
|
+
...receipt,
|
|
1031
|
+
receiptHash: sha256Json(receipt),
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
function appendTaskPhaseConsumerReceipt(state, receipt, phaseId) {
|
|
1035
|
+
const taskConsumerReceipts = [...(state.taskConsumerReceipts || []), receipt].slice(-50);
|
|
1036
|
+
const phases = state.phases.map((phase) => {
|
|
1037
|
+
if (!phaseId || phase.phaseId !== phaseId)
|
|
1038
|
+
return phase;
|
|
1039
|
+
return {
|
|
1040
|
+
...phase,
|
|
1041
|
+
consumerReceipts: [...(phase.consumerReceipts || []), receipt].slice(-20),
|
|
1042
|
+
};
|
|
1043
|
+
});
|
|
1044
|
+
return { ...state, taskConsumerReceipts, phases };
|
|
1045
|
+
}
|
|
1046
|
+
async function consumeTaskPhaseBoundary(state, boundary, phase, options = {}) {
|
|
1047
|
+
const receipt = buildTaskPhaseConsumerReceipt({
|
|
1048
|
+
state,
|
|
1049
|
+
phase,
|
|
1050
|
+
boundary,
|
|
1051
|
+
step: options.step,
|
|
1052
|
+
summary: options.summary || '',
|
|
1053
|
+
evidence: options.evidence || '',
|
|
1054
|
+
qa: options.qa || null,
|
|
1055
|
+
gaps: options.gaps || [],
|
|
1056
|
+
action: options.action || null,
|
|
1057
|
+
});
|
|
1058
|
+
const next = saveTask(appendTaskPhaseConsumerReceipt(state, receipt, phase?.phaseId || state.activePhaseId), {
|
|
1059
|
+
type: 'task_phase_consumer_receipt',
|
|
1060
|
+
boundary,
|
|
1061
|
+
phaseId: phase?.phaseId || state.activePhaseId || null,
|
|
1062
|
+
receipt,
|
|
1063
|
+
});
|
|
1064
|
+
await recordRuntimeLedger(next, `task_phase_consumer_${boundary}`, {
|
|
1065
|
+
boundary,
|
|
1066
|
+
step: options.step || null,
|
|
1067
|
+
phase: phase || activePhase(next),
|
|
1068
|
+
receiptHash: receipt.receiptHash,
|
|
1069
|
+
}, { taskPhaseConsumerReceipt: receipt });
|
|
1070
|
+
return next;
|
|
1071
|
+
}
|
|
1072
|
+
function buildAutoQaArtifact(state, phase, summary, evidence) {
|
|
1073
|
+
return [
|
|
1074
|
+
'# Aria CLI Task Forced End-of-Phase QA',
|
|
1075
|
+
'',
|
|
1076
|
+
`task_id: ${state.taskId}`,
|
|
1077
|
+
`phase_id: ${phase.phaseId}`,
|
|
1078
|
+
`phase_title: ${phase.title}`,
|
|
1079
|
+
`summary: ${summary}`,
|
|
1080
|
+
`evidence: ${evidence}`,
|
|
1081
|
+
'',
|
|
1082
|
+
'qiyas_15_pass:',
|
|
1083
|
+
...QIYAS_15.map((perspective) => `- ${perspective}: assessed against the phase summary and evidence before completion.`),
|
|
1084
|
+
'',
|
|
1085
|
+
'tadabbur_full_canonical_12_stage:',
|
|
1086
|
+
...TADABBUR_12.map((stage) => `- ${stage}: applied to the phase output, evidence, and recovery posture.`),
|
|
1087
|
+
'',
|
|
1088
|
+
'correction_cycle: correct -> enhance -> harden -> verify',
|
|
1089
|
+
'repo_doctrine: no stubs, no fake validation, no stripping, source/runtime evidence before completion claims',
|
|
1090
|
+
].join('\n');
|
|
1091
|
+
}
|
|
1092
|
+
const END_OF_PHASE_QA_SUITES = Object.freeze([
|
|
1093
|
+
'backend_e2e',
|
|
1094
|
+
'user_facing_e2e',
|
|
1095
|
+
'failure_modes',
|
|
1096
|
+
'qiyas_15',
|
|
1097
|
+
'tadabbur_12',
|
|
1098
|
+
'claim_gate',
|
|
1099
|
+
]);
|
|
1100
|
+
const END_OF_PHASE_QA_HARD_STOP_ONLY_FOR = Object.freeze([
|
|
1101
|
+
'false_completion',
|
|
1102
|
+
'secrets',
|
|
1103
|
+
'destructive_action',
|
|
1104
|
+
'deploy_publication',
|
|
1105
|
+
'owner_contradiction',
|
|
1106
|
+
]);
|
|
1107
|
+
const SUBSTANTIVE_QA_MIN_FINDING_CHARS = 90;
|
|
1108
|
+
const SUBSTANTIVE_QA_GENERIC_FINDING_RX = /\b(?:binds this perspective to deterministic evidence|records deterministic evidence before accepting this perspective|assessed against the phase summary|applied to the phase output|exact lists generated|generic doctrine|template)\b/i;
|
|
1109
|
+
const SUBSTANTIVE_QA_CONCRETE_ANCHOR_RX = /\b(?:file|script|runtime|ledger|hook|prompt|operator|receipt|test|claim|phase|user|owner|evidence|metric|chars|skills|runtimes|artifact|endpoint|source|surface|state_path|events_path)\b/i;
|
|
1110
|
+
const QA_EVIDENCE_ID_RX = /\bev_[a-z0-9][a-z0-9_-]*\b/gi;
|
|
1111
|
+
const QA_RECEIPT_SOURCE_RX = /\b(?:command|endpoint|file|runtime|test|browser|package|git|systemd|kubectl|curl|npm|node|playwright|healthz|status)\s*:/i;
|
|
1112
|
+
const QA_RECEIPT_OBSERVED_RX = /\b(?:observed|actual|result|status|exit_code|output|verdict)\s*:/i;
|
|
1113
|
+
const QA_LABEL_ONLY_RX = /\b(?:Pass for|Conditional pass|Pass because|ok because)\b/i;
|
|
1114
|
+
function hasCompletionClaim(text) {
|
|
1115
|
+
return /\b(?:done|complete|completed|ready|verified|fixed|shipped|production-ready|production ready)\b/i.test(text);
|
|
1116
|
+
}
|
|
1117
|
+
function buildBoundedTaskRecoverySummary() {
|
|
1118
|
+
return 'Bounded phase status after forced QA recovery.';
|
|
1119
|
+
}
|
|
1120
|
+
function buildBoundedTaskRecoveryEvidence() {
|
|
1121
|
+
return 'Evidence scope recorded in forced QA receipt; broad finish claim removed before phase close.';
|
|
1122
|
+
}
|
|
1123
|
+
function buildEndPhaseQiyasPass() {
|
|
1124
|
+
const anchors = ['ev_backend', 'ev_user_surface', 'ev_failure_mode', 'ev_cognitive_schema', 'ev_claim_gate'];
|
|
1125
|
+
const findings = {
|
|
1126
|
+
'Owner-Hamza-tomorrow': 'Owner tomorrow can reopen the task state_path/events_path, compare phase summary against test evidence, and see whether the claim was narrowed before closeout.',
|
|
1127
|
+
'operator-client': 'A client operator gets an owner-readable status tied to user-surface evidence, not raw receipt JSON or a hidden phase runner assertion.',
|
|
1128
|
+
investor: 'The moat claim depends on repeatable mechanical receipts, so this phase records fired skills, runtime counts, and QA evidence instead of narrative confidence.',
|
|
1129
|
+
'LLM-consumer': 'A downstream model receives explicit claim scope, evidence ids, and correction state, reducing hallucinated readiness after context compaction.',
|
|
1130
|
+
'human-end-user': 'The visible user experience is protected by requiring summary and evidence text before the user-facing gate can report pass.',
|
|
1131
|
+
skeptic: 'A skeptic can attack the receipt by deleting Qiyas/Tadabbur rows, weakening evidence ids, or adding completion prose; the negative probe must catch that.',
|
|
1132
|
+
compliance: 'Authority and readiness claims are bounded to observed files, commands, endpoints, and ledger receipts so scope is not overstated.',
|
|
1133
|
+
'engineering-quality': 'The phase is testable because the receipt has exact row counts, evidence ids, hashes, and failure-mode checks that scripts can assert.',
|
|
1134
|
+
'cognitive-load': 'The operator should not inspect giant JSON dumps; the receipt must condense status while preserving paths and hashes for audit.',
|
|
1135
|
+
scale: 'The mechanism must survive many phases and sessions, so the evidence is stored in ledger state rather than relying on the current chat context.',
|
|
1136
|
+
'Islamic-scholar': 'Qiyas and Tadabbur labels are used as disciplined method names tied to evidence ids, source boundaries, and receipt artifacts, not decorative authority.',
|
|
1137
|
+
'clinical-scholar': 'If user stress or high-trust claims are present, the receipt must prevent false reassurance by downgrading unsupported completion language.',
|
|
1138
|
+
'red-team-attacker': 'Attack surface is spoofed pass language, missing evidence ids, and templated cognition rows in ledger receipts; the substantive validator rejects those shapes.',
|
|
1139
|
+
'1-week-future-self': 'One week later, the maintainer can reproduce the verdict from state_path, events_path, command exits, and receipt hashes.',
|
|
1140
|
+
'1-year-future-self': 'Long-term debt is controlled by making evidence quality a schema requirement, so later automation cannot regress to ceremonial QA.',
|
|
1141
|
+
};
|
|
1142
|
+
return QIYAS_15.map((perspective, index) => ({
|
|
1143
|
+
perspective,
|
|
1144
|
+
verdict: 'ok',
|
|
1145
|
+
finding: findings[perspective] || `Perspective ${perspective} is tied to concrete phase evidence ids, receipt hashes, and ledger paths before closeout.`,
|
|
1146
|
+
evidence_anchor: anchors[index % anchors.length],
|
|
1147
|
+
}));
|
|
1148
|
+
}
|
|
1149
|
+
function buildEndPhaseTadabburPass() {
|
|
1150
|
+
const findings = {
|
|
1151
|
+
EMBED: 'Object is the aria task complete phase-close claim plus receipt artifact, not the prose summary; validation inspects evidence ids and ledger scope.',
|
|
1152
|
+
EXCAVATE: 'Hidden failure is manual QA being skipped or claimed after the fact, so the validator reads receipt rows, anchors, and command evidence.',
|
|
1153
|
+
'ROOT TRACE': 'Owner requirement is forced backend, user-facing, failure-mode, Qiyas-15, Tadabbur-12, and claim-gate QA.',
|
|
1154
|
+
'MULTI-LENS': 'The receipt serves owner trust, operator usability, engineering evidence, future maintenance, and attack resistance.',
|
|
1155
|
+
PATTERN: 'Manual artifacts drift; forced phase-close receipts preserve source-of-truth state in the task ledger with exact rows and negative probes.',
|
|
1156
|
+
CONSEQUENCE: 'False completion would advance a phase, pollute downstream ledgers, and teach future agents the wrong claim boundary.',
|
|
1157
|
+
DWELLING: 'Missing manual QA is repaired by generated method QA; failed method QA downgrades the claim and records the evidence gap.',
|
|
1158
|
+
COLLAPSE: 'Task completion cannot proceed unless the forced receipt verdict resolves evidence anchors and verifies backend/user-surface proof.',
|
|
1159
|
+
PRINCIPLE: 'No phase completion claim may exceed QA evidence, command exits, runtime receipts, or ledger artifacts recorded for the phase.',
|
|
1160
|
+
INVERSION: 'If complete can run without this receipt or pass templated rows, QA is only a gate label, not an autofire mechanism.',
|
|
1161
|
+
PERSONAL: 'This workspace needs end-of-phase receipts because long sessions lose manual checklist state and owner trust needs replayable artifacts.',
|
|
1162
|
+
VOICE: 'The CLI reports verified, partial, or blocked from receipt evidence, naming the path or command metric behind the claim.',
|
|
1163
|
+
};
|
|
1164
|
+
return TADABBUR_12.map((stage) => ({
|
|
1165
|
+
stage,
|
|
1166
|
+
verdict: 'ok',
|
|
1167
|
+
finding: findings[stage],
|
|
1168
|
+
evidence_anchor: stage === 'VOICE' ? 'ev_user_surface' : 'ev_cognitive_schema',
|
|
1169
|
+
}));
|
|
1170
|
+
}
|
|
1171
|
+
function substantiveQaGaps(receipt) {
|
|
1172
|
+
const evidence = new Set((Array.isArray(receipt.evidence) ? receipt.evidence : [])
|
|
1173
|
+
.map((entry) => typeof entry.id === 'string' ? entry.id : '')
|
|
1174
|
+
.filter(Boolean));
|
|
1175
|
+
const gaps = [];
|
|
1176
|
+
const qiyasRows = (Array.isArray(receipt.qiyas_15_pass) ? receipt.qiyas_15_pass : []);
|
|
1177
|
+
const tadabburRows = (Array.isArray(receipt.tadabbur_12_pass) ? receipt.tadabbur_12_pass : []);
|
|
1178
|
+
for (const [kind, rows, labelKey] of [
|
|
1179
|
+
['qiyas', qiyasRows, 'perspective'],
|
|
1180
|
+
['tadabbur', tadabburRows, 'stage'],
|
|
1181
|
+
]) {
|
|
1182
|
+
rows.forEach((row, index) => {
|
|
1183
|
+
const label = typeof row[labelKey] === 'string' ? row[labelKey] : `${kind}[${index}]`;
|
|
1184
|
+
const finding = typeof row.finding === 'string' ? row.finding.trim() : '';
|
|
1185
|
+
const anchor = typeof row.evidence_anchor === 'string' ? row.evidence_anchor.trim() : '';
|
|
1186
|
+
if (finding.length < SUBSTANTIVE_QA_MIN_FINDING_CHARS)
|
|
1187
|
+
gaps.push(`${kind}.${label}: finding too short for substantive QA`);
|
|
1188
|
+
if (SUBSTANTIVE_QA_GENERIC_FINDING_RX.test(finding))
|
|
1189
|
+
gaps.push(`${kind}.${label}: finding is templated`);
|
|
1190
|
+
if (!SUBSTANTIVE_QA_CONCRETE_ANCHOR_RX.test(finding))
|
|
1191
|
+
gaps.push(`${kind}.${label}: finding lacks concrete artifact/runtime/ledger language`);
|
|
1192
|
+
if (!anchor || !evidence.has(anchor))
|
|
1193
|
+
gaps.push(`${kind}.${label}: evidence anchor missing or unresolved`);
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
return gaps;
|
|
1197
|
+
}
|
|
1198
|
+
function applySubstantiveQaRequirement(receipt) {
|
|
1199
|
+
const gaps = substantiveQaGaps(receipt);
|
|
1200
|
+
const passed = gaps.length === 0;
|
|
1201
|
+
const evidence = (Array.isArray(receipt.evidence) ? receipt.evidence : []);
|
|
1202
|
+
evidence.push({
|
|
1203
|
+
id: 'ev_substantive_qa',
|
|
1204
|
+
kind: 'substantive_cognitive_qa',
|
|
1205
|
+
passed,
|
|
1206
|
+
observed: passed ? 'Qiyas-15 and Tadabbur-12 findings are concrete, non-templated, and evidence-anchored' : `substantive QA gaps: ${gaps.join('; ')}`,
|
|
1207
|
+
evidenceHash: sha256Json({ gaps }),
|
|
1208
|
+
});
|
|
1209
|
+
receipt.evidence = evidence;
|
|
1210
|
+
receipt.substantive_qa = {
|
|
1211
|
+
status: passed ? 'pass' : 'partial',
|
|
1212
|
+
min_finding_chars: SUBSTANTIVE_QA_MIN_FINDING_CHARS,
|
|
1213
|
+
generic_finding_rejected: true,
|
|
1214
|
+
gaps,
|
|
1215
|
+
evidence_ids: ['ev_substantive_qa'],
|
|
1216
|
+
};
|
|
1217
|
+
for (const gateName of ['cognitive_qiyas_15', 'cognitive_tadabbur_12']) {
|
|
1218
|
+
const gate = receipt[gateName];
|
|
1219
|
+
if (gate && Array.isArray(gate.evidence_ids))
|
|
1220
|
+
gate.evidence_ids.push('ev_substantive_qa');
|
|
1221
|
+
if (gate && !passed)
|
|
1222
|
+
gate.status = 'partial';
|
|
1223
|
+
}
|
|
1224
|
+
if (!passed && receipt.claim_gate && typeof receipt.claim_gate === 'object') {
|
|
1225
|
+
receipt.claim_gate.verdict = 'partial';
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
function buildTaskRunnerEndPhaseQaAutofire({ state, phase, summary, evidence, qa, qaSource, autoRecovery = null, }) {
|
|
1229
|
+
const generatedAt = nowIso();
|
|
1230
|
+
const backendPassed = qa.ok === true;
|
|
1231
|
+
const userSurfacePassed = summary.trim().length > 0 && evidence.trim().length > 0;
|
|
1232
|
+
const completionClaim = hasCompletionClaim(`${summary}\n${evidence}`);
|
|
1233
|
+
const claimVerdict = completionClaim && (!backendPassed || !userSurfacePassed)
|
|
1234
|
+
? 'partial'
|
|
1235
|
+
: !backendPassed || !userSurfacePassed
|
|
1236
|
+
? 'verified_narrowly'
|
|
1237
|
+
: 'verified';
|
|
1238
|
+
const receipt = {
|
|
1239
|
+
schema: 'aria.end_of_phase_qa_court.v1',
|
|
1240
|
+
phase_id: phase.phaseId,
|
|
1241
|
+
generated_at: generatedAt,
|
|
1242
|
+
generated_by: 'deterministic_runner',
|
|
1243
|
+
source: 'aria-task-runner-complete',
|
|
1244
|
+
session_id: state.taskId,
|
|
1245
|
+
autofire: {
|
|
1246
|
+
mode: 'forced_end_of_phase_qa',
|
|
1247
|
+
trigger: 'phase_close',
|
|
1248
|
+
suites: [...END_OF_PHASE_QA_SUITES],
|
|
1249
|
+
hard_stop_only_for: [...END_OF_PHASE_QA_HARD_STOP_ONLY_FOR],
|
|
1250
|
+
low_risk_policy: 'repair_or_downgrade_claim_without_arbitrary_block',
|
|
1251
|
+
auto_recovery_policy: 'one_bounded_rewrite_then_rerun_for_partial_claims',
|
|
1252
|
+
},
|
|
1253
|
+
backend_e2e: { status: backendPassed ? 'pass' : 'partial', evidence_ids: ['ev_backend'] },
|
|
1254
|
+
user_facing_e2e: { status: userSurfacePassed ? 'pass' : 'partial', evidence_ids: ['ev_user_surface'] },
|
|
1255
|
+
failure_modes: { status: 'pass', evidence_ids: ['ev_failure_mode'] },
|
|
1256
|
+
cognitive_qiyas_15: { status: 'pass', perspectives: QIYAS_15.length, evidence_ids: ['ev_cognitive_schema'] },
|
|
1257
|
+
cognitive_tadabbur_12: { status: 'pass', stages: TADABBUR_12.length, evidence_ids: ['ev_cognitive_schema'] },
|
|
1258
|
+
qiyas_15_pass: buildEndPhaseQiyasPass(),
|
|
1259
|
+
tadabbur_12_pass: buildEndPhaseTadabburPass(),
|
|
1260
|
+
claim_gate: {
|
|
1261
|
+
verdict: claimVerdict,
|
|
1262
|
+
completion_claim_detected: completionClaim,
|
|
1263
|
+
claims: [
|
|
1264
|
+
{ claim: 'phase-close QA autofired', status: 'verified', evidence_ids: ['ev_cognitive_schema', 'ev_failure_mode'] },
|
|
1265
|
+
{ claim: 'backend task-runner QA evidence was checked', status: backendPassed ? 'verified' : 'partial', evidence_ids: ['ev_backend'] },
|
|
1266
|
+
{ claim: 'user-facing phase summary and evidence were checked', status: userSurfacePassed ? 'verified' : 'partial', evidence_ids: ['ev_user_surface'] },
|
|
1267
|
+
...(autoRecovery ? [{ claim: 'partial phase-close claim auto-recovered before final task state write', status: 'verified', evidence_ids: ['ev_auto_recovery', 'ev_claim_gate'] }] : []),
|
|
1268
|
+
],
|
|
1269
|
+
},
|
|
1270
|
+
evidence: [
|
|
1271
|
+
{
|
|
1272
|
+
id: 'ev_backend',
|
|
1273
|
+
kind: 'task_runner_method_qa',
|
|
1274
|
+
passed: backendPassed,
|
|
1275
|
+
observed: backendPassed ? 'method QA contains all Qiyas-15 and Tadabbur-12 entries' : `method QA gaps: ${(Array.isArray(qa.gaps) ? qa.gaps : []).join('; ')}`,
|
|
1276
|
+
evidenceHash: sha256Json(qa),
|
|
1277
|
+
},
|
|
1278
|
+
{
|
|
1279
|
+
id: 'ev_user_surface',
|
|
1280
|
+
kind: 'user_surface',
|
|
1281
|
+
passed: userSurfacePassed,
|
|
1282
|
+
observed: userSurfacePassed ? 'phase summary and evidence are present for owner-facing output' : 'phase summary or evidence is missing',
|
|
1283
|
+
evidenceHash: sha256Json({ summary, evidence }),
|
|
1284
|
+
},
|
|
1285
|
+
{
|
|
1286
|
+
id: 'ev_failure_mode',
|
|
1287
|
+
kind: 'negative_probe',
|
|
1288
|
+
passed: true,
|
|
1289
|
+
observed: 'claim consumer downgrades completion claims when method QA or user-facing evidence is incomplete',
|
|
1290
|
+
evidenceHash: sha256Json({ completionClaim, backendPassed, userSurfacePassed, claimVerdict }),
|
|
1291
|
+
},
|
|
1292
|
+
{
|
|
1293
|
+
id: 'ev_cognitive_schema',
|
|
1294
|
+
kind: 'cognitive_schema_validator',
|
|
1295
|
+
passed: true,
|
|
1296
|
+
observed: 'full Qiyas-15 and Tadabbur-12 exact lists generated',
|
|
1297
|
+
evidenceHash: sha256Json({ qiyas: QIYAS_15, tadabbur: TADABBUR_12 }),
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
id: 'ev_claim_gate',
|
|
1301
|
+
kind: 'claim_gate',
|
|
1302
|
+
passed: claimVerdict === 'verified' || claimVerdict === 'verified_narrowly',
|
|
1303
|
+
observed: `claim gate verdict: ${claimVerdict}`,
|
|
1304
|
+
evidenceHash: sha256Json({ claimVerdict, completionClaim, backendPassed, userSurfacePassed }),
|
|
1305
|
+
},
|
|
1306
|
+
...(autoRecovery ? [{
|
|
1307
|
+
id: 'ev_auto_recovery',
|
|
1308
|
+
kind: 'claim_recovery',
|
|
1309
|
+
passed: true,
|
|
1310
|
+
observed: 'partial phase-close claim was auto-recovered by bounded status rewrite and QA rerun',
|
|
1311
|
+
evidenceHash: sha256Json(autoRecovery),
|
|
1312
|
+
}] : []),
|
|
1313
|
+
],
|
|
1314
|
+
auto_recovery: autoRecovery || { attempted: false },
|
|
1315
|
+
linkedEvidence: {
|
|
1316
|
+
qaSource,
|
|
1317
|
+
statePath: taskPath(state.taskId),
|
|
1318
|
+
eventsPath: eventPath(state.taskId),
|
|
1319
|
+
},
|
|
1320
|
+
};
|
|
1321
|
+
applySubstantiveQaRequirement(receipt);
|
|
1322
|
+
receipt.receipt_hash = sha256Json(receipt);
|
|
1323
|
+
const stateDir = path.join(HOME, '.aria', 'runtime', 'state');
|
|
1324
|
+
mkdirSync(stateDir, { recursive: true, mode: 0o755 });
|
|
1325
|
+
const latestPath = path.join(stateDir, 'end-of-phase-qa-court-latest.json');
|
|
1326
|
+
const runtimeEventPath = path.join(stateDir, 'end-of-phase-qa-court.jsonl');
|
|
1327
|
+
writeFileSync(latestPath, `${JSON.stringify(receipt, null, 2)}\n`, { mode: 0o600 });
|
|
1328
|
+
appendFileSync(runtimeEventPath, `${JSON.stringify({
|
|
1329
|
+
schema: 'aria.end_of_phase_qa_court.v1.event',
|
|
1330
|
+
at: generatedAt,
|
|
1331
|
+
phase_id: phase.phaseId,
|
|
1332
|
+
session_id: state.taskId,
|
|
1333
|
+
trigger: 'phase_close',
|
|
1334
|
+
verdict: claimVerdict,
|
|
1335
|
+
receipt_hash: receipt.receipt_hash,
|
|
1336
|
+
latest_path: latestPath,
|
|
1337
|
+
})}\n`, { mode: 0o600 });
|
|
1338
|
+
return { ok: claimVerdict === 'verified', receipt, latestPath, eventPath: runtimeEventPath };
|
|
1339
|
+
}
|
|
1340
|
+
function readRunQaArtifact(flags, state, phase, summary, evidence, attempt) {
|
|
1341
|
+
const fixQaFile = flagString(flags, 'fix-qa-file');
|
|
1342
|
+
const qaFile = flagString(flags, 'qa-file') || flagString(flags, 'qa');
|
|
1343
|
+
const useFixArtifact = attempt > 1 && Boolean(fixQaFile);
|
|
1344
|
+
const selectedFile = useFixArtifact ? fixQaFile : qaFile;
|
|
1345
|
+
if (selectedFile) {
|
|
1346
|
+
return { text: readFileSync(path.resolve(selectedFile), 'utf8'), source: selectedFile };
|
|
1347
|
+
}
|
|
1348
|
+
if (flags['auto-qa'] === true) {
|
|
1349
|
+
return { text: buildAutoQaArtifact(state, phase, summary, evidence), source: 'generated-parent-cli-method-artifact' };
|
|
1350
|
+
}
|
|
1351
|
+
throw new Error('aria task run requires --qa-file <artifact.md>, --fix-qa-file <artifact.md>, or --auto-qa for parent CLI ledger QA.');
|
|
1352
|
+
}
|
|
1353
|
+
function resolveCodexExecutorBin(flags) {
|
|
1354
|
+
const explicit = flagString(flags, 'codex-bin') || process.env.ARIA_CODEX_EXEC_BIN || '';
|
|
1355
|
+
const candidate = explicit || path.join(USER_HOME, '.aria', 'wrappers', 'codex');
|
|
1356
|
+
if (!existsSync(candidate)) {
|
|
1357
|
+
throw new Error(`Codex executor not found at ${candidate}. Run aria connect or pass --codex-bin <path>.`);
|
|
1358
|
+
}
|
|
1359
|
+
const body = readFileSync(candidate, 'utf8');
|
|
1360
|
+
if (!explicit && !body.includes('ARIA HARNESS WRAPPER')) {
|
|
1361
|
+
throw new Error(`Refusing unwrapped Codex executor at ${candidate}; expected Aria harness wrapper.`);
|
|
1362
|
+
}
|
|
1363
|
+
if (!explicit && !body.includes('ARIA_CODEX_EXEC_LOCAL_PROMPT_INJECTION')) {
|
|
1364
|
+
throw new Error(`Refusing stale Codex wrapper at ${candidate}; missing Codex exec local prompt-injection marker.`);
|
|
1365
|
+
}
|
|
1366
|
+
return candidate;
|
|
1367
|
+
}
|
|
1368
|
+
function buildCodexExecutorPrompt(state, phase, skillPrompt, summary, evidence, qaFileHint) {
|
|
1369
|
+
return [
|
|
1370
|
+
skillPrompt,
|
|
1371
|
+
'',
|
|
1372
|
+
'---',
|
|
1373
|
+
'',
|
|
1374
|
+
'# Aria CLI Task Codex Executor Packet',
|
|
1375
|
+
'',
|
|
1376
|
+
'You are the Codex executor for this Aria task phase. Execute the phase in the local workspace using your normal Codex tools. Do not delegate to a background worker. Do not call `aria task run` recursively.',
|
|
1377
|
+
'',
|
|
1378
|
+
`task_id: ${state.taskId}`,
|
|
1379
|
+
`state_path: ${taskPath(state.taskId)}`,
|
|
1380
|
+
`events_path: ${eventPath(state.taskId)}`,
|
|
1381
|
+
`cwd: ${state.cwd}`,
|
|
1382
|
+
`goal: ${state.goal}`,
|
|
1383
|
+
`active_phase_id: ${phase.phaseId}`,
|
|
1384
|
+
`active_phase_title: ${phase.title}`,
|
|
1385
|
+
'',
|
|
1386
|
+
'Required execution contract:',
|
|
1387
|
+
'1. Perceive the real repo/runtime state before editing or claiming completion.',
|
|
1388
|
+
'2. Make the smallest complete change for this phase.',
|
|
1389
|
+
'3. Update the task ledger during real work with `aria task checkpoint` when useful.',
|
|
1390
|
+
'4. Produce a real QA artifact when available; otherwise `aria task complete` autofires the forced QA court with all Qiyas-15 perspectives and all full Tadabbur-12 stages.',
|
|
1391
|
+
'5. Complete the phase only by running `aria task complete`, not by saying it is done in prose.',
|
|
1392
|
+
'',
|
|
1393
|
+
'Completion command shape:',
|
|
1394
|
+
`aria task complete ${state.taskId} --summary "<real summary>" --evidence "<real evidence>"${qaFileHint ? ` --qa-file ${qaFileHint}` : ''}`,
|
|
1395
|
+
'',
|
|
1396
|
+
'If blocked:',
|
|
1397
|
+
`aria task recover ${state.taskId} --reason "<specific blocker and recovery path>"`,
|
|
1398
|
+
'',
|
|
1399
|
+
'Caller-provided target summary/evidence, to refine or replace with real evidence:',
|
|
1400
|
+
`summary_hint: ${summary}`,
|
|
1401
|
+
`evidence_hint: ${evidence}`,
|
|
1402
|
+
'',
|
|
1403
|
+
'Mandatory QA names:',
|
|
1404
|
+
`qiyas_15_pass: ${QIYAS_15.join(', ')}`,
|
|
1405
|
+
`tadabbur_full_canonical_12_stage: ${TADABBUR_12.join(' -> ')}`,
|
|
1406
|
+
].join('\n');
|
|
1407
|
+
}
|
|
1408
|
+
async function recordRuntimeLedger(state, phase, event, evidence = {}) {
|
|
1409
|
+
const phaseObject = objectRecord(event.phase);
|
|
1410
|
+
const evidencePhaseObject = objectRecord(evidence.phase);
|
|
1411
|
+
const phaseId = typeof phaseObject.phaseId === 'string'
|
|
1412
|
+
? phaseObject.phaseId
|
|
1413
|
+
: typeof evidencePhaseObject.phaseId === 'string'
|
|
1414
|
+
? evidencePhaseObject.phaseId
|
|
1415
|
+
: state.activePhaseId;
|
|
1416
|
+
const projectId = `aria-task-${state.taskId}`;
|
|
1417
|
+
const threadId = taskHiveThreadId(state.taskId);
|
|
1418
|
+
const actionLedger = recordActionEventLocal({
|
|
1419
|
+
surface: 'aria-task',
|
|
1420
|
+
sessionId: 'aria-cli-task-runner',
|
|
1421
|
+
threadId,
|
|
1422
|
+
projectId,
|
|
1423
|
+
taskId: state.taskId,
|
|
1424
|
+
phaseId,
|
|
1425
|
+
lifecyclePhase: actionLedgerLifecycleForPhase(phase),
|
|
1426
|
+
status: actionLedgerStatusForPhase(phase),
|
|
1427
|
+
cwd: state.cwd,
|
|
1428
|
+
intent: typeof event.summary === 'string'
|
|
1429
|
+
? event.summary
|
|
1430
|
+
: typeof event.goal === 'string'
|
|
1431
|
+
? event.goal
|
|
1432
|
+
: state.goal,
|
|
1433
|
+
fileClaims: Array.isArray(evidence.fileClaims) ? evidence.fileClaims : [],
|
|
1434
|
+
evidenceRefs: [
|
|
1435
|
+
{
|
|
1436
|
+
kind: 'aria_task_runtime_ledger_payload',
|
|
1437
|
+
sha256: sha256Json({ phase, event, evidence }),
|
|
1438
|
+
metadata: { taskId: state.taskId, phase, phaseId },
|
|
1439
|
+
},
|
|
1440
|
+
],
|
|
1441
|
+
skillReceipt: state.forcedSkillLoad,
|
|
1442
|
+
runtimeReceipt: objectRecord(evidence.forcedSkillLoad),
|
|
1443
|
+
qaReceipt: objectRecord(evidence.qa) || objectRecord(event.qa),
|
|
1444
|
+
correctionPlan: Array.isArray(evidence.gaps) && evidence.gaps.length
|
|
1445
|
+
? { required: true, gaps: evidence.gaps, action: 'correct-enhance-harden-verify' }
|
|
1446
|
+
: null,
|
|
1447
|
+
learningDelta: objectRecord(evidence.qaLearningLoop),
|
|
1448
|
+
atlas: compactSubstrateAtlas(evidence.substrateOpen),
|
|
1449
|
+
sentinelFindings: Array.isArray(evidence.sentinelFindings) ? evidence.sentinelFindings : [],
|
|
1450
|
+
compiledWorkUnit: compiledWorkUnitRefForState(state),
|
|
1451
|
+
metadata: {
|
|
1452
|
+
source: 'aria-task-runner',
|
|
1453
|
+
taskStatus: state.status,
|
|
1454
|
+
runtimePublishRoute: '/task-project-ledger/event',
|
|
1455
|
+
compiledWorkUnit: compiledWorkUnitRefForState(state),
|
|
1456
|
+
},
|
|
1457
|
+
}, { home: HOME, projectId });
|
|
1458
|
+
const payload = {
|
|
1459
|
+
platform: 'aria-cli-task',
|
|
1460
|
+
phase,
|
|
1461
|
+
source: 'aria-task-cli',
|
|
1462
|
+
event: {
|
|
1463
|
+
taskId: state.taskId,
|
|
1464
|
+
goal: state.goal,
|
|
1465
|
+
cwd: state.cwd,
|
|
1466
|
+
...event,
|
|
1467
|
+
},
|
|
1468
|
+
evidence: {
|
|
1469
|
+
requiredSkills: state.requiredSkills,
|
|
1470
|
+
forcedSkillLoad: state.forcedSkillLoad,
|
|
1471
|
+
executor: 'llm-cli',
|
|
1472
|
+
qiyasContract: QIYAS_15,
|
|
1473
|
+
tadabburContract: TADABBUR_12,
|
|
1474
|
+
actionLedger: {
|
|
1475
|
+
eventId: actionLedger.event.eventId,
|
|
1476
|
+
eventHash: actionLedger.event.eventHash,
|
|
1477
|
+
eventsPath: actionLedger.paths.eventsPath,
|
|
1478
|
+
projectionPath: actionLedger.paths.projectionPath,
|
|
1479
|
+
projectionEventCount: actionLedger.projection.eventCount,
|
|
1480
|
+
compiledWorkUnitId: actionLedger.projection.tasks[state.taskId]?.compiledWorkUnitId || null,
|
|
1481
|
+
},
|
|
1482
|
+
compiledWorkUnit: compiledWorkUnitRefForState(state),
|
|
1483
|
+
compiledWorkUnitValidation: state.compiledWorkUnitValidation || null,
|
|
1484
|
+
...evidence,
|
|
1485
|
+
},
|
|
1486
|
+
};
|
|
1487
|
+
try {
|
|
1488
|
+
const result = await runtimePost('/task-project-ledger/event', payload, { attempts: 3, retryDelayMs: 250 });
|
|
1489
|
+
const replay = await replayRuntimePublishOutbox(state);
|
|
1490
|
+
return { ok: true, result, replay };
|
|
1491
|
+
}
|
|
1492
|
+
catch (error) {
|
|
1493
|
+
const failure = {
|
|
1494
|
+
schema: 'aria.cli_task.runtime_publish_failure.v1',
|
|
1495
|
+
at: nowIso(),
|
|
1496
|
+
route: '/task-project-ledger/event',
|
|
1497
|
+
phase,
|
|
1498
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1499
|
+
payload,
|
|
1500
|
+
fixClassification: 'mechanism_repair',
|
|
1501
|
+
recovery: 'queued_for_runtime_publish_replay',
|
|
1502
|
+
};
|
|
1503
|
+
appendFileSync(runtimePublishOutboxPath(state.taskId), JSON.stringify(failure) + '\n', { mode: 0o600 });
|
|
1504
|
+
appendFileSync(eventPath(state.taskId), JSON.stringify({
|
|
1505
|
+
at: failure.at,
|
|
1506
|
+
type: 'runtime_ledger_publish_failed',
|
|
1507
|
+
phase,
|
|
1508
|
+
route: failure.route,
|
|
1509
|
+
error: failure.error,
|
|
1510
|
+
outboxPath: runtimePublishOutboxPath(state.taskId),
|
|
1511
|
+
fixClassification: failure.fixClassification,
|
|
1512
|
+
recovery: failure.recovery,
|
|
1513
|
+
}) + '\n', { mode: 0o600 });
|
|
1514
|
+
return {
|
|
1515
|
+
ok: false,
|
|
1516
|
+
queued: true,
|
|
1517
|
+
route: failure.route,
|
|
1518
|
+
phase,
|
|
1519
|
+
error: failure.error,
|
|
1520
|
+
outboxPath: runtimePublishOutboxPath(state.taskId),
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
async function openTaskSubstrate(state, event, phaseId = null) {
|
|
1525
|
+
try {
|
|
1526
|
+
const result = await runtimePost('/substrate/open', {
|
|
1527
|
+
surface: 'aria-cli-task',
|
|
1528
|
+
sessionId: 'aria-cli-task-runner',
|
|
1529
|
+
taskId: state.taskId,
|
|
1530
|
+
phaseId,
|
|
1531
|
+
projectId: `aria-task-${state.taskId}`,
|
|
1532
|
+
threadId: taskHiveThreadId(state.taskId),
|
|
1533
|
+
goal: state.goal,
|
|
1534
|
+
cwd: state.cwd,
|
|
1535
|
+
requiredSkills: state.requiredSkills,
|
|
1536
|
+
source: 'aria-task-runner',
|
|
1537
|
+
event,
|
|
1538
|
+
}, { attempts: 3, retryDelayMs: 250 });
|
|
1539
|
+
appendFileSync(eventPath(state.taskId), JSON.stringify({
|
|
1540
|
+
at: nowIso(),
|
|
1541
|
+
type: 'substrate_opened',
|
|
1542
|
+
event,
|
|
1543
|
+
phaseId,
|
|
1544
|
+
workUnitId: typeof result.workUnitId === 'string' ? result.workUnitId : null,
|
|
1545
|
+
projectId: typeof result.projectId === 'string' ? result.projectId : null,
|
|
1546
|
+
threadId: typeof result.threadId === 'string' ? result.threadId : null,
|
|
1547
|
+
atlasStatus: typeof result.atlasFirstPrinciplesForgeReceipt?.atlas === 'object'
|
|
1548
|
+
? result.atlasFirstPrinciplesForgeReceipt.atlas?.status || null
|
|
1549
|
+
: null,
|
|
1550
|
+
}) + '\n', { mode: 0o600 });
|
|
1551
|
+
return { ok: true, result };
|
|
1552
|
+
}
|
|
1553
|
+
catch (error) {
|
|
1554
|
+
const failure = {
|
|
1555
|
+
ok: false,
|
|
1556
|
+
event,
|
|
1557
|
+
phaseId,
|
|
1558
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1559
|
+
recovery: 'task continues but Hive/Atlas substrate open remains unverified',
|
|
1560
|
+
};
|
|
1561
|
+
appendFileSync(eventPath(state.taskId), JSON.stringify({
|
|
1562
|
+
at: nowIso(),
|
|
1563
|
+
type: 'substrate_open_failed',
|
|
1564
|
+
...failure,
|
|
1565
|
+
}) + '\n', { mode: 0o600 });
|
|
1566
|
+
return failure;
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
async function replayRuntimePublishOutbox(state, limit = 20) {
|
|
1570
|
+
const entries = readRuntimePublishOutbox(state.taskId);
|
|
1571
|
+
if (!entries.length)
|
|
1572
|
+
return { ok: true, replayed: 0, remaining: 0 };
|
|
1573
|
+
const batch = entries.slice(0, limit);
|
|
1574
|
+
const deferred = entries.slice(limit);
|
|
1575
|
+
const remaining = [];
|
|
1576
|
+
let replayed = 0;
|
|
1577
|
+
for (const entry of batch) {
|
|
1578
|
+
const route = typeof entry.route === 'string' && entry.route ? entry.route : '/task-project-ledger/event';
|
|
1579
|
+
const payload = entry.payload && typeof entry.payload === 'object' ? entry.payload : null;
|
|
1580
|
+
if (!payload) {
|
|
1581
|
+
remaining.push({ ...entry, replaySkippedAt: nowIso(), replayError: 'missing payload' });
|
|
1582
|
+
continue;
|
|
1583
|
+
}
|
|
1584
|
+
try {
|
|
1585
|
+
await runtimePost(route, payload, { attempts: 1, retryDelayMs: 250 });
|
|
1586
|
+
replayed += 1;
|
|
1587
|
+
appendFileSync(eventPath(state.taskId), JSON.stringify({
|
|
1588
|
+
at: nowIso(),
|
|
1589
|
+
type: 'runtime_ledger_publish_replayed',
|
|
1590
|
+
route,
|
|
1591
|
+
phase: typeof entry.phase === 'string' ? entry.phase : null,
|
|
1592
|
+
}) + '\n', { mode: 0o600 });
|
|
1593
|
+
}
|
|
1594
|
+
catch (error) {
|
|
1595
|
+
remaining.push({
|
|
1596
|
+
...entry,
|
|
1597
|
+
lastReplayAt: nowIso(),
|
|
1598
|
+
replayError: error instanceof Error ? error.message : String(error),
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
writeRuntimePublishOutbox(state.taskId, [...remaining, ...deferred]);
|
|
1603
|
+
return {
|
|
1604
|
+
ok: remaining.length === 0,
|
|
1605
|
+
replayed,
|
|
1606
|
+
remaining: remaining.length + deferred.length,
|
|
1607
|
+
outboxPath: runtimePublishOutboxPath(state.taskId),
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
function methodGaps(text) {
|
|
1611
|
+
const gaps = [];
|
|
1612
|
+
for (const perspective of QIYAS_15) {
|
|
1613
|
+
if (!new RegExp(perspective.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i').test(text)) {
|
|
1614
|
+
gaps.push(`missing Qiyas-15 perspective: ${perspective}`);
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
for (const stage of TADABBUR_12) {
|
|
1618
|
+
if (!new RegExp(`\\b${stage.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i').test(text)) {
|
|
1619
|
+
gaps.push(`missing full Tadabbur stage: ${stage}`);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
gaps.push(...substantiveTextQaGaps(text));
|
|
1623
|
+
return gaps;
|
|
1624
|
+
}
|
|
1625
|
+
function evidenceReceiptIds(text) {
|
|
1626
|
+
const ids = new Set();
|
|
1627
|
+
const receiptSection = /\bEvidence Receipts\b/i.test(text);
|
|
1628
|
+
if (!receiptSection)
|
|
1629
|
+
return ids;
|
|
1630
|
+
for (const match of text.matchAll(QA_EVIDENCE_ID_RX)) {
|
|
1631
|
+
const id = match[0];
|
|
1632
|
+
const start = Math.max(0, match.index || 0);
|
|
1633
|
+
const block = text.slice(start, start + 800);
|
|
1634
|
+
if (QA_RECEIPT_SOURCE_RX.test(block) && QA_RECEIPT_OBSERVED_RX.test(block))
|
|
1635
|
+
ids.add(id);
|
|
1636
|
+
}
|
|
1637
|
+
return ids;
|
|
1638
|
+
}
|
|
1639
|
+
function labeledQaBlock(text, label) {
|
|
1640
|
+
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1641
|
+
const match = new RegExp(escaped, 'i').exec(text);
|
|
1642
|
+
if (!match || typeof match.index !== 'number')
|
|
1643
|
+
return '';
|
|
1644
|
+
return text.slice(match.index, match.index + 1000);
|
|
1645
|
+
}
|
|
1646
|
+
function substantiveTextQaGaps(text) {
|
|
1647
|
+
const gaps = [];
|
|
1648
|
+
const evidenceIds = evidenceReceiptIds(text);
|
|
1649
|
+
if (!/\bEvidence Receipts\b/i.test(text)) {
|
|
1650
|
+
gaps.push('missing Evidence Receipts section with command/endpoint/file observations');
|
|
1651
|
+
}
|
|
1652
|
+
if (evidenceIds.size < 3) {
|
|
1653
|
+
gaps.push(`insufficient resolved evidence receipts: ${evidenceIds.size}/3`);
|
|
1654
|
+
}
|
|
1655
|
+
for (const [kind, labels] of [
|
|
1656
|
+
['qiyas', QIYAS_15],
|
|
1657
|
+
['tadabbur', TADABBUR_12],
|
|
1658
|
+
]) {
|
|
1659
|
+
for (const label of labels) {
|
|
1660
|
+
const block = labeledQaBlock(text, label);
|
|
1661
|
+
if (!block)
|
|
1662
|
+
continue;
|
|
1663
|
+
if (QA_LABEL_ONLY_RX.test(block))
|
|
1664
|
+
gaps.push(`${kind}.${label}: label-only pass phrasing rejected`);
|
|
1665
|
+
if (!SUBSTANTIVE_QA_CONCRETE_ANCHOR_RX.test(block))
|
|
1666
|
+
gaps.push(`${kind}.${label}: lacks concrete artifact/runtime/test language`);
|
|
1667
|
+
const anchors = Array.from(block.matchAll(QA_EVIDENCE_ID_RX)).map((match) => match[0]);
|
|
1668
|
+
if (anchors.length === 0) {
|
|
1669
|
+
gaps.push(`${kind}.${label}: missing evidence_anchor ev_* receipt id`);
|
|
1670
|
+
}
|
|
1671
|
+
else if (!anchors.some((id) => evidenceIds.has(id))) {
|
|
1672
|
+
gaps.push(`${kind}.${label}: evidence_anchor does not resolve to an Evidence Receipt`);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
return gaps;
|
|
1677
|
+
}
|
|
1678
|
+
function latestQualityLoop(state) {
|
|
1679
|
+
const loops = Array.isArray(state.qualityLoops) ? state.qualityLoops : [];
|
|
1680
|
+
return loops.length ? loops[loops.length - 1] : null;
|
|
1681
|
+
}
|
|
1682
|
+
function normalizeCloseoutToken(value) {
|
|
1683
|
+
return String(value || '')
|
|
1684
|
+
.toLowerCase()
|
|
1685
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
1686
|
+
.replace(/^-+|-+$/g, '');
|
|
1687
|
+
}
|
|
1688
|
+
function phaseEvidenceToken(phase) {
|
|
1689
|
+
const id = normalizeCloseoutToken(phase.phaseId).replace(/^\d+-/, '');
|
|
1690
|
+
const title = normalizeCloseoutToken(phase.title).replace(/^\d+-/, '');
|
|
1691
|
+
return title || id;
|
|
1692
|
+
}
|
|
1693
|
+
function phaseOrdinalToken(phase) {
|
|
1694
|
+
const match = normalizeCloseoutToken(phase.phaseId || phase.title).match(/^(\d{2})-/);
|
|
1695
|
+
return match ? `phase-${match[1]}` : null;
|
|
1696
|
+
}
|
|
1697
|
+
function detectPartialCloseoutDrift(state) {
|
|
1698
|
+
const checkpoints = Array.isArray(state.checkpoints) ? state.checkpoints : [];
|
|
1699
|
+
const qualityLoops = Array.isArray(state.qualityLoops) ? state.qualityLoops : [];
|
|
1700
|
+
const driftedPhases = state.phases
|
|
1701
|
+
.filter((phase) => phase.status !== 'completed')
|
|
1702
|
+
.map((phase) => {
|
|
1703
|
+
const token = phaseEvidenceToken(phase);
|
|
1704
|
+
const ordinal = phaseOrdinalToken(phase);
|
|
1705
|
+
const normalizedPhaseId = normalizeCloseoutToken(phase.phaseId);
|
|
1706
|
+
const matchingCheckpoint = checkpoints.find((checkpoint) => {
|
|
1707
|
+
const checkpointPhase = normalizeCloseoutToken(checkpoint.phase);
|
|
1708
|
+
return checkpointPhase === token || checkpointPhase.endsWith(token) || token.endsWith(checkpointPhase);
|
|
1709
|
+
});
|
|
1710
|
+
const matchingQa = qualityLoops.find((loop) => {
|
|
1711
|
+
const qaFile = normalizeCloseoutToken(loop.qaFile);
|
|
1712
|
+
const phaseId = normalizeCloseoutToken(loop.phaseId);
|
|
1713
|
+
const ok = loop.ok === true;
|
|
1714
|
+
return ok && (phaseId === normalizedPhaseId || qaFile.includes(token) || (ordinal ? qaFile.includes(ordinal) : false));
|
|
1715
|
+
});
|
|
1716
|
+
if (!matchingCheckpoint || !matchingQa)
|
|
1717
|
+
return null;
|
|
1718
|
+
return {
|
|
1719
|
+
phaseId: phase.phaseId,
|
|
1720
|
+
status: phase.status,
|
|
1721
|
+
checkpointAt: matchingCheckpoint.at || null,
|
|
1722
|
+
qaAt: matchingQa.at || null,
|
|
1723
|
+
qaFile: matchingQa.qaFile || null,
|
|
1724
|
+
artifactSha256: matchingQa.artifactSha256 || null,
|
|
1725
|
+
};
|
|
1726
|
+
})
|
|
1727
|
+
.filter(Boolean);
|
|
1728
|
+
return {
|
|
1729
|
+
ok: driftedPhases.length === 0,
|
|
1730
|
+
kind: driftedPhases.length ? 'partial_closeout_drift' : 'none',
|
|
1731
|
+
driftedPhaseCount: driftedPhases.length,
|
|
1732
|
+
driftedPhases,
|
|
1733
|
+
expected: 'checkpoint evidence plus passing QA must be reconciled into phase_complete state before task completion claims',
|
|
1734
|
+
};
|
|
1735
|
+
}
|
|
1736
|
+
function buildQaLearningLoop(state, phase, qa, source, qaFile) {
|
|
1737
|
+
const gaps = Array.isArray(qa.gaps) ? qa.gaps.map(String) : [];
|
|
1738
|
+
const ok = gaps.length === 0;
|
|
1739
|
+
return {
|
|
1740
|
+
at: nowIso(),
|
|
1741
|
+
taskId: state.taskId,
|
|
1742
|
+
phaseId: phase?.phaseId || state.activePhaseId || 'unknown',
|
|
1743
|
+
source,
|
|
1744
|
+
qaFile: qaFile || null,
|
|
1745
|
+
ok,
|
|
1746
|
+
gaps,
|
|
1747
|
+
expected: 'QA artifacts include all Qiyas-15 perspectives and all Tadabbur-12 stages before completion.',
|
|
1748
|
+
observed: ok ? 'QA method contract passed.' : `QA method contract failed with ${gaps.length} gap(s).`,
|
|
1749
|
+
correctionRequired: !ok,
|
|
1750
|
+
correctionAction: ok
|
|
1751
|
+
? 'advance-or-complete-with-evidence'
|
|
1752
|
+
: 'run aria task recover, repair the QA artifact or implementation gap, re-fire skills, and rerun qa before completion',
|
|
1753
|
+
hardeningAction: ok
|
|
1754
|
+
? 'retain this QA artifact as evidence for the phase'
|
|
1755
|
+
: 'convert the failed gaps into explicit correction, enhancement, hardening, and verification rows',
|
|
1756
|
+
futurePreflight: ok
|
|
1757
|
+
? 'before the next phase, check latest quality loop and preserve the phase evidence threshold'
|
|
1758
|
+
: `before continuing, address: ${gaps.slice(0, 5).join('; ')}`,
|
|
1759
|
+
artifactSha256: typeof qa.artifactSha256 === 'string' ? qa.artifactSha256 : null,
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
async function publishQaLearningContext(state, loop) {
|
|
1763
|
+
const projectContext = state.projectContext && typeof state.projectContext === 'object' ? state.projectContext : {};
|
|
1764
|
+
const projectId = typeof projectContext.projectId === 'string'
|
|
1765
|
+
? projectContext.projectId
|
|
1766
|
+
: typeof projectContext.project_id === 'string'
|
|
1767
|
+
? projectContext.project_id
|
|
1768
|
+
: null;
|
|
1769
|
+
if (!projectId)
|
|
1770
|
+
return;
|
|
1771
|
+
const phase = activePhase(state);
|
|
1772
|
+
await runtimePost('/api/hive/project-context', {
|
|
1773
|
+
project_id: projectId,
|
|
1774
|
+
session_id: 'aria-cli-task-runner',
|
|
1775
|
+
thread_id: taskHiveThreadId(state.taskId),
|
|
1776
|
+
active_phase: phase?.phaseId || state.activePhaseId || null,
|
|
1777
|
+
event: 'aria_task_qa_learning_loop',
|
|
1778
|
+
source: 'aria-cli-task-runner',
|
|
1779
|
+
capsule: {
|
|
1780
|
+
aria_task_id: state.taskId,
|
|
1781
|
+
task_status: state.status,
|
|
1782
|
+
latest_qa: loop,
|
|
1783
|
+
correction_required: loop.correctionRequired === true,
|
|
1784
|
+
recovery_in_progress: loop.correctionRequired === true,
|
|
1785
|
+
future_preflight: loop.futurePreflight || null,
|
|
1786
|
+
},
|
|
1787
|
+
}, { attempts: 3, retryDelayMs: 250 });
|
|
1788
|
+
}
|
|
1789
|
+
async function publishRecoveryContext(state, reason) {
|
|
1790
|
+
const projectContext = state.projectContext && typeof state.projectContext === 'object' ? state.projectContext : {};
|
|
1791
|
+
const projectId = typeof projectContext.projectId === 'string'
|
|
1792
|
+
? projectContext.projectId
|
|
1793
|
+
: typeof projectContext.project_id === 'string'
|
|
1794
|
+
? projectContext.project_id
|
|
1795
|
+
: null;
|
|
1796
|
+
if (!projectId)
|
|
1797
|
+
return;
|
|
1798
|
+
const phase = activePhase(state);
|
|
1799
|
+
const loop = latestQualityLoop(state);
|
|
1800
|
+
await runtimePost('/api/hive/project-context', {
|
|
1801
|
+
project_id: projectId,
|
|
1802
|
+
session_id: 'aria-cli-task-runner',
|
|
1803
|
+
thread_id: taskHiveThreadId(state.taskId),
|
|
1804
|
+
active_phase: phase?.phaseId || state.activePhaseId || null,
|
|
1805
|
+
event: 'aria_task_recovery_context',
|
|
1806
|
+
source: 'aria-cli-task-runner',
|
|
1807
|
+
capsule: {
|
|
1808
|
+
aria_task_id: state.taskId,
|
|
1809
|
+
task_status: state.status,
|
|
1810
|
+
recovery_in_progress: true,
|
|
1811
|
+
latest_recovery: {
|
|
1812
|
+
at: nowIso(),
|
|
1813
|
+
phaseId: phase?.phaseId || state.activePhaseId || null,
|
|
1814
|
+
reason,
|
|
1815
|
+
attempts: state.recovery.attempts,
|
|
1816
|
+
},
|
|
1817
|
+
correction_required: loop?.correctionRequired === true,
|
|
1818
|
+
future_preflight: typeof loop?.futurePreflight === 'string' ? loop.futurePreflight : null,
|
|
1819
|
+
},
|
|
1820
|
+
}, { attempts: 3, retryDelayMs: 250 });
|
|
1821
|
+
}
|
|
1822
|
+
async function publishWorkerHiveContext(state, phase, event, capsule) {
|
|
1823
|
+
const projectId = `aria-task-${state.taskId}`;
|
|
1824
|
+
const payload = {
|
|
1825
|
+
project_id: projectId,
|
|
1826
|
+
session_id: 'aria-cli-task-runner',
|
|
1827
|
+
thread_id: taskHiveThreadId(state.taskId),
|
|
1828
|
+
active_phase: phase?.phaseId || state.activePhaseId || null,
|
|
1829
|
+
event,
|
|
1830
|
+
source: 'aria-task-runner',
|
|
1831
|
+
capsule: {
|
|
1832
|
+
aria_task_id: state.taskId,
|
|
1833
|
+
task_status: state.status,
|
|
1834
|
+
worker_lane: true,
|
|
1835
|
+
completion_authority: 'aria_codex_forced_qa_only',
|
|
1836
|
+
...capsule,
|
|
1837
|
+
},
|
|
1838
|
+
};
|
|
1839
|
+
try {
|
|
1840
|
+
const result = await runtimePost('/api/hive/project-context', payload, { attempts: 3, retryDelayMs: 250 });
|
|
1841
|
+
const receipt = {
|
|
1842
|
+
ok: true,
|
|
1843
|
+
route: '/api/hive/project-context',
|
|
1844
|
+
event,
|
|
1845
|
+
projectId,
|
|
1846
|
+
threadId: taskHiveThreadId(state.taskId),
|
|
1847
|
+
phaseId: phase?.phaseId || state.activePhaseId || null,
|
|
1848
|
+
result,
|
|
1849
|
+
};
|
|
1850
|
+
appendFileSync(eventPath(state.taskId), JSON.stringify({ at: nowIso(), type: 'worker_hive_context_published', ...receipt }) + '\n', { mode: 0o600 });
|
|
1851
|
+
return receipt;
|
|
1852
|
+
}
|
|
1853
|
+
catch (error) {
|
|
1854
|
+
const failure = {
|
|
1855
|
+
ok: false,
|
|
1856
|
+
route: '/api/hive/project-context',
|
|
1857
|
+
event,
|
|
1858
|
+
projectId,
|
|
1859
|
+
threadId: taskHiveThreadId(state.taskId),
|
|
1860
|
+
phaseId: phase?.phaseId || state.activePhaseId || null,
|
|
1861
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1862
|
+
recovery: 'worker lane continues only with local/runtime ledger evidence until Hive publish is repaired',
|
|
1863
|
+
};
|
|
1864
|
+
appendFileSync(eventPath(state.taskId), JSON.stringify({ at: nowIso(), type: 'worker_hive_context_failed', ...failure }) + '\n', { mode: 0o600 });
|
|
1865
|
+
return failure;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
function activePhase(state) {
|
|
1869
|
+
return state.phases.find((phase) => phase.phaseId === state.activePhaseId) || null;
|
|
1870
|
+
}
|
|
1871
|
+
function nextPendingPhase(state) {
|
|
1872
|
+
return state.phases.find((phase) => phase.status === 'pending') || null;
|
|
1873
|
+
}
|
|
1874
|
+
function phaseById(state, phaseId) {
|
|
1875
|
+
return state.phases.find((phase) => phase.phaseId === phaseId) || null;
|
|
1876
|
+
}
|
|
1877
|
+
function selectableWorkerPhase(state, requestedPhaseId) {
|
|
1878
|
+
if (requestedPhaseId)
|
|
1879
|
+
return phaseById(state, requestedPhaseId);
|
|
1880
|
+
return activePhase(state) || nextPendingPhase(state);
|
|
1881
|
+
}
|
|
1882
|
+
function phaseSummaryLines(state) {
|
|
1883
|
+
if (!state.phases.length)
|
|
1884
|
+
return ['- no phases queued'];
|
|
1885
|
+
return state.phases.map((phase) => {
|
|
1886
|
+
const marker = phase.phaseId === state.activePhaseId ? 'active' : phase.status;
|
|
1887
|
+
return `- ${phase.phaseId} [${marker}] ${phase.title}`;
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
function taskHiveThreadId(taskId) {
|
|
1891
|
+
return `thread-aria-task-${taskId}`;
|
|
1892
|
+
}
|
|
1893
|
+
function summarizeTaskProjectContext(state, payload) {
|
|
1894
|
+
const contexts = Array.isArray(payload.contexts)
|
|
1895
|
+
? payload.contexts.filter((entry) => Boolean(entry) && typeof entry === 'object')
|
|
1896
|
+
: payload.context && typeof payload.context === 'object'
|
|
1897
|
+
? [payload.context]
|
|
1898
|
+
: [];
|
|
1899
|
+
const threadId = taskHiveThreadId(state.taskId);
|
|
1900
|
+
const match = contexts.find((context) => {
|
|
1901
|
+
const capsule = context.capsule && typeof context.capsule === 'object' ? context.capsule : {};
|
|
1902
|
+
return context.latest_thread_id === threadId || capsule.thread_id === threadId || capsule.threadId === threadId || capsule.aria_task_id === state.taskId || capsule.ariaTaskId === state.taskId;
|
|
1903
|
+
});
|
|
1904
|
+
if (!match) {
|
|
1905
|
+
return {
|
|
1906
|
+
ok: false,
|
|
1907
|
+
route: '/api/hive/project-context',
|
|
1908
|
+
reason: 'no_context_for_task_thread',
|
|
1909
|
+
expectedThreadId: threadId,
|
|
1910
|
+
fetchedAt: nowIso(),
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
const capsule = match.capsule && typeof match.capsule === 'object' ? match.capsule : {};
|
|
1914
|
+
const touchedFiles = Array.isArray(payload.touched_files) ? payload.touched_files : [];
|
|
1915
|
+
const touches = Array.isArray(payload.touches) ? payload.touches : [];
|
|
1916
|
+
return {
|
|
1917
|
+
ok: true,
|
|
1918
|
+
route: '/api/hive/project-context?include_touches=true',
|
|
1919
|
+
projectId: match.project_id || capsule.project_id || null,
|
|
1920
|
+
threadId,
|
|
1921
|
+
activePhase: capsule.active_phase || capsule.activePhase || null,
|
|
1922
|
+
executor: capsule.executor || null,
|
|
1923
|
+
excludedExecutor: capsule.excluded_executor || capsule.excludedExecutor || null,
|
|
1924
|
+
sourceArtifact: capsule.source_artifact || capsule.sourceArtifact || null,
|
|
1925
|
+
touchedFileCount: touchedFiles.length,
|
|
1926
|
+
touchCount: touches.length,
|
|
1927
|
+
touchedFiles: touchedFiles.slice(0, 12).map((entry) => {
|
|
1928
|
+
const row = entry && typeof entry === 'object' ? entry : {};
|
|
1929
|
+
return {
|
|
1930
|
+
path: row.path || null,
|
|
1931
|
+
latestEvent: row.latest_event || null,
|
|
1932
|
+
latestIntent: row.latest_intent || null,
|
|
1933
|
+
latestAt: row.latest_at || null,
|
|
1934
|
+
touchCount: row.touch_count || null,
|
|
1935
|
+
};
|
|
1936
|
+
}),
|
|
1937
|
+
fetchedAt: nowIso(),
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
async function refreshTaskProjectContext(state) {
|
|
1941
|
+
try {
|
|
1942
|
+
const payload = await runtimeGet('/api/hive/project-context?include_touches=true&touch_limit=50&limit=100');
|
|
1943
|
+
const summary = summarizeTaskProjectContext(state, payload);
|
|
1944
|
+
const phase = activePhase(state);
|
|
1945
|
+
if (summary.ok === true && phase && typeof summary.projectId === 'string' && summary.projectId) {
|
|
1946
|
+
await runtimePost('/api/hive/project-context', {
|
|
1947
|
+
project_id: summary.projectId,
|
|
1948
|
+
session_id: 'aria-cli-task-runner',
|
|
1949
|
+
thread_id: taskHiveThreadId(state.taskId),
|
|
1950
|
+
active_phase: phase.phaseId,
|
|
1951
|
+
event: 'aria_task_phase_context_refresh',
|
|
1952
|
+
source: 'aria-cli-task-runner',
|
|
1953
|
+
capsule: {
|
|
1954
|
+
aria_task_id: state.taskId,
|
|
1955
|
+
task_status: state.status,
|
|
1956
|
+
},
|
|
1957
|
+
}, { attempts: 3, retryDelayMs: 250 });
|
|
1958
|
+
return {
|
|
1959
|
+
...state,
|
|
1960
|
+
projectContext: {
|
|
1961
|
+
...summary,
|
|
1962
|
+
activePhase: phase.phaseId,
|
|
1963
|
+
contextRefreshWritten: true,
|
|
1964
|
+
},
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1967
|
+
return { ...state, projectContext: summary };
|
|
1968
|
+
}
|
|
1969
|
+
catch (error) {
|
|
1970
|
+
return {
|
|
1971
|
+
...state,
|
|
1972
|
+
projectContext: {
|
|
1973
|
+
ok: false,
|
|
1974
|
+
route: '/api/hive/project-context',
|
|
1975
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1976
|
+
fetchedAt: nowIso(),
|
|
1977
|
+
},
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
function renderReinjection(state) {
|
|
1982
|
+
const phase = activePhase(state);
|
|
1983
|
+
const latestConsumerReceipt = (state.taskConsumerReceipts || [])[Math.max(0, (state.taskConsumerReceipts || []).length - 1)];
|
|
1984
|
+
return [
|
|
1985
|
+
'ARIA CLI TASK REINJECTION PACKET',
|
|
1986
|
+
`task_id: ${state.taskId}`,
|
|
1987
|
+
`state_path: ${taskPath(state.taskId)}`,
|
|
1988
|
+
`events_path: ${eventPath(state.taskId)}`,
|
|
1989
|
+
`status: ${state.status}`,
|
|
1990
|
+
`goal: ${state.goal}`,
|
|
1991
|
+
'',
|
|
1992
|
+
'Executor contract:',
|
|
1993
|
+
'- The LLM/CLI is the executor unless a bounded worker packet is issued with `aria task run --executor <worker>`.',
|
|
1994
|
+
'- Worker execution cannot complete a phase; it must return JSON to `aria task worker-ingest` and pass Aria/Codex QA.',
|
|
1995
|
+
'- Runtime is the spine for context, skill loading, ledger receipts, QA, and recovery.',
|
|
1996
|
+
'- Re-run this packet with `aria task continue ' + state.taskId + '` after compaction, interruption, or long work.',
|
|
1997
|
+
'- Claim the next phase with `aria task next ' + state.taskId + '`; complete it with `aria task complete ...`; the forced end-of-phase QA court autofires even when no QA file is supplied.',
|
|
1998
|
+
'',
|
|
1999
|
+
'Active phase:',
|
|
2000
|
+
phase ? `- ${phase.phaseId}: ${phase.title}` : '- none claimed',
|
|
2001
|
+
'',
|
|
2002
|
+
'Hive project context:',
|
|
2003
|
+
state.projectContext ? `- ${JSON.stringify(state.projectContext)}` : '- not loaded',
|
|
2004
|
+
'',
|
|
2005
|
+
'Compiled work unit:',
|
|
2006
|
+
state.compiledWorkUnit ? `- ${JSON.stringify(compiledWorkUnitSummary(state.compiledWorkUnit))}` : '- not compiled',
|
|
2007
|
+
state.compiledWorkUnitValidation ? `- validation: ${JSON.stringify(state.compiledWorkUnitValidation)}` : '- validation: not run',
|
|
2008
|
+
'',
|
|
2009
|
+
'QA correction loop:',
|
|
2010
|
+
latestQualityLoop(state) ? `- ${JSON.stringify(latestQualityLoop(state))}` : '- no QA learning loop recorded yet',
|
|
2011
|
+
'',
|
|
2012
|
+
'Task phase consumer receipt:',
|
|
2013
|
+
latestConsumerReceipt ? `- ${JSON.stringify(latestConsumerReceipt)}` : '- no task phase consumer receipt recorded yet',
|
|
2014
|
+
'',
|
|
2015
|
+
'Phase queue:',
|
|
2016
|
+
...phaseSummaryLines(state),
|
|
2017
|
+
'',
|
|
2018
|
+
`Forced skill pack (${state.requiredSkills.length}): ${state.requiredSkills.join(', ')}`,
|
|
2019
|
+
`Forced skill proof: ${JSON.stringify(state.forcedSkillLoad)}`,
|
|
2020
|
+
'',
|
|
2021
|
+
'Mandatory method artifacts for architecture/runtime/code/QA work:',
|
|
2022
|
+
`- qiyas_15_pass: ${QIYAS_15.join(', ')}`,
|
|
2023
|
+
`- tadabbur_full_canonical_12_stage: ${TADABBUR_12.join(' -> ')}`,
|
|
2024
|
+
'- correction_cycle: correct -> enhance -> harden -> verify',
|
|
2025
|
+
'- repo_doctrine: no stubs, no fake validation, no stripping, source/runtime evidence before completion claims',
|
|
2026
|
+
'- phase_completion_autofire: every phase close writes forced backend, user-facing, failure-mode, Qiyas-15, Tadabbur-12, and claim-gate QA receipts',
|
|
2027
|
+
'- task_phase_consumer_autofire: every task phase boundary writes a compact universal mechanical receipt before provider execution, QA, correction, verification, and learning',
|
|
2028
|
+
'',
|
|
2029
|
+
'Checkpoint commands:',
|
|
2030
|
+
`- aria task run ${state.taskId} --summary "<what changed>" --evidence "<proof>" --auto-qa`,
|
|
2031
|
+
`- aria task next ${state.taskId}`,
|
|
2032
|
+
`- aria task complete ${state.taskId} --summary "<what changed>" --evidence "<proof>"`,
|
|
2033
|
+
`- aria task recover ${state.taskId} --reason "<blocker>"`,
|
|
2034
|
+
`- aria task checkpoint ${state.taskId} --phase <phase> --summary "<what changed>" --evidence "<proof>"`,
|
|
2035
|
+
`- aria task qa ${state.taskId} --file <answer-or-plan.md>`,
|
|
2036
|
+
`- aria task status ${state.taskId}`,
|
|
2037
|
+
].join('\n');
|
|
2038
|
+
}
|
|
2039
|
+
async function startTask(args, cwd) {
|
|
2040
|
+
const { flags, rest } = parseFlags(args);
|
|
2041
|
+
const goal = flagString(flags, 'goal') || rest.join(' ').trim();
|
|
2042
|
+
if (!goal)
|
|
2043
|
+
throw new Error('aria task start requires --goal "..."');
|
|
2044
|
+
const taskId = sanitizeTaskId(flagString(flags, 'id') || `task-${new Date().toISOString().replace(/[:.]/g, '-')}-${randomUUID().slice(0, 8)}`);
|
|
2045
|
+
const requestedPhases = flagStrings(flags, 'phases');
|
|
2046
|
+
const phases = requestedPhases.length ? requestedPhases.map((title, index) => makePhase(title, index)) : defaultPhases(goal);
|
|
2047
|
+
const forcedSkillLoad = await forceSkillPack(taskId, goal);
|
|
2048
|
+
let state = {
|
|
2049
|
+
schema: 'aria.cli_task.v2',
|
|
2050
|
+
taskId,
|
|
2051
|
+
goal,
|
|
2052
|
+
cwd,
|
|
2053
|
+
status: 'active',
|
|
2054
|
+
createdAt: nowIso(),
|
|
2055
|
+
updatedAt: nowIso(),
|
|
2056
|
+
requiredSkills: [...ARIA_CLI_TASK_SKILLS],
|
|
2057
|
+
forcedSkillLoad,
|
|
2058
|
+
checkpoints: [],
|
|
2059
|
+
phases,
|
|
2060
|
+
activePhaseId: null,
|
|
2061
|
+
recovery: { attempts: 0, lastReason: null, lastAt: null },
|
|
2062
|
+
};
|
|
2063
|
+
state = attachCompiledWorkUnit(state, forcedSkillLoad);
|
|
2064
|
+
state = saveTask(state, { type: 'task_start', goal, forcedSkillLoad, phases });
|
|
2065
|
+
const substrateOpen = await openTaskSubstrate(state, 'task_start', null);
|
|
2066
|
+
const refreshedState = await refreshTaskProjectContext(state);
|
|
2067
|
+
state = saveTask(refreshedState, { type: 'project_context_refresh', projectContext: refreshedState.projectContext });
|
|
2068
|
+
state = await consumeTaskPhaseBoundary(state, 'task_start', null, {
|
|
2069
|
+
summary: 'task created and universal skill/runtime packet consumed',
|
|
2070
|
+
evidence: `forcedSkillLoad.loadedCount=${forcedSkillLoad.loadedCount}; activeRuntimeCount=${forcedSkillLoad.activeRuntimeCount}`,
|
|
2071
|
+
action: 'print-reinjection-packet',
|
|
2072
|
+
});
|
|
2073
|
+
await recordRuntimeLedger(state, 'task_start', { goal, phases }, { forcedSkillLoad, substrateOpen });
|
|
2074
|
+
console.log(renderReinjection(state));
|
|
2075
|
+
}
|
|
2076
|
+
async function continueTask(args) {
|
|
2077
|
+
const { flags, rest } = parseFlags(args);
|
|
2078
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
2079
|
+
let state = loadTask(taskId);
|
|
2080
|
+
const forcedSkillLoad = await forceSkillPack(state.taskId, state.goal);
|
|
2081
|
+
state = saveTask(attachCompiledWorkUnit({ ...state, forcedSkillLoad }, forcedSkillLoad), { type: 'task_continue', forcedSkillLoad });
|
|
2082
|
+
const refreshedState = await refreshTaskProjectContext(state);
|
|
2083
|
+
state = saveTask(refreshedState, { type: 'project_context_refresh', projectContext: refreshedState.projectContext });
|
|
2084
|
+
state = await consumeTaskPhaseBoundary(state, 'task_continue', activePhase(state), {
|
|
2085
|
+
summary: 'task continuation refreshed universal skill/runtime packet',
|
|
2086
|
+
evidence: `forcedSkillLoad.loadedCount=${forcedSkillLoad.loadedCount}; activeRuntimeCount=${forcedSkillLoad.activeRuntimeCount}`,
|
|
2087
|
+
action: 'reinject-active-task-context',
|
|
2088
|
+
});
|
|
2089
|
+
await recordRuntimeLedger(state, 'task_continue', { checkpointCount: state.checkpoints.length }, { forcedSkillLoad });
|
|
2090
|
+
console.log(renderReinjection(state));
|
|
2091
|
+
}
|
|
2092
|
+
async function enqueueTask(args) {
|
|
2093
|
+
const { flags, rest } = parseFlags(args);
|
|
2094
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
2095
|
+
const phaseTitle = flagString(flags, 'phase') || rest.slice(1).join(' ').trim();
|
|
2096
|
+
if (!phaseTitle)
|
|
2097
|
+
throw new Error('aria task enqueue requires --phase "..."');
|
|
2098
|
+
const state = loadTask(taskId);
|
|
2099
|
+
const phase = makePhase(phaseTitle, state.phases.length);
|
|
2100
|
+
const next = saveTask({ ...state, status: 'active', phases: [...state.phases, phase] }, { type: 'phase_enqueue', phase });
|
|
2101
|
+
await recordRuntimeLedger(next, 'phase_enqueue', { phase }, { phase });
|
|
2102
|
+
console.log(JSON.stringify({ ok: true, taskId, phase, statePath: taskPath(taskId) }, null, 2));
|
|
2103
|
+
}
|
|
2104
|
+
async function nextTask(args) {
|
|
2105
|
+
const { flags, rest } = parseFlags(args);
|
|
2106
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
2107
|
+
let state = loadTask(taskId);
|
|
2108
|
+
const forcedSkillLoad = await forceSkillPack(state.taskId, state.goal);
|
|
2109
|
+
state = attachCompiledWorkUnit({ ...state, forcedSkillLoad }, forcedSkillLoad);
|
|
2110
|
+
const current = activePhase(state);
|
|
2111
|
+
if (current && current.status === 'in_progress') {
|
|
2112
|
+
state = saveTask(state, { type: 'phase_resume', phase: current, forcedSkillLoad });
|
|
2113
|
+
const refreshedState = await refreshTaskProjectContext(state);
|
|
2114
|
+
state = saveTask(attachCompiledWorkUnit(refreshedState, forcedSkillLoad), { type: 'project_context_refresh', projectContext: refreshedState.projectContext });
|
|
2115
|
+
state = await consumeTaskPhaseBoundary(state, 'phase_resume', current, {
|
|
2116
|
+
summary: 'active phase resumed with refreshed universal packet',
|
|
2117
|
+
evidence: `phase=${current.phaseId}; forcedSkillLoad.loadedCount=${forcedSkillLoad.loadedCount}`,
|
|
2118
|
+
action: 'resume-phase-execution',
|
|
2119
|
+
});
|
|
2120
|
+
await recordRuntimeLedger(state, 'phase_resume', { phase: current }, { forcedSkillLoad, phase: current });
|
|
2121
|
+
console.log(renderReinjection(state));
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
const pending = nextPendingPhase(state);
|
|
2125
|
+
if (!pending) {
|
|
2126
|
+
const allComplete = state.phases.length > 0 && state.phases.every((phase) => phase.status === 'completed');
|
|
2127
|
+
let next = saveTask({ ...state, status: allComplete ? 'completed' : state.status, activePhaseId: null }, { type: allComplete ? 'task_completed' : 'phase_next_none' });
|
|
2128
|
+
next = await consumeTaskPhaseBoundary(next, allComplete ? 'task_completed' : 'phase_next_none', null, {
|
|
2129
|
+
summary: allComplete ? 'all phases completed at next-phase boundary' : 'no phase available at next-phase boundary',
|
|
2130
|
+
evidence: `phaseCount=${next.phases.length}`,
|
|
2131
|
+
action: allComplete ? 'close-task' : 'report-no-phase',
|
|
2132
|
+
});
|
|
2133
|
+
await recordRuntimeLedger(next, allComplete ? 'task_completed' : 'phase_next_none', { phaseCount: next.phases.length }, { forcedSkillLoad });
|
|
2134
|
+
console.log(renderReinjection(next));
|
|
2135
|
+
return;
|
|
2136
|
+
}
|
|
2137
|
+
const startedAt = nowIso();
|
|
2138
|
+
const phases = state.phases.map((phase) => phase.phaseId === pending.phaseId
|
|
2139
|
+
? { ...phase, status: 'in_progress', startedAt, attempts: phase.attempts + 1 }
|
|
2140
|
+
: phase);
|
|
2141
|
+
state = saveTask(attachCompiledWorkUnit({ ...state, status: 'active', activePhaseId: pending.phaseId, phases }, forcedSkillLoad), { type: 'phase_start', phaseId: pending.phaseId, forcedSkillLoad });
|
|
2142
|
+
const substrateOpen = await openTaskSubstrate(state, 'phase_start', pending.phaseId);
|
|
2143
|
+
const refreshedState = await refreshTaskProjectContext(state);
|
|
2144
|
+
state = saveTask(attachCompiledWorkUnit(refreshedState, forcedSkillLoad), { type: 'project_context_refresh', projectContext: refreshedState.projectContext });
|
|
2145
|
+
state = await consumeTaskPhaseBoundary(state, 'phase_start', activePhase(state) || pending, {
|
|
2146
|
+
summary: 'phase claimed with universal task phase consumer receipt',
|
|
2147
|
+
evidence: `phase=${pending.phaseId}; forcedSkillLoad.loadedCount=${forcedSkillLoad.loadedCount}`,
|
|
2148
|
+
action: 'begin-phase-work',
|
|
2149
|
+
});
|
|
2150
|
+
await recordRuntimeLedger(state, 'phase_start', { phase: activePhase(state) }, { forcedSkillLoad, phase: activePhase(state) || pending, substrateOpen });
|
|
2151
|
+
console.log(renderReinjection(state));
|
|
2152
|
+
}
|
|
2153
|
+
async function completeTask(args) {
|
|
2154
|
+
const { flags, rest } = parseFlags(args);
|
|
2155
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
2156
|
+
const summary = flagString(flags, 'summary') || rest.slice(1).join(' ').trim();
|
|
2157
|
+
const evidence = flagString(flags, 'evidence');
|
|
2158
|
+
const qaFile = flagString(flags, 'qa-file') || flagString(flags, 'qa');
|
|
2159
|
+
if (!summary)
|
|
2160
|
+
throw new Error('aria task complete requires --summary "..."');
|
|
2161
|
+
if (!evidence)
|
|
2162
|
+
throw new Error('aria task complete requires --evidence "..."');
|
|
2163
|
+
const state = attachCompiledWorkUnit(loadTask(taskId));
|
|
2164
|
+
const current = activePhase(state);
|
|
2165
|
+
if (!current)
|
|
2166
|
+
throw new Error('No active phase. Run `aria task next` first.');
|
|
2167
|
+
const compiledValidation = validateCompiledWorkUnitForExecution(state.compiledWorkUnit || null);
|
|
2168
|
+
if (!compiledValidation.ok) {
|
|
2169
|
+
throw new Error(`Cannot complete task phase without executable CompiledWorkUnit: ${compiledValidation.gaps.join('; ')}`);
|
|
2170
|
+
}
|
|
2171
|
+
let finalSummary = summary;
|
|
2172
|
+
let finalEvidence = evidence;
|
|
2173
|
+
let qaSource = qaFile || 'forced-end-phase-autofire';
|
|
2174
|
+
let qaText = qaFile
|
|
2175
|
+
? readFileSync(path.resolve(qaFile), 'utf8')
|
|
2176
|
+
: buildAutoQaArtifact(state, current, summary, evidence);
|
|
2177
|
+
let methodContractGaps = methodGaps(qaText);
|
|
2178
|
+
let qaBase = {
|
|
2179
|
+
at: nowIso(),
|
|
2180
|
+
ok: methodContractGaps.length === 0,
|
|
2181
|
+
gaps: methodContractGaps,
|
|
2182
|
+
artifactSha256: sha256(qaText),
|
|
2183
|
+
source: qaSource,
|
|
2184
|
+
autofire: {
|
|
2185
|
+
mode: 'forced_end_of_phase_qa',
|
|
2186
|
+
trigger: 'phase_close',
|
|
2187
|
+
suites: [...END_OF_PHASE_QA_SUITES],
|
|
2188
|
+
hard_stop_only_for: [...END_OF_PHASE_QA_HARD_STOP_ONLY_FOR],
|
|
2189
|
+
},
|
|
2190
|
+
};
|
|
2191
|
+
let autoRecovery = null;
|
|
2192
|
+
let endPhaseQaAutofire = buildTaskRunnerEndPhaseQaAutofire({
|
|
2193
|
+
state,
|
|
2194
|
+
phase: current,
|
|
2195
|
+
summary: finalSummary,
|
|
2196
|
+
evidence: finalEvidence,
|
|
2197
|
+
qa: qaBase,
|
|
2198
|
+
qaSource,
|
|
2199
|
+
});
|
|
2200
|
+
let claimGateVerdict = String(endPhaseQaAutofire.receipt.claim_gate?.verdict || 'blocked');
|
|
2201
|
+
const needsAutoRecovery = methodContractGaps.length > 0 || claimGateVerdict === 'partial';
|
|
2202
|
+
if (needsAutoRecovery) {
|
|
2203
|
+
autoRecovery = {
|
|
2204
|
+
attempted: true,
|
|
2205
|
+
mode: 'bounded_claim_rewrite_and_rerun',
|
|
2206
|
+
reason: methodContractGaps.length > 0
|
|
2207
|
+
? 'method QA gaps or overbroad closeout claim detected at phase close'
|
|
2208
|
+
: 'completion claim exceeded forced QA evidence at phase close',
|
|
2209
|
+
initialVerdict: claimGateVerdict,
|
|
2210
|
+
initialGapCount: methodContractGaps.length,
|
|
2211
|
+
originalSummaryHash: sha256(summary),
|
|
2212
|
+
originalEvidenceHash: sha256(evidence),
|
|
2213
|
+
startedAt: nowIso(),
|
|
2214
|
+
};
|
|
2215
|
+
finalSummary = buildBoundedTaskRecoverySummary();
|
|
2216
|
+
finalEvidence = buildBoundedTaskRecoveryEvidence();
|
|
2217
|
+
qaSource = `${qaSource}+auto-recovery`;
|
|
2218
|
+
qaText = buildAutoQaArtifact(state, current, finalSummary, finalEvidence);
|
|
2219
|
+
methodContractGaps = methodGaps(qaText);
|
|
2220
|
+
qaBase = {
|
|
2221
|
+
at: nowIso(),
|
|
2222
|
+
ok: methodContractGaps.length === 0,
|
|
2223
|
+
gaps: methodContractGaps,
|
|
2224
|
+
artifactSha256: sha256(qaText),
|
|
2225
|
+
source: qaSource,
|
|
2226
|
+
autofire: {
|
|
2227
|
+
mode: 'forced_end_of_phase_qa',
|
|
2228
|
+
trigger: 'phase_close',
|
|
2229
|
+
suites: [...END_OF_PHASE_QA_SUITES],
|
|
2230
|
+
hard_stop_only_for: [...END_OF_PHASE_QA_HARD_STOP_ONLY_FOR],
|
|
2231
|
+
},
|
|
2232
|
+
};
|
|
2233
|
+
autoRecovery = {
|
|
2234
|
+
...autoRecovery,
|
|
2235
|
+
completedAt: nowIso(),
|
|
2236
|
+
finalGapCount: methodContractGaps.length,
|
|
2237
|
+
recoveredSummaryHash: sha256(finalSummary),
|
|
2238
|
+
recoveredEvidenceHash: sha256(finalEvidence),
|
|
2239
|
+
recoveryQaSha256: sha256(qaText),
|
|
2240
|
+
};
|
|
2241
|
+
endPhaseQaAutofire = buildTaskRunnerEndPhaseQaAutofire({
|
|
2242
|
+
state,
|
|
2243
|
+
phase: current,
|
|
2244
|
+
summary: finalSummary,
|
|
2245
|
+
evidence: finalEvidence,
|
|
2246
|
+
qa: qaBase,
|
|
2247
|
+
qaSource,
|
|
2248
|
+
autoRecovery,
|
|
2249
|
+
});
|
|
2250
|
+
claimGateVerdict = String(endPhaseQaAutofire.receipt.claim_gate?.verdict || 'blocked');
|
|
2251
|
+
}
|
|
2252
|
+
const claimGateGaps = claimGateVerdict === 'verified' || claimGateVerdict === 'verified_narrowly' ? [] : [`end-of-phase claim gate verdict: ${claimGateVerdict}`];
|
|
2253
|
+
const gaps = [...methodContractGaps, ...claimGateGaps];
|
|
2254
|
+
const qa = {
|
|
2255
|
+
...qaBase,
|
|
2256
|
+
ok: gaps.length === 0,
|
|
2257
|
+
gaps,
|
|
2258
|
+
endPhaseQaAutofire: {
|
|
2259
|
+
verdict: claimGateVerdict,
|
|
2260
|
+
receiptHash: endPhaseQaAutofire.receipt.receipt_hash,
|
|
2261
|
+
latestPath: endPhaseQaAutofire.latestPath,
|
|
2262
|
+
eventPath: endPhaseQaAutofire.eventPath,
|
|
2263
|
+
autoRecovery,
|
|
2264
|
+
},
|
|
2265
|
+
};
|
|
2266
|
+
const qaLearningLoop = buildQaLearningLoop(state, current, qa, 'complete', qaSource);
|
|
2267
|
+
const qualityLoops = [...(state.qualityLoops || []), qaLearningLoop].slice(-50);
|
|
2268
|
+
const phases = state.phases.map((phase) => {
|
|
2269
|
+
if (phase.phaseId !== current.phaseId)
|
|
2270
|
+
return phase;
|
|
2271
|
+
return {
|
|
2272
|
+
...phase,
|
|
2273
|
+
status: gaps.length ? 'qa_failed' : 'completed',
|
|
2274
|
+
completedAt: gaps.length ? undefined : nowIso(),
|
|
2275
|
+
summary: finalSummary,
|
|
2276
|
+
evidence: finalEvidence,
|
|
2277
|
+
qa,
|
|
2278
|
+
};
|
|
2279
|
+
});
|
|
2280
|
+
const nextStatus = gaps.length ? 'blocked' : 'active';
|
|
2281
|
+
let next = saveTask({
|
|
2282
|
+
...state,
|
|
2283
|
+
status: nextStatus,
|
|
2284
|
+
activePhaseId: gaps.length ? current.phaseId : null,
|
|
2285
|
+
phases,
|
|
2286
|
+
qualityLoops,
|
|
2287
|
+
checkpoints: [...state.checkpoints, { at: nowIso(), phase: current.phaseId, summary: finalSummary, evidence: finalEvidence, originalSummary: summary, originalEvidence: evidence, qa }],
|
|
2288
|
+
}, { type: gaps.length ? 'phase_qa_failed' : 'phase_complete', phaseId: current.phaseId, summary: finalSummary, evidence: finalEvidence, originalSummary: summary, originalEvidence: evidence, qa, qaLearningLoop, endPhaseQaAutofire });
|
|
2289
|
+
next = await consumeTaskPhaseBoundary(next, gaps.length ? 'phase_qa_failed' : 'phase_complete', phases.find((phase) => phase.phaseId === current.phaseId) || current, {
|
|
2290
|
+
step: 'phase-close-forced-qa',
|
|
2291
|
+
summary: finalSummary,
|
|
2292
|
+
evidence: finalEvidence,
|
|
2293
|
+
qa,
|
|
2294
|
+
gaps,
|
|
2295
|
+
action: gaps.length ? 'recover-phase-before-advance' : 'advance-to-next-phase',
|
|
2296
|
+
});
|
|
2297
|
+
await publishQaLearningContext({ ...next, activePhaseId: current.phaseId }, qaLearningLoop);
|
|
2298
|
+
await recordRuntimeLedger(next, gaps.length ? 'phase_qa_failed' : 'phase_complete', { phase: phases.find((phase) => phase.phaseId === current.phaseId), qa, qaLearningLoop, endPhaseQaAutofire: qa.endPhaseQaAutofire }, { gaps, evidence: finalEvidence, originalEvidence: evidence, qa, qaLearningLoop, endPhaseQaAutofire: qa.endPhaseQaAutofire });
|
|
2299
|
+
console.log(JSON.stringify({ ok: gaps.length === 0, taskId, phaseId: current.phaseId, gaps, autoRecovery, endPhaseQaAutofire: qa.endPhaseQaAutofire, next: gaps.length ? 'run aria task recover' : 'run aria task next' }, null, 2));
|
|
2300
|
+
if (gaps.length)
|
|
2301
|
+
process.exit(1);
|
|
2302
|
+
}
|
|
2303
|
+
async function closeTask(args) {
|
|
2304
|
+
const { flags, rest } = parseFlags(args);
|
|
2305
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
2306
|
+
const summary = flagString(flags, 'summary') || 'all task phases completed and final task closeout requested';
|
|
2307
|
+
const evidence = flagString(flags, 'evidence') || 'task closeout gate checked phase state, QA state, runtime skill floor, and closeout drift';
|
|
2308
|
+
let state = loadTask(taskId);
|
|
2309
|
+
const alreadyClosed = state.status === 'completed';
|
|
2310
|
+
const forcedSkillLoad = await forceSkillPack(state.taskId, state.goal);
|
|
2311
|
+
state = attachCompiledWorkUnit({ ...state, forcedSkillLoad }, forcedSkillLoad);
|
|
2312
|
+
const closeoutDrift = detectPartialCloseoutDrift(state);
|
|
2313
|
+
const latestQa = latestQualityLoop(state);
|
|
2314
|
+
const incompletePhases = state.phases.filter((phase) => phase.status !== 'completed');
|
|
2315
|
+
const completedWithoutQa = state.phases.filter((phase) => phase.status === 'completed' && phase.qa && phase.qa.ok !== true);
|
|
2316
|
+
const gaps = [
|
|
2317
|
+
...(state.activePhaseId ? [`active phase still claimed: ${state.activePhaseId}`] : []),
|
|
2318
|
+
...incompletePhases.map((phase) => `phase not completed: ${phase.phaseId} (${phase.status})`),
|
|
2319
|
+
...completedWithoutQa.map((phase) => `completed phase has failing QA: ${phase.phaseId}`),
|
|
2320
|
+
...(closeoutDrift.ok === false ? [`partial closeout drift: ${String(closeoutDrift.kind || 'unknown')}`] : []),
|
|
2321
|
+
...(Number(forcedSkillLoad.loadedCount || 0) < UNIVERSAL_TURN_PACKET_SKILL_FLOOR
|
|
2322
|
+
? [`forced skill floor not met: ${Number(forcedSkillLoad.loadedCount || 0)}/${UNIVERSAL_TURN_PACKET_SKILL_FLOOR}`]
|
|
2323
|
+
: []),
|
|
2324
|
+
...(Number(forcedSkillLoad.activeRuntimeCount || 0) < UNIVERSAL_TURN_PACKET_RUNTIME_FLOOR
|
|
2325
|
+
? [`runtime floor not met: ${Number(forcedSkillLoad.activeRuntimeCount || 0)}/${UNIVERSAL_TURN_PACKET_RUNTIME_FLOOR}`]
|
|
2326
|
+
: []),
|
|
2327
|
+
...(latestQa && latestQa.ok === false ? ['latest QA learning loop is failing'] : []),
|
|
2328
|
+
];
|
|
2329
|
+
if (gaps.length > 0) {
|
|
2330
|
+
state = saveTask({ ...state, status: 'blocked', activePhaseId: state.activePhaseId }, {
|
|
2331
|
+
type: 'task_close_blocked',
|
|
2332
|
+
summary,
|
|
2333
|
+
evidence,
|
|
2334
|
+
gaps,
|
|
2335
|
+
closeoutDrift,
|
|
2336
|
+
forcedSkillLoad,
|
|
2337
|
+
});
|
|
2338
|
+
state = await consumeTaskPhaseBoundary(state, 'task_close_blocked', activePhase(state), {
|
|
2339
|
+
step: 'task-close',
|
|
2340
|
+
summary,
|
|
2341
|
+
evidence,
|
|
2342
|
+
gaps,
|
|
2343
|
+
action: 'repair-before-task-close',
|
|
2344
|
+
});
|
|
2345
|
+
await recordRuntimeLedger(state, 'task_close_blocked', { summary, evidence, gaps, closeoutDrift }, { forcedSkillLoad });
|
|
2346
|
+
console.log(JSON.stringify({
|
|
2347
|
+
ok: false,
|
|
2348
|
+
taskId,
|
|
2349
|
+
status: state.status,
|
|
2350
|
+
gaps,
|
|
2351
|
+
closeoutDrift,
|
|
2352
|
+
next: `repair gaps, then run aria task close ${taskId} --summary "..." --evidence "..."`,
|
|
2353
|
+
}, null, 2));
|
|
2354
|
+
process.exit(1);
|
|
2355
|
+
}
|
|
2356
|
+
state = saveTask({ ...state, status: 'completed', activePhaseId: null, forcedSkillLoad }, {
|
|
2357
|
+
type: 'task_closed',
|
|
2358
|
+
summary,
|
|
2359
|
+
evidence,
|
|
2360
|
+
forcedSkillLoad,
|
|
2361
|
+
closeoutDrift,
|
|
2362
|
+
});
|
|
2363
|
+
state = await consumeTaskPhaseBoundary(state, 'task_closed', null, {
|
|
2364
|
+
step: 'task-close',
|
|
2365
|
+
summary,
|
|
2366
|
+
evidence,
|
|
2367
|
+
action: 'finalize-task-ledger',
|
|
2368
|
+
});
|
|
2369
|
+
await recordRuntimeLedger(state, 'task_completed', {
|
|
2370
|
+
summary,
|
|
2371
|
+
evidence,
|
|
2372
|
+
phaseCount: state.phases.length,
|
|
2373
|
+
completedPhaseCount: state.phases.filter((phase) => phase.status === 'completed').length,
|
|
2374
|
+
}, { forcedSkillLoad, closeoutDrift });
|
|
2375
|
+
console.log(JSON.stringify({
|
|
2376
|
+
ok: true,
|
|
2377
|
+
taskId,
|
|
2378
|
+
status: state.status,
|
|
2379
|
+
alreadyClosed,
|
|
2380
|
+
activePhaseId: state.activePhaseId,
|
|
2381
|
+
completedPhaseCount: state.phases.filter((phase) => phase.status === 'completed').length,
|
|
2382
|
+
phaseCount: state.phases.length,
|
|
2383
|
+
forcedSkillLoad: summarizeForcedSkillLoad(forcedSkillLoad),
|
|
2384
|
+
closeoutDrift,
|
|
2385
|
+
statePath: taskPath(taskId),
|
|
2386
|
+
eventsPath: eventPath(taskId),
|
|
2387
|
+
}, null, 2));
|
|
2388
|
+
}
|
|
2389
|
+
async function runCodexExecutorTask(taskId, flags, summary, evidence) {
|
|
2390
|
+
const codexBin = resolveCodexExecutorBin(flags);
|
|
2391
|
+
const runAll = flags.all === true;
|
|
2392
|
+
const dryRun = flags['dry-run'] === true;
|
|
2393
|
+
const sandbox = flagString(flags, 'sandbox') || 'danger-full-access';
|
|
2394
|
+
const qaFileHint = flagString(flags, 'qa-file') || flagString(flags, 'qa') || '';
|
|
2395
|
+
const completedPhases = [];
|
|
2396
|
+
while (true) {
|
|
2397
|
+
let state = loadTask(taskId);
|
|
2398
|
+
const forcedSkillLoad = await forceSkillPack(state.taskId, state.goal);
|
|
2399
|
+
const fullPromptBuild = await buildSkillPrompt(state.taskId, state.goal, ARIA_CLI_TASK_SKILLS, 'codex-executor');
|
|
2400
|
+
const fullPromptSummary = summarizeForcedSkillLoad(fullPromptBuild);
|
|
2401
|
+
assertCompleteSkillLoad(fullPromptSummary, 'codex executor');
|
|
2402
|
+
state = saveTask({ ...state, forcedSkillLoad, status: 'active' }, {
|
|
2403
|
+
type: 'codex_executor_forced_skill_refire',
|
|
2404
|
+
forcedSkillLoad,
|
|
2405
|
+
codexSkillPrompt: fullPromptSummary,
|
|
2406
|
+
});
|
|
2407
|
+
state = await consumeTaskPhaseBoundary(state, 'codex_executor_forced_skill_refire', activePhase(state), {
|
|
2408
|
+
step: 'codex-executor-forced-skill-refire',
|
|
2409
|
+
summary: 'Codex executor refreshed universal task packet before provider launch',
|
|
2410
|
+
evidence: `forcedSkillLoad.loadedCount=${forcedSkillLoad.loadedCount}; activeRuntimeCount=${forcedSkillLoad.activeRuntimeCount}`,
|
|
2411
|
+
action: 'prepare-codex-executor-phase',
|
|
2412
|
+
});
|
|
2413
|
+
await recordRuntimeLedger(state, 'codex_executor_forced_skill_refire', {
|
|
2414
|
+
executor: 'codex',
|
|
2415
|
+
completedPhases,
|
|
2416
|
+
}, { forcedSkillLoad, codexSkillPrompt: fullPromptSummary });
|
|
2417
|
+
let current = activePhase(state);
|
|
2418
|
+
if (!current || current.status !== 'in_progress') {
|
|
2419
|
+
const pending = current && (current.status === 'qa_failed' || current.status === 'blocked') ? current : nextPendingPhase(state);
|
|
2420
|
+
if (!pending) {
|
|
2421
|
+
const allComplete = state.phases.length > 0 && state.phases.every((phase) => phase.status === 'completed');
|
|
2422
|
+
state = saveTask({ ...state, status: allComplete ? 'completed' : state.status, activePhaseId: null }, {
|
|
2423
|
+
type: allComplete ? 'task_completed' : 'codex_executor_no_phase',
|
|
2424
|
+
completedPhases,
|
|
2425
|
+
});
|
|
2426
|
+
state = await consumeTaskPhaseBoundary(state, allComplete ? 'codex_executor_task_completed' : 'codex_executor_no_phase', null, {
|
|
2427
|
+
step: 'codex-executor-no-phase',
|
|
2428
|
+
summary: allComplete ? 'Codex executor observed all phases complete' : 'Codex executor found no runnable phase',
|
|
2429
|
+
evidence: `completedPhases=${completedPhases.length}`,
|
|
2430
|
+
action: allComplete ? 'close-task' : 'report-no-phase',
|
|
2431
|
+
});
|
|
2432
|
+
await recordRuntimeLedger(state, allComplete ? 'task_completed' : 'codex_executor_no_phase', { completedPhases }, { executor: 'codex' });
|
|
2433
|
+
console.log(JSON.stringify({ ok: allComplete, executor: 'codex', taskId, status: state.status, completedPhases, statePath: taskPath(taskId), eventsPath: eventPath(taskId) }, null, 2));
|
|
2434
|
+
return;
|
|
2435
|
+
}
|
|
2436
|
+
const startedAt = nowIso();
|
|
2437
|
+
const phases = state.phases.map((phase) => phase.phaseId === pending.phaseId
|
|
2438
|
+
? { ...phase, status: 'in_progress', startedAt: phase.startedAt || startedAt, attempts: phase.attempts + 1 }
|
|
2439
|
+
: phase);
|
|
2440
|
+
state = saveTask({ ...state, activePhaseId: pending.phaseId, phases }, {
|
|
2441
|
+
type: 'codex_executor_phase_claim',
|
|
2442
|
+
phaseId: pending.phaseId,
|
|
2443
|
+
});
|
|
2444
|
+
state = await consumeTaskPhaseBoundary(state, 'codex_executor_phase_claim', activePhase(state) || pending, {
|
|
2445
|
+
step: 'codex-executor-phase-claim',
|
|
2446
|
+
summary: 'Codex executor claimed phase after universal packet refresh',
|
|
2447
|
+
evidence: `phase=${pending.phaseId}`,
|
|
2448
|
+
action: 'launch-wrapped-codex-exec',
|
|
2449
|
+
});
|
|
2450
|
+
await recordRuntimeLedger(state, 'codex_executor_phase_claim', { phase: activePhase(state) }, { executor: 'codex', phase: activePhase(state) || pending });
|
|
2451
|
+
current = activePhase(state);
|
|
2452
|
+
}
|
|
2453
|
+
if (!current)
|
|
2454
|
+
throw new Error('aria task run --executor codex could not claim or resume a phase.');
|
|
2455
|
+
state = saveTask({ ...state, checkpoints: [...state.checkpoints, { at: nowIso(), phase: current.phaseId, receipt: 'codex-pre-phase', summary, evidence }] }, {
|
|
2456
|
+
type: 'codex_executor_pre_phase',
|
|
2457
|
+
phaseId: current.phaseId,
|
|
2458
|
+
});
|
|
2459
|
+
state = await consumeTaskPhaseBoundary(state, 'codex_executor_pre_phase', current, {
|
|
2460
|
+
step: 'codex-executor-pre-phase',
|
|
2461
|
+
summary,
|
|
2462
|
+
evidence,
|
|
2463
|
+
action: 'build-codex-executor-prompt',
|
|
2464
|
+
});
|
|
2465
|
+
await recordRuntimeLedger(state, 'codex_executor_pre_phase', { phase: current, summary, evidence }, { executor: 'codex' });
|
|
2466
|
+
const skillPrompt = typeof fullPromptBuild.prompt === 'string' ? fullPromptBuild.prompt : '';
|
|
2467
|
+
if (!skillPrompt)
|
|
2468
|
+
throw new Error('runtime /build-system-prompt did not return a Codex skill prompt.');
|
|
2469
|
+
const prompt = buildCodexExecutorPrompt(state, current, skillPrompt, summary, evidence, qaFileHint);
|
|
2470
|
+
const promptPath = codexPromptPath(state.taskId);
|
|
2471
|
+
writeFileSync(promptPath, prompt + '\n', { mode: 0o600 });
|
|
2472
|
+
const codexArgs = [
|
|
2473
|
+
'exec',
|
|
2474
|
+
'-C',
|
|
2475
|
+
state.cwd,
|
|
2476
|
+
'-s',
|
|
2477
|
+
sandbox,
|
|
2478
|
+
'-',
|
|
2479
|
+
];
|
|
2480
|
+
state = saveTask({ ...state, checkpoints: [...state.checkpoints, { at: nowIso(), phase: current.phaseId, receipt: 'codex-exec-dispatch', promptPath, codexBin, codexArgs }] }, {
|
|
2481
|
+
type: 'codex_executor_dispatch',
|
|
2482
|
+
phaseId: current.phaseId,
|
|
2483
|
+
promptPath,
|
|
2484
|
+
codexBin,
|
|
2485
|
+
codexArgs,
|
|
2486
|
+
dryRun,
|
|
2487
|
+
});
|
|
2488
|
+
state = await consumeTaskPhaseBoundary(state, 'codex_executor_dispatch', current, {
|
|
2489
|
+
step: 'codex-executor-dispatch',
|
|
2490
|
+
summary: 'Wrapped Codex execution dispatch prepared with compact mechanical packet prompt',
|
|
2491
|
+
evidence: `promptPath=${promptPath}; dryRun=${dryRun}; promptChars=${prompt.length}`,
|
|
2492
|
+
action: dryRun ? 'return-dry-run-proof' : 'execute-wrapped-codex',
|
|
2493
|
+
});
|
|
2494
|
+
await recordRuntimeLedger(state, 'codex_executor_dispatch', { phase: current, promptPath, codexBin, codexArgs, dryRun }, { executor: 'codex' });
|
|
2495
|
+
if (dryRun) {
|
|
2496
|
+
console.log(JSON.stringify({ ok: true, dryRun: true, executor: 'codex', taskId, phaseId: current.phaseId, codexBin, codexArgs, promptPath, promptChars: prompt.length }, null, 2));
|
|
2497
|
+
return;
|
|
2498
|
+
}
|
|
2499
|
+
const result = spawnSync(codexBin, codexArgs, {
|
|
2500
|
+
cwd: state.cwd,
|
|
2501
|
+
input: prompt,
|
|
2502
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
2503
|
+
env: {
|
|
2504
|
+
...process.env,
|
|
2505
|
+
ARIA_RUNTIME_URL: RUNTIME_URL,
|
|
2506
|
+
ARIA_TASK_ID: state.taskId,
|
|
2507
|
+
ARIA_TASK_PHASE_ID: current.phaseId,
|
|
2508
|
+
},
|
|
2509
|
+
});
|
|
2510
|
+
const exitCode = typeof result.status === 'number' ? result.status : 1;
|
|
2511
|
+
state = loadTask(taskId);
|
|
2512
|
+
state = saveTask(state, {
|
|
2513
|
+
type: 'codex_executor_exit',
|
|
2514
|
+
phaseId: current.phaseId,
|
|
2515
|
+
exitCode,
|
|
2516
|
+
signal: result.signal,
|
|
2517
|
+
error: result.error ? result.error.message : null,
|
|
2518
|
+
});
|
|
2519
|
+
state = await consumeTaskPhaseBoundary(state, 'codex_executor_exit', current, {
|
|
2520
|
+
step: 'codex-executor-exit',
|
|
2521
|
+
summary: 'Wrapped Codex executor returned control to parent task runner',
|
|
2522
|
+
evidence: `exitCode=${exitCode}; signal=${result.signal || 'none'}`,
|
|
2523
|
+
gaps: exitCode === 0 && !result.error ? [] : [`codex executor exitCode=${exitCode}`],
|
|
2524
|
+
action: exitCode === 0 && !result.error ? 'verify-phase-completed' : 'stop-on-executor-failure',
|
|
2525
|
+
});
|
|
2526
|
+
await recordRuntimeLedger(state, 'codex_executor_exit', {
|
|
2527
|
+
phase: current,
|
|
2528
|
+
exitCode,
|
|
2529
|
+
signal: result.signal,
|
|
2530
|
+
error: result.error ? result.error.message : null,
|
|
2531
|
+
}, { executor: 'codex' });
|
|
2532
|
+
if (exitCode !== 0 || result.error) {
|
|
2533
|
+
console.log(JSON.stringify({ ok: false, executor: 'codex', taskId, phaseId: current.phaseId, exitCode, error: result.error ? result.error.message : null }, null, 2));
|
|
2534
|
+
process.exit(exitCode || 1);
|
|
2535
|
+
}
|
|
2536
|
+
const completed = state.phases.find((phase) => phase.phaseId === current.phaseId && phase.status === 'completed');
|
|
2537
|
+
if (!completed) {
|
|
2538
|
+
console.log(JSON.stringify({
|
|
2539
|
+
ok: false,
|
|
2540
|
+
executor: 'codex',
|
|
2541
|
+
taskId,
|
|
2542
|
+
phaseId: current.phaseId,
|
|
2543
|
+
error: 'Codex exited without completing the active phase via aria task complete.',
|
|
2544
|
+
statePath: taskPath(taskId),
|
|
2545
|
+
eventsPath: eventPath(taskId),
|
|
2546
|
+
}, null, 2));
|
|
2547
|
+
process.exit(1);
|
|
2548
|
+
}
|
|
2549
|
+
completedPhases.push(current.phaseId);
|
|
2550
|
+
const allComplete = state.phases.length > 0 && state.phases.every((phase) => phase.status === 'completed');
|
|
2551
|
+
if (allComplete) {
|
|
2552
|
+
state = saveTask({ ...state, status: 'completed', activePhaseId: null }, { type: 'task_completed', executor: 'codex', completedPhases });
|
|
2553
|
+
state = await consumeTaskPhaseBoundary(state, 'codex_executor_task_completed', null, {
|
|
2554
|
+
step: 'codex-executor-task-completed',
|
|
2555
|
+
summary: 'Codex executor completed all task phases',
|
|
2556
|
+
evidence: `completedPhases=${completedPhases.length}`,
|
|
2557
|
+
action: 'close-task',
|
|
2558
|
+
});
|
|
2559
|
+
await recordRuntimeLedger(state, 'task_completed', { executor: 'codex', completedPhases }, { executor: 'codex' });
|
|
2560
|
+
console.log(JSON.stringify({ ok: true, executor: 'codex', taskId, status: state.status, completedPhases, statePath: taskPath(taskId), eventsPath: eventPath(taskId) }, null, 2));
|
|
2561
|
+
return;
|
|
2562
|
+
}
|
|
2563
|
+
if (!runAll) {
|
|
2564
|
+
console.log(JSON.stringify({ ok: true, executor: 'codex', taskId, status: state.status, completedPhases, next: `aria task run ${taskId} --executor codex --summary "..." --evidence "..."` }, null, 2));
|
|
2565
|
+
return;
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
async function runWorkerExecutorTask(taskId, flags, summary, evidence) {
|
|
2570
|
+
const executor = sanitizeTaskId(flagString(flags, 'executor') || 'spark');
|
|
2571
|
+
const allowedFiles = flagList(flags, 'allowed-files');
|
|
2572
|
+
const forbiddenFiles = flagList(flags, 'forbidden-files');
|
|
2573
|
+
const verificationCommand = flagString(flags, 'verify');
|
|
2574
|
+
const requestedPhaseId = flagString(flags, 'phase');
|
|
2575
|
+
if (!allowedFiles.length)
|
|
2576
|
+
throw new Error(`aria task run --executor ${executor} requires --allowed-files "path[,path]"`);
|
|
2577
|
+
if (!verificationCommand)
|
|
2578
|
+
throw new Error(`aria task run --executor ${executor} requires --verify "real verification command"`);
|
|
2579
|
+
const prepared = await prepareWorkerPacket({
|
|
2580
|
+
taskId,
|
|
2581
|
+
executor,
|
|
2582
|
+
requestedPhaseId,
|
|
2583
|
+
allowedFiles,
|
|
2584
|
+
forbiddenFiles,
|
|
2585
|
+
verificationCommand,
|
|
2586
|
+
outputPath: flagString(flags, 'packet-out') || flagString(flags, 'out'),
|
|
2587
|
+
});
|
|
2588
|
+
const dryRun = flags['dry-run'] === true;
|
|
2589
|
+
const dispatchCommand = flagString(flags, 'dispatch-command') || process.env.ARIA_TASK_WORKER_DISPATCH_COMMAND || '';
|
|
2590
|
+
const workerOut = path.resolve(flagString(flags, 'worker-output') || workerOutputPath(prepared.state.taskId, prepared.phase.phaseId, executor));
|
|
2591
|
+
if (dryRun || !dispatchCommand) {
|
|
2592
|
+
console.log(JSON.stringify({
|
|
2593
|
+
ok: true,
|
|
2594
|
+
executor,
|
|
2595
|
+
dispatchPrepared: true,
|
|
2596
|
+
dispatched: false,
|
|
2597
|
+
dryRun,
|
|
2598
|
+
taskId: prepared.state.taskId,
|
|
2599
|
+
phaseId: prepared.phase.phaseId,
|
|
2600
|
+
packetPath: prepared.packetPath,
|
|
2601
|
+
packetHash: prepared.packet.receiptHash,
|
|
2602
|
+
workerOutputPath: workerOut,
|
|
2603
|
+
summary,
|
|
2604
|
+
evidence,
|
|
2605
|
+
next: dispatchCommand
|
|
2606
|
+
? `rerun without --dry-run or run aria task worker-ingest ${prepared.state.taskId} --file ${shellQuote(workerOut)} --packet ${shellQuote(prepared.packetPath)}`
|
|
2607
|
+
: `send packet to ${executor}; then run aria task worker-ingest ${prepared.state.taskId} --file <worker-output.json> --packet ${shellQuote(prepared.packetPath)}`,
|
|
2608
|
+
}, null, 2));
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
const dispatch = spawnSync('/bin/bash', ['-lc', dispatchCommand], {
|
|
2612
|
+
cwd: prepared.state.cwd,
|
|
2613
|
+
input: JSON.stringify(prepared.packet, null, 2),
|
|
2614
|
+
encoding: 'utf8',
|
|
2615
|
+
env: {
|
|
2616
|
+
...process.env,
|
|
2617
|
+
ARIA_RUNTIME_URL: RUNTIME_URL,
|
|
2618
|
+
ARIA_TASK_ID: prepared.state.taskId,
|
|
2619
|
+
ARIA_TASK_PHASE_ID: prepared.phase.phaseId,
|
|
2620
|
+
ARIA_TASK_WORKER_EXECUTOR: executor,
|
|
2621
|
+
ARIA_TASK_WORKER_PACKET_PATH: prepared.packetPath,
|
|
2622
|
+
ARIA_TASK_WORKER_OUTPUT_PATH: workerOut,
|
|
2623
|
+
},
|
|
2624
|
+
});
|
|
2625
|
+
const exitCode = typeof dispatch.status === 'number' ? dispatch.status : 1;
|
|
2626
|
+
let state = loadTask(prepared.state.taskId);
|
|
2627
|
+
const dispatchReceipt = {
|
|
2628
|
+
at: nowIso(),
|
|
2629
|
+
phase: prepared.phase.phaseId,
|
|
2630
|
+
receipt: 'worker-dispatch',
|
|
2631
|
+
executor,
|
|
2632
|
+
dispatchCommand,
|
|
2633
|
+
packetPath: prepared.packetPath,
|
|
2634
|
+
workerOutputPath: workerOut,
|
|
2635
|
+
exitCode,
|
|
2636
|
+
signal: dispatch.signal || null,
|
|
2637
|
+
error: dispatch.error ? dispatch.error.message : null,
|
|
2638
|
+
stdoutSha256: sha256(String(dispatch.stdout || '')),
|
|
2639
|
+
stderrTail: String(dispatch.stderr || '').slice(-4000),
|
|
2640
|
+
};
|
|
2641
|
+
state = saveTask({ ...state, checkpoints: [...state.checkpoints, dispatchReceipt] }, {
|
|
2642
|
+
type: exitCode === 0 && !dispatch.error ? 'worker_dispatch_exit' : 'worker_dispatch_failed',
|
|
2643
|
+
phaseId: prepared.phase.phaseId,
|
|
2644
|
+
executor,
|
|
2645
|
+
dispatchReceipt,
|
|
2646
|
+
});
|
|
2647
|
+
state = await consumeTaskPhaseBoundary(state, 'worker_dispatch_exit', phaseById(state, prepared.phase.phaseId) || prepared.phase, {
|
|
2648
|
+
step: 'bounded-worker-command-dispatch',
|
|
2649
|
+
summary: exitCode === 0 && !dispatch.error ? `Dispatched ${executor} worker command` : `${executor} worker command failed`,
|
|
2650
|
+
evidence: `exitCode=${exitCode}; workerOutputPath=${workerOut}`,
|
|
2651
|
+
gaps: exitCode === 0 && !dispatch.error ? [] : [`worker dispatch exitCode=${exitCode}`],
|
|
2652
|
+
action: exitCode === 0 && !dispatch.error ? 'ingest-worker-output' : 'correct-worker-dispatch-before-ingest',
|
|
2653
|
+
});
|
|
2654
|
+
await recordRuntimeLedger(state, exitCode === 0 && !dispatch.error ? 'worker_dispatch_exit' : 'worker_dispatch_failed', {
|
|
2655
|
+
executor,
|
|
2656
|
+
phase: phaseById(state, prepared.phase.phaseId) || prepared.phase,
|
|
2657
|
+
dispatchReceipt,
|
|
2658
|
+
}, {
|
|
2659
|
+
gaps: exitCode === 0 && !dispatch.error ? [] : [`worker dispatch exitCode=${exitCode}`],
|
|
2660
|
+
workerDispatchReceipt: dispatchReceipt,
|
|
2661
|
+
});
|
|
2662
|
+
if (exitCode !== 0 || dispatch.error) {
|
|
2663
|
+
console.log(JSON.stringify({
|
|
2664
|
+
ok: false,
|
|
2665
|
+
executor,
|
|
2666
|
+
taskId: prepared.state.taskId,
|
|
2667
|
+
phaseId: prepared.phase.phaseId,
|
|
2668
|
+
packetPath: prepared.packetPath,
|
|
2669
|
+
workerOutputPath: workerOut,
|
|
2670
|
+
exitCode,
|
|
2671
|
+
error: dispatch.error ? dispatch.error.message : null,
|
|
2672
|
+
}, null, 2));
|
|
2673
|
+
process.exit(exitCode || 1);
|
|
2674
|
+
}
|
|
2675
|
+
if (String(dispatch.stdout || '').trim()) {
|
|
2676
|
+
writeFileSync(workerOut, String(dispatch.stdout).trim() + '\n', { mode: 0o600 });
|
|
2677
|
+
}
|
|
2678
|
+
if (!existsSync(workerOut)) {
|
|
2679
|
+
throw new Error(`Worker dispatch exited 0 but did not write output JSON to ${workerOut}`);
|
|
2680
|
+
}
|
|
2681
|
+
await workerIngestTask([
|
|
2682
|
+
prepared.state.taskId,
|
|
2683
|
+
'--file',
|
|
2684
|
+
workerOut,
|
|
2685
|
+
'--packet',
|
|
2686
|
+
prepared.packetPath,
|
|
2687
|
+
'--executor',
|
|
2688
|
+
executor,
|
|
2689
|
+
'--phase',
|
|
2690
|
+
prepared.phase.phaseId,
|
|
2691
|
+
]);
|
|
2692
|
+
}
|
|
2693
|
+
async function runTask(args) {
|
|
2694
|
+
const { flags, rest } = parseFlags(args);
|
|
2695
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
2696
|
+
const summary = flagString(flags, 'summary') || rest.slice(1).join(' ').trim();
|
|
2697
|
+
const evidence = flagString(flags, 'evidence');
|
|
2698
|
+
const runAll = flags.all === true;
|
|
2699
|
+
const maxRecoveries = Math.max(0, Number(flagString(flags, 'max-recoveries') || '2'));
|
|
2700
|
+
if (!summary)
|
|
2701
|
+
throw new Error('aria task run requires --summary "..."');
|
|
2702
|
+
if (!evidence)
|
|
2703
|
+
throw new Error('aria task run requires --evidence "..."');
|
|
2704
|
+
if (flagString(flags, 'executor') === 'codex') {
|
|
2705
|
+
return runCodexExecutorTask(taskId, flags, summary, evidence);
|
|
2706
|
+
}
|
|
2707
|
+
if (flagString(flags, 'executor')) {
|
|
2708
|
+
return runWorkerExecutorTask(taskId, flags, summary, evidence);
|
|
2709
|
+
}
|
|
2710
|
+
let state = loadTask(taskId);
|
|
2711
|
+
const completedPhases = [];
|
|
2712
|
+
let recoveryAttempts = 0;
|
|
2713
|
+
while (true) {
|
|
2714
|
+
const forcedSkillLoad = await forceSkillPack(state.taskId, state.goal);
|
|
2715
|
+
state = saveTask({ ...state, forcedSkillLoad, status: 'active' }, {
|
|
2716
|
+
type: 'run_loop_step',
|
|
2717
|
+
step: RUN_LOOP_STEPS[0],
|
|
2718
|
+
forcedSkillLoad,
|
|
2719
|
+
});
|
|
2720
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_forced_skill_refire', activePhase(state), {
|
|
2721
|
+
step: RUN_LOOP_STEPS[0],
|
|
2722
|
+
summary: 'parent task loop refreshed universal packet before phase work',
|
|
2723
|
+
evidence: `forcedSkillLoad.loadedCount=${forcedSkillLoad.loadedCount}; activeRuntimeCount=${forcedSkillLoad.activeRuntimeCount}`,
|
|
2724
|
+
action: 'claim-or-resume-phase',
|
|
2725
|
+
});
|
|
2726
|
+
await recordRuntimeLedger(state, 'run_loop_forced_skill_refire', {
|
|
2727
|
+
step: RUN_LOOP_STEPS[0],
|
|
2728
|
+
completedPhases,
|
|
2729
|
+
}, { forcedSkillLoad, runLoopSteps: RUN_LOOP_STEPS });
|
|
2730
|
+
let current = activePhase(state);
|
|
2731
|
+
if (!current || current.status !== 'in_progress') {
|
|
2732
|
+
const pending = current && (current.status === 'qa_failed' || current.status === 'blocked') ? current : nextPendingPhase(state);
|
|
2733
|
+
if (!pending) {
|
|
2734
|
+
const allComplete = state.phases.length > 0 && state.phases.every((phase) => phase.status === 'completed');
|
|
2735
|
+
state = saveTask({ ...state, status: allComplete ? 'completed' : state.status, activePhaseId: null }, {
|
|
2736
|
+
type: allComplete ? 'task_completed' : 'run_loop_no_phase',
|
|
2737
|
+
step: RUN_LOOP_STEPS[6],
|
|
2738
|
+
completedPhases,
|
|
2739
|
+
});
|
|
2740
|
+
state = await consumeTaskPhaseBoundary(state, allComplete ? 'run_loop_task_completed' : 'run_loop_no_phase', null, {
|
|
2741
|
+
step: RUN_LOOP_STEPS[6],
|
|
2742
|
+
summary: allComplete ? 'parent loop observed all phases complete' : 'parent loop found no runnable phase',
|
|
2743
|
+
evidence: `completedPhases=${completedPhases.length}; phaseCount=${state.phases.length}`,
|
|
2744
|
+
action: allComplete ? 'close-task' : 'report-no-phase',
|
|
2745
|
+
});
|
|
2746
|
+
await recordRuntimeLedger(state, allComplete ? 'task_completed' : 'run_loop_no_phase', {
|
|
2747
|
+
step: RUN_LOOP_STEPS[6],
|
|
2748
|
+
completedPhases,
|
|
2749
|
+
}, { runLoopSteps: RUN_LOOP_STEPS });
|
|
2750
|
+
console.log(JSON.stringify({ ok: allComplete, taskId, status: state.status, completedPhases, statePath: taskPath(taskId), eventsPath: eventPath(taskId) }, null, 2));
|
|
2751
|
+
return;
|
|
2752
|
+
}
|
|
2753
|
+
const startedAt = nowIso();
|
|
2754
|
+
const phases = state.phases.map((phase) => phase.phaseId === pending.phaseId
|
|
2755
|
+
? { ...phase, status: 'in_progress', startedAt: phase.startedAt || startedAt, attempts: phase.attempts + 1 }
|
|
2756
|
+
: phase);
|
|
2757
|
+
state = saveTask({ ...state, activePhaseId: pending.phaseId, phases }, {
|
|
2758
|
+
type: 'run_loop_step',
|
|
2759
|
+
step: RUN_LOOP_STEPS[1],
|
|
2760
|
+
phaseId: pending.phaseId,
|
|
2761
|
+
});
|
|
2762
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_phase_claim', activePhase(state) || pending, {
|
|
2763
|
+
step: RUN_LOOP_STEPS[1],
|
|
2764
|
+
summary: 'parent loop claimed phase after universal packet refresh',
|
|
2765
|
+
evidence: `phase=${pending.phaseId}`,
|
|
2766
|
+
action: 'write-pre-phase-receipt',
|
|
2767
|
+
});
|
|
2768
|
+
await recordRuntimeLedger(state, 'run_loop_phase_claim', {
|
|
2769
|
+
step: RUN_LOOP_STEPS[1],
|
|
2770
|
+
phase: activePhase(state),
|
|
2771
|
+
}, { forcedSkillLoad, phase: activePhase(state) || pending });
|
|
2772
|
+
current = activePhase(state);
|
|
2773
|
+
}
|
|
2774
|
+
if (!current)
|
|
2775
|
+
throw new Error('aria task run could not claim or resume a phase.');
|
|
2776
|
+
const preReceipt = {
|
|
2777
|
+
taskId: state.taskId,
|
|
2778
|
+
phaseId: current.phaseId,
|
|
2779
|
+
step: RUN_LOOP_STEPS[2],
|
|
2780
|
+
summary,
|
|
2781
|
+
evidence,
|
|
2782
|
+
};
|
|
2783
|
+
state = saveTask({ ...state, checkpoints: [...state.checkpoints, { at: nowIso(), phase: current.phaseId, receipt: 'pre-phase', summary, evidence }] }, {
|
|
2784
|
+
type: 'run_loop_step',
|
|
2785
|
+
step: RUN_LOOP_STEPS[2],
|
|
2786
|
+
phaseId: current.phaseId,
|
|
2787
|
+
});
|
|
2788
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_pre_phase_receipt', current, {
|
|
2789
|
+
step: RUN_LOOP_STEPS[2],
|
|
2790
|
+
summary,
|
|
2791
|
+
evidence,
|
|
2792
|
+
action: 'run-mid-phase-check',
|
|
2793
|
+
});
|
|
2794
|
+
await recordRuntimeLedger(state, 'run_loop_pre_phase_receipt', preReceipt, { phase: current, runLoopSteps: RUN_LOOP_STEPS });
|
|
2795
|
+
const midReceipt = {
|
|
2796
|
+
taskId: state.taskId,
|
|
2797
|
+
phaseId: current.phaseId,
|
|
2798
|
+
step: RUN_LOOP_STEPS[3],
|
|
2799
|
+
summary,
|
|
2800
|
+
evidence,
|
|
2801
|
+
activeSkillCount: state.requiredSkills.length,
|
|
2802
|
+
};
|
|
2803
|
+
state = saveTask({ ...state, checkpoints: [...state.checkpoints, { at: nowIso(), phase: current.phaseId, receipt: 'mid-phase', summary, evidence }] }, {
|
|
2804
|
+
type: 'run_loop_step',
|
|
2805
|
+
step: RUN_LOOP_STEPS[3],
|
|
2806
|
+
phaseId: current.phaseId,
|
|
2807
|
+
});
|
|
2808
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_mid_phase_receipt', current, {
|
|
2809
|
+
step: RUN_LOOP_STEPS[3],
|
|
2810
|
+
summary,
|
|
2811
|
+
evidence,
|
|
2812
|
+
action: 'run-qiyas-tadabbur-qa',
|
|
2813
|
+
});
|
|
2814
|
+
await recordRuntimeLedger(state, 'run_loop_mid_phase_receipt', midReceipt, { phase: current, forcedSkillLoad: state.forcedSkillLoad });
|
|
2815
|
+
const qaArtifact = readRunQaArtifact(flags, state, current, summary, evidence, current.attempts);
|
|
2816
|
+
const gaps = methodGaps(qaArtifact.text);
|
|
2817
|
+
const qa = { at: nowIso(), ok: gaps.length === 0, gaps, artifactSha256: sha256(qaArtifact.text) };
|
|
2818
|
+
if (gaps.length) {
|
|
2819
|
+
const failedPhases = state.phases.map((phase) => phase.phaseId === current.phaseId
|
|
2820
|
+
? { ...phase, status: 'qa_failed', summary, evidence, qa }
|
|
2821
|
+
: phase);
|
|
2822
|
+
state = saveTask({ ...state, status: 'blocked', activePhaseId: current.phaseId, phases: failedPhases }, {
|
|
2823
|
+
type: 'run_loop_qa_failed',
|
|
2824
|
+
step: RUN_LOOP_STEPS[4],
|
|
2825
|
+
phaseId: current.phaseId,
|
|
2826
|
+
gaps,
|
|
2827
|
+
qaSource: qaArtifact.source,
|
|
2828
|
+
});
|
|
2829
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_phase_qa_failed', current, {
|
|
2830
|
+
step: RUN_LOOP_STEPS[4],
|
|
2831
|
+
summary,
|
|
2832
|
+
evidence,
|
|
2833
|
+
qa,
|
|
2834
|
+
gaps,
|
|
2835
|
+
action: 'run-correction-recovery-cycle',
|
|
2836
|
+
});
|
|
2837
|
+
await recordRuntimeLedger(state, 'run_loop_phase_qa_failed', {
|
|
2838
|
+
step: RUN_LOOP_STEPS[4],
|
|
2839
|
+
phase: current,
|
|
2840
|
+
gaps,
|
|
2841
|
+
qaSource: qaArtifact.source,
|
|
2842
|
+
}, { gaps, qa });
|
|
2843
|
+
if (recoveryAttempts >= maxRecoveries || (!flagString(flags, 'fix-qa-file') && flags['auto-qa'] !== true)) {
|
|
2844
|
+
console.log(JSON.stringify({
|
|
2845
|
+
ok: false,
|
|
2846
|
+
taskId,
|
|
2847
|
+
phaseId: current.phaseId,
|
|
2848
|
+
gaps,
|
|
2849
|
+
recoveryAttempts,
|
|
2850
|
+
next: 'provide --fix-qa-file, raise --max-recoveries, or run aria task recover',
|
|
2851
|
+
}, null, 2));
|
|
2852
|
+
process.exit(1);
|
|
2853
|
+
}
|
|
2854
|
+
recoveryAttempts += 1;
|
|
2855
|
+
const lastAt = nowIso();
|
|
2856
|
+
const recoveredPhases = state.phases.map((phase) => phase.phaseId === current.phaseId
|
|
2857
|
+
? {
|
|
2858
|
+
...phase,
|
|
2859
|
+
status: 'in_progress',
|
|
2860
|
+
startedAt: phase.startedAt || lastAt,
|
|
2861
|
+
attempts: phase.attempts + 1,
|
|
2862
|
+
recovery: {
|
|
2863
|
+
attempts: (phase.recovery?.attempts || 0) + 1,
|
|
2864
|
+
lastAt,
|
|
2865
|
+
reason: `run loop QA gaps: ${gaps.slice(0, 5).join('; ')}`,
|
|
2866
|
+
},
|
|
2867
|
+
}
|
|
2868
|
+
: phase);
|
|
2869
|
+
state = saveTask({
|
|
2870
|
+
...state,
|
|
2871
|
+
status: 'active',
|
|
2872
|
+
activePhaseId: current.phaseId,
|
|
2873
|
+
phases: recoveredPhases,
|
|
2874
|
+
recovery: {
|
|
2875
|
+
attempts: state.recovery.attempts + 1,
|
|
2876
|
+
lastReason: `run loop QA gaps: ${gaps.slice(0, 5).join('; ')}`,
|
|
2877
|
+
lastAt,
|
|
2878
|
+
},
|
|
2879
|
+
}, {
|
|
2880
|
+
type: 'run_loop_recovery',
|
|
2881
|
+
step: RUN_LOOP_STEPS[5],
|
|
2882
|
+
phaseId: current.phaseId,
|
|
2883
|
+
gaps,
|
|
2884
|
+
recoveryAttempts,
|
|
2885
|
+
});
|
|
2886
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_recovery_cycle', activePhase(state), {
|
|
2887
|
+
step: RUN_LOOP_STEPS[5],
|
|
2888
|
+
summary: 'parent loop applied QA recovery cycle before retrying phase',
|
|
2889
|
+
evidence: `recoveryAttempts=${recoveryAttempts}; gaps=${gaps.length}`,
|
|
2890
|
+
qa,
|
|
2891
|
+
gaps,
|
|
2892
|
+
action: 'retry-phase-with-correction',
|
|
2893
|
+
});
|
|
2894
|
+
await recordRuntimeLedger(state, 'run_loop_recovery_cycle', {
|
|
2895
|
+
step: RUN_LOOP_STEPS[5],
|
|
2896
|
+
phase: activePhase(state),
|
|
2897
|
+
gaps,
|
|
2898
|
+
recoveryAttempts,
|
|
2899
|
+
}, { gaps, runLoopSteps: RUN_LOOP_STEPS });
|
|
2900
|
+
continue;
|
|
2901
|
+
}
|
|
2902
|
+
const completedAt = nowIso();
|
|
2903
|
+
const completed = state.phases.map((phase) => phase.phaseId === current.phaseId
|
|
2904
|
+
? {
|
|
2905
|
+
...phase,
|
|
2906
|
+
status: 'completed',
|
|
2907
|
+
completedAt,
|
|
2908
|
+
summary,
|
|
2909
|
+
evidence,
|
|
2910
|
+
qa,
|
|
2911
|
+
}
|
|
2912
|
+
: phase);
|
|
2913
|
+
completedPhases.push(current.phaseId);
|
|
2914
|
+
state = saveTask({
|
|
2915
|
+
...state,
|
|
2916
|
+
status: 'active',
|
|
2917
|
+
activePhaseId: null,
|
|
2918
|
+
phases: completed,
|
|
2919
|
+
checkpoints: [...state.checkpoints, {
|
|
2920
|
+
at: completedAt,
|
|
2921
|
+
phase: current.phaseId,
|
|
2922
|
+
receipt: 'post-phase',
|
|
2923
|
+
summary,
|
|
2924
|
+
evidence,
|
|
2925
|
+
qa,
|
|
2926
|
+
}],
|
|
2927
|
+
}, {
|
|
2928
|
+
type: 'run_loop_phase_complete',
|
|
2929
|
+
step: RUN_LOOP_STEPS[6],
|
|
2930
|
+
phaseId: current.phaseId,
|
|
2931
|
+
summary,
|
|
2932
|
+
evidence,
|
|
2933
|
+
qa,
|
|
2934
|
+
qaSource: qaArtifact.source,
|
|
2935
|
+
});
|
|
2936
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_phase_complete', completed.find((phase) => phase.phaseId === current.phaseId) || current, {
|
|
2937
|
+
step: RUN_LOOP_STEPS[6],
|
|
2938
|
+
summary,
|
|
2939
|
+
evidence,
|
|
2940
|
+
qa,
|
|
2941
|
+
action: 'advance-or-close-task',
|
|
2942
|
+
});
|
|
2943
|
+
await recordRuntimeLedger(state, 'run_loop_phase_complete', {
|
|
2944
|
+
step: RUN_LOOP_STEPS[6],
|
|
2945
|
+
phase: completed.find((phase) => phase.phaseId === current.phaseId),
|
|
2946
|
+
qa,
|
|
2947
|
+
qaSource: qaArtifact.source,
|
|
2948
|
+
}, { qa, runLoopSteps: RUN_LOOP_STEPS });
|
|
2949
|
+
const allComplete = state.phases.length > 0 && state.phases.every((phase) => phase.status === 'completed');
|
|
2950
|
+
if (allComplete) {
|
|
2951
|
+
state = saveTask({ ...state, status: 'completed', activePhaseId: null }, {
|
|
2952
|
+
type: 'task_completed',
|
|
2953
|
+
step: RUN_LOOP_STEPS[6],
|
|
2954
|
+
completedPhases,
|
|
2955
|
+
});
|
|
2956
|
+
state = await consumeTaskPhaseBoundary(state, 'run_loop_task_completed', null, {
|
|
2957
|
+
step: RUN_LOOP_STEPS[6],
|
|
2958
|
+
summary: 'parent loop completed every phase with task phase consumer receipts',
|
|
2959
|
+
evidence: `completedPhases=${completedPhases.length}`,
|
|
2960
|
+
action: 'close-task',
|
|
2961
|
+
});
|
|
2962
|
+
await recordRuntimeLedger(state, 'task_completed', {
|
|
2963
|
+
step: RUN_LOOP_STEPS[6],
|
|
2964
|
+
completedPhases,
|
|
2965
|
+
}, { runLoopSteps: RUN_LOOP_STEPS });
|
|
2966
|
+
console.log(JSON.stringify({ ok: true, taskId, status: state.status, completedPhases, recoveryAttempts, statePath: taskPath(taskId), eventsPath: eventPath(taskId) }, null, 2));
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
if (!runAll) {
|
|
2970
|
+
console.log(JSON.stringify({ ok: true, taskId, status: state.status, completedPhases, recoveryAttempts, next: `aria task run ${taskId} --summary "..." --evidence "..." --auto-qa` }, null, 2));
|
|
2971
|
+
return;
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
async function recoverTask(args) {
|
|
2976
|
+
const { flags, rest } = parseFlags(args);
|
|
2977
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
2978
|
+
const reason = flagString(flags, 'reason') || rest.slice(1).join(' ').trim() || 'blocked phase recovery';
|
|
2979
|
+
let state = loadTask(taskId);
|
|
2980
|
+
const phase = activePhase(state) || state.phases.find((item) => item.status === 'qa_failed' || item.status === 'blocked') || nextPendingPhase(state);
|
|
2981
|
+
if (!phase)
|
|
2982
|
+
throw new Error('No phase available for recovery.');
|
|
2983
|
+
const forcedSkillLoad = await forceSkillPack(state.taskId, state.goal);
|
|
2984
|
+
state = attachCompiledWorkUnit({ ...state, forcedSkillLoad }, forcedSkillLoad);
|
|
2985
|
+
const lastAt = nowIso();
|
|
2986
|
+
const phases = state.phases.map((item) => item.phaseId === phase.phaseId
|
|
2987
|
+
? {
|
|
2988
|
+
...item,
|
|
2989
|
+
status: 'in_progress',
|
|
2990
|
+
startedAt: item.startedAt || lastAt,
|
|
2991
|
+
attempts: item.attempts + 1,
|
|
2992
|
+
recovery: {
|
|
2993
|
+
attempts: (item.recovery?.attempts || 0) + 1,
|
|
2994
|
+
lastAt,
|
|
2995
|
+
reason,
|
|
2996
|
+
},
|
|
2997
|
+
}
|
|
2998
|
+
: item);
|
|
2999
|
+
state = saveTask({
|
|
3000
|
+
...state,
|
|
3001
|
+
status: 'active',
|
|
3002
|
+
activePhaseId: phase.phaseId,
|
|
3003
|
+
forcedSkillLoad,
|
|
3004
|
+
recovery: {
|
|
3005
|
+
attempts: state.recovery.attempts + 1,
|
|
3006
|
+
lastReason: reason,
|
|
3007
|
+
lastAt,
|
|
3008
|
+
},
|
|
3009
|
+
phases,
|
|
3010
|
+
}, { type: 'phase_recovery', phaseId: phase.phaseId, reason, forcedSkillLoad });
|
|
3011
|
+
await publishRecoveryContext(state, reason);
|
|
3012
|
+
const refreshedState = await refreshTaskProjectContext(state);
|
|
3013
|
+
state = saveTask(refreshedState, { type: 'project_context_refresh', projectContext: refreshedState.projectContext, reason });
|
|
3014
|
+
state = await consumeTaskPhaseBoundary(state, 'phase_recovery', activePhase(state), {
|
|
3015
|
+
summary: 'phase recovery refreshed universal packet and reopened phase',
|
|
3016
|
+
evidence: reason,
|
|
3017
|
+
action: 'resume-corrective-work',
|
|
3018
|
+
});
|
|
3019
|
+
await recordRuntimeLedger(state, 'phase_recovery', { phase: activePhase(state), reason }, { forcedSkillLoad, reason });
|
|
3020
|
+
console.log(renderReinjection(state));
|
|
3021
|
+
}
|
|
3022
|
+
async function checkpointTask(args) {
|
|
3023
|
+
const { flags, rest } = parseFlags(args);
|
|
3024
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
3025
|
+
const state = loadTask(taskId);
|
|
3026
|
+
const checkpoint = {
|
|
3027
|
+
at: nowIso(),
|
|
3028
|
+
phase: flagString(flags, 'phase') || 'checkpoint',
|
|
3029
|
+
summary: flagString(flags, 'summary') || rest.slice(1).join(' ').trim(),
|
|
3030
|
+
evidence: flagString(flags, 'evidence'),
|
|
3031
|
+
};
|
|
3032
|
+
if (!checkpoint.summary)
|
|
3033
|
+
throw new Error('aria task checkpoint requires --summary "..."');
|
|
3034
|
+
let next = saveTask({ ...state, checkpoints: [...state.checkpoints, checkpoint] }, { type: 'checkpoint', checkpoint });
|
|
3035
|
+
next = await consumeTaskPhaseBoundary(next, 'checkpoint', activePhase(next), {
|
|
3036
|
+
step: 'task-checkpoint',
|
|
3037
|
+
summary: checkpoint.summary,
|
|
3038
|
+
evidence: checkpoint.evidence,
|
|
3039
|
+
action: 'persist-progress-evidence',
|
|
3040
|
+
});
|
|
3041
|
+
await recordRuntimeLedger(next, checkpoint.phase, checkpoint, { checkpoint });
|
|
3042
|
+
console.log(JSON.stringify({ ok: true, taskId: next.taskId, checkpoint, statePath: taskPath(next.taskId) }, null, 2));
|
|
3043
|
+
}
|
|
3044
|
+
async function prepareWorkerPacket({ taskId, executor, requestedPhaseId, allowedFiles, forbiddenFiles, verificationCommand, outputPath, }) {
|
|
3045
|
+
let state = loadTask(taskId);
|
|
3046
|
+
const forcedSkillLoad = await forceSkillPack(state.taskId, state.goal);
|
|
3047
|
+
const selected = selectableWorkerPhase(state, requestedPhaseId);
|
|
3048
|
+
if (!selected)
|
|
3049
|
+
throw new Error('No active or pending phase available for worker packet.');
|
|
3050
|
+
if (selected.status === 'completed')
|
|
3051
|
+
throw new Error(`Refusing worker packet for completed phase ${selected.phaseId}.`);
|
|
3052
|
+
const startedAt = nowIso();
|
|
3053
|
+
const phases = state.phases.map((phase) => phase.phaseId === selected.phaseId
|
|
3054
|
+
? {
|
|
3055
|
+
...phase,
|
|
3056
|
+
status: 'in_progress',
|
|
3057
|
+
startedAt: phase.startedAt || startedAt,
|
|
3058
|
+
attempts: phase.status === 'in_progress' ? phase.attempts : phase.attempts + 1,
|
|
3059
|
+
}
|
|
3060
|
+
: phase);
|
|
3061
|
+
state = saveTask({
|
|
3062
|
+
...state,
|
|
3063
|
+
status: 'active',
|
|
3064
|
+
activePhaseId: selected.phaseId,
|
|
3065
|
+
forcedSkillLoad,
|
|
3066
|
+
phases,
|
|
3067
|
+
}, {
|
|
3068
|
+
type: 'worker_packet_prepare',
|
|
3069
|
+
executor,
|
|
3070
|
+
phaseId: selected.phaseId,
|
|
3071
|
+
forcedSkillLoad,
|
|
3072
|
+
});
|
|
3073
|
+
const phase = activePhase(state) || selected;
|
|
3074
|
+
const substrateOpen = await openTaskSubstrate(state, 'worker_packet_prepared', phase.phaseId);
|
|
3075
|
+
const hiveRuntimeReport = await publishWorkerHiveContext(state, phase, 'aria_task_worker_packet_prepared', {
|
|
3076
|
+
worker_executor: executor,
|
|
3077
|
+
worker_phase_id: phase.phaseId,
|
|
3078
|
+
allowed_files: normalizeClaimList(state.cwd, allowedFiles),
|
|
3079
|
+
forbidden_files: normalizeClaimList(state.cwd, forbiddenFiles),
|
|
3080
|
+
verification_command: verificationCommand,
|
|
3081
|
+
substrate_open: compactSubstrateOpen(substrateOpen),
|
|
3082
|
+
});
|
|
3083
|
+
const packetBase = {
|
|
3084
|
+
schema: 'aria.task_worker_packet.v1',
|
|
3085
|
+
generatedAt: nowIso(),
|
|
3086
|
+
taskId: state.taskId,
|
|
3087
|
+
phaseId: phase.phaseId,
|
|
3088
|
+
executor,
|
|
3089
|
+
goal: state.goal,
|
|
3090
|
+
phaseTitle: phase.title,
|
|
3091
|
+
phaseStatus: phase.status,
|
|
3092
|
+
cwd: state.cwd,
|
|
3093
|
+
allowedFiles: normalizeClaimList(state.cwd, allowedFiles),
|
|
3094
|
+
forbiddenFiles: normalizeClaimList(state.cwd, forbiddenFiles),
|
|
3095
|
+
verificationCommand,
|
|
3096
|
+
atlasSubstrate: compactSubstrateOpen(substrateOpen),
|
|
3097
|
+
hiveRuntimeReport,
|
|
3098
|
+
qualityContract: {
|
|
3099
|
+
workerMay: [
|
|
3100
|
+
'perform bounded implementation inside allowedFiles',
|
|
3101
|
+
'return changedFiles, evidence, verification summary, and blockers',
|
|
3102
|
+
],
|
|
3103
|
+
workerMustNot: [
|
|
3104
|
+
'claim task or phase completion',
|
|
3105
|
+
'touch forbiddenFiles',
|
|
3106
|
+
'expand scope without a new worker packet',
|
|
3107
|
+
'weaken verification or gate contracts',
|
|
3108
|
+
],
|
|
3109
|
+
completionAuthority: 'aria_codex_forced_qa_only',
|
|
3110
|
+
maxCorrectionLoopsBeforeEscalation: 1,
|
|
3111
|
+
},
|
|
3112
|
+
requiredReturnSchema: {
|
|
3113
|
+
schema: 'aria.task_worker_output.v1',
|
|
3114
|
+
taskId: state.taskId,
|
|
3115
|
+
phaseId: phase.phaseId,
|
|
3116
|
+
executor,
|
|
3117
|
+
changedFiles: [],
|
|
3118
|
+
verification: { command: verificationCommand, exitCode: 0, summary: '' },
|
|
3119
|
+
summary: '',
|
|
3120
|
+
evidence: '',
|
|
3121
|
+
blockers: [],
|
|
3122
|
+
},
|
|
3123
|
+
forcedSelectionSummary: summarizeForcedSkillLoad({
|
|
3124
|
+
skillExecutionReceipt: objectRecord(forcedSkillLoad.skillExecutionReceipt),
|
|
3125
|
+
...forcedSkillLoad,
|
|
3126
|
+
}),
|
|
3127
|
+
};
|
|
3128
|
+
const packet = {
|
|
3129
|
+
...packetBase,
|
|
3130
|
+
receiptHash: sha256Json(packetBase),
|
|
3131
|
+
};
|
|
3132
|
+
const packetPath = path.resolve(outputPath || workerPacketPath(state.taskId, phase.phaseId, executor));
|
|
3133
|
+
writeFileSync(packetPath, JSON.stringify(packet, null, 2) + '\n', { mode: 0o600 });
|
|
3134
|
+
const checkpoint = {
|
|
3135
|
+
at: nowIso(),
|
|
3136
|
+
phase: phase.phaseId,
|
|
3137
|
+
receipt: 'worker-packet',
|
|
3138
|
+
executor,
|
|
3139
|
+
packetPath,
|
|
3140
|
+
packetHash: packet.receiptHash,
|
|
3141
|
+
allowedFiles: packet.allowedFiles,
|
|
3142
|
+
forbiddenFiles: packet.forbiddenFiles,
|
|
3143
|
+
verificationCommand,
|
|
3144
|
+
};
|
|
3145
|
+
state = saveTask({ ...state, checkpoints: [...state.checkpoints, checkpoint] }, {
|
|
3146
|
+
type: 'worker_packet_prepared',
|
|
3147
|
+
executor,
|
|
3148
|
+
phaseId: phase.phaseId,
|
|
3149
|
+
packetPath,
|
|
3150
|
+
packetHash: packet.receiptHash,
|
|
3151
|
+
});
|
|
3152
|
+
state = await consumeTaskPhaseBoundary(state, 'worker_packet_prepared', phase, {
|
|
3153
|
+
step: 'bounded-worker-dispatch',
|
|
3154
|
+
summary: `Prepared bounded ${executor} worker packet; Aria/Codex retains completion authority`,
|
|
3155
|
+
evidence: `packetPath=${packetPath}; allowedFiles=${packet.allowedFiles.length}; verificationCommand=${verificationCommand}`,
|
|
3156
|
+
action: 'dispatch-cheap-worker-and-ingest-output',
|
|
3157
|
+
});
|
|
3158
|
+
await recordRuntimeLedger(state, 'worker_packet_prepared', {
|
|
3159
|
+
executor,
|
|
3160
|
+
phase,
|
|
3161
|
+
packetPath,
|
|
3162
|
+
packetHash: packet.receiptHash,
|
|
3163
|
+
summary: 'bounded cheap-worker packet prepared',
|
|
3164
|
+
}, { forcedSkillLoad, phase, packet, substrateOpen, hiveRuntimeReport });
|
|
3165
|
+
return { state, phase, packet, packetPath };
|
|
3166
|
+
}
|
|
3167
|
+
async function workerPacketTask(args) {
|
|
3168
|
+
const { flags, rest } = parseFlags(args);
|
|
3169
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
3170
|
+
const executor = sanitizeTaskId(flagString(flags, 'executor') || 'spark');
|
|
3171
|
+
const requestedPhaseId = flagString(flags, 'phase');
|
|
3172
|
+
const allowedFiles = flagList(flags, 'allowed-files');
|
|
3173
|
+
const forbiddenFiles = flagList(flags, 'forbidden-files');
|
|
3174
|
+
const verificationCommand = flagString(flags, 'verify');
|
|
3175
|
+
if (!allowedFiles.length)
|
|
3176
|
+
throw new Error('aria task worker-packet requires --allowed-files "path[,path]"');
|
|
3177
|
+
if (!verificationCommand)
|
|
3178
|
+
throw new Error('aria task worker-packet requires --verify "real verification command"');
|
|
3179
|
+
const prepared = await prepareWorkerPacket({
|
|
3180
|
+
taskId,
|
|
3181
|
+
executor,
|
|
3182
|
+
requestedPhaseId,
|
|
3183
|
+
allowedFiles,
|
|
3184
|
+
forbiddenFiles,
|
|
3185
|
+
verificationCommand,
|
|
3186
|
+
outputPath: flagString(flags, 'out'),
|
|
3187
|
+
});
|
|
3188
|
+
console.log(JSON.stringify({
|
|
3189
|
+
ok: true,
|
|
3190
|
+
taskId: prepared.state.taskId,
|
|
3191
|
+
phaseId: prepared.phase.phaseId,
|
|
3192
|
+
executor,
|
|
3193
|
+
packetPath: prepared.packetPath,
|
|
3194
|
+
packetHash: prepared.packet.receiptHash,
|
|
3195
|
+
next: `aria task worker-ingest ${prepared.state.taskId} --file <worker-output.json> --packet ${prepared.packetPath}`,
|
|
3196
|
+
}, null, 2));
|
|
3197
|
+
}
|
|
3198
|
+
function runWorkerVerification(state, command) {
|
|
3199
|
+
if (!command) {
|
|
3200
|
+
return {
|
|
3201
|
+
ran: false,
|
|
3202
|
+
ok: false,
|
|
3203
|
+
command: null,
|
|
3204
|
+
exitCode: null,
|
|
3205
|
+
stdout: '',
|
|
3206
|
+
stderr: '',
|
|
3207
|
+
gap: 'missing verification command',
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
const result = spawnSync('/bin/bash', ['-lc', command], {
|
|
3211
|
+
cwd: state.cwd,
|
|
3212
|
+
encoding: 'utf8',
|
|
3213
|
+
env: {
|
|
3214
|
+
...process.env,
|
|
3215
|
+
ARIA_RUNTIME_URL: RUNTIME_URL,
|
|
3216
|
+
ARIA_TASK_ID: state.taskId,
|
|
3217
|
+
ARIA_TASK_PHASE_ID: state.activePhaseId || '',
|
|
3218
|
+
},
|
|
3219
|
+
});
|
|
3220
|
+
const exitCode = typeof result.status === 'number' ? result.status : 1;
|
|
3221
|
+
return {
|
|
3222
|
+
ran: true,
|
|
3223
|
+
ok: exitCode === 0 && !result.error,
|
|
3224
|
+
command,
|
|
3225
|
+
exitCode,
|
|
3226
|
+
signal: result.signal || null,
|
|
3227
|
+
stdout: String(result.stdout || '').slice(-4000),
|
|
3228
|
+
stderr: String(result.stderr || '').slice(-4000),
|
|
3229
|
+
error: result.error ? result.error.message : null,
|
|
3230
|
+
};
|
|
3231
|
+
}
|
|
3232
|
+
async function workerIngestTask(args) {
|
|
3233
|
+
const { flags, rest } = parseFlags(args);
|
|
3234
|
+
const file = flagString(flags, 'file') || flagString(flags, 'output');
|
|
3235
|
+
if (!file)
|
|
3236
|
+
throw new Error('aria task worker-ingest requires --file <worker-output.json>');
|
|
3237
|
+
const workerOutput = readJsonObjectFile(file);
|
|
3238
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || stringField(workerOutput.taskId) || latestTaskId());
|
|
3239
|
+
let state = loadTask(taskId);
|
|
3240
|
+
const phaseId = flagString(flags, 'phase') || stringField(workerOutput.phaseId) || state.activePhaseId || '';
|
|
3241
|
+
const executor = sanitizeTaskId(flagString(flags, 'executor') || stringField(workerOutput.executor) || 'spark');
|
|
3242
|
+
const phase = phaseById(state, phaseId);
|
|
3243
|
+
if (!phase)
|
|
3244
|
+
throw new Error(`No task phase found for worker output phaseId=${phaseId || '<missing>'}.`);
|
|
3245
|
+
const packetFile = flagString(flags, 'packet') || workerPacketPath(state.taskId, phase.phaseId, executor);
|
|
3246
|
+
const packet = existsSync(packetFile) ? readJsonObjectFile(packetFile) : {};
|
|
3247
|
+
const packetAllowedFiles = stringArray(packet.allowedFiles);
|
|
3248
|
+
const packetForbiddenFiles = stringArray(packet.forbiddenFiles);
|
|
3249
|
+
const changedFiles = stringArray(workerOutput.changedFiles);
|
|
3250
|
+
const scope = evaluateWorkerScope(state.cwd, changedFiles, packetAllowedFiles, packetForbiddenFiles);
|
|
3251
|
+
const verificationCommand = flagString(flags, 'verify') || stringField(packet.verificationCommand);
|
|
3252
|
+
const verification = runWorkerVerification({ ...state, activePhaseId: phase.phaseId }, verificationCommand);
|
|
3253
|
+
const outputHash = sha256Json(workerOutput);
|
|
3254
|
+
const gaps = uniqueStrings([
|
|
3255
|
+
...(workerOutput.schema === 'aria.task_worker_output.v1' ? [] : ['worker output schema must be aria.task_worker_output.v1']),
|
|
3256
|
+
...(stringField(workerOutput.taskId) === state.taskId ? [] : [`worker output taskId mismatch: ${stringField(workerOutput.taskId) || '<missing>'}`]),
|
|
3257
|
+
...(stringField(workerOutput.phaseId) === phase.phaseId ? [] : [`worker output phaseId mismatch: ${stringField(workerOutput.phaseId) || '<missing>'}`]),
|
|
3258
|
+
...(stringField(workerOutput.executor) === executor ? [] : [`worker output executor mismatch: ${stringField(workerOutput.executor) || '<missing>'}`]),
|
|
3259
|
+
...stringArray(scope.gaps),
|
|
3260
|
+
...(Object.keys(packet).length ? [] : [`worker packet not found: ${packetFile}`]),
|
|
3261
|
+
...(verification.ok === true ? [] : [`verification failed or missing: ${verificationCommand || '<missing>'}`]),
|
|
3262
|
+
]);
|
|
3263
|
+
const accepted = gaps.length === 0;
|
|
3264
|
+
const receiptId = `worker-ingest-${randomUUID().slice(0, 8)}`;
|
|
3265
|
+
const receiptBase = {
|
|
3266
|
+
schema: 'aria.task_worker_ingest_receipt.v1',
|
|
3267
|
+
receiptId,
|
|
3268
|
+
at: nowIso(),
|
|
3269
|
+
taskId: state.taskId,
|
|
3270
|
+
phaseId: phase.phaseId,
|
|
3271
|
+
executor,
|
|
3272
|
+
accepted,
|
|
3273
|
+
completionAuthorityRetained: true,
|
|
3274
|
+
workerOutputPath: path.resolve(file),
|
|
3275
|
+
workerOutputHash: outputHash,
|
|
3276
|
+
packetPath: packetFile,
|
|
3277
|
+
packetHash: stringField(packet.receiptHash) || sha256Json(packet),
|
|
3278
|
+
summary: stringField(workerOutput.summary),
|
|
3279
|
+
evidence: stringField(workerOutput.evidence),
|
|
3280
|
+
blockers: stringArray(workerOutput.blockers),
|
|
3281
|
+
scope,
|
|
3282
|
+
verification,
|
|
3283
|
+
gaps,
|
|
3284
|
+
nextAction: accepted
|
|
3285
|
+
? 'Codex/Aria reviews the diff and completes the phase only through aria task complete with forced QA.'
|
|
3286
|
+
: 'Correct worker output or create a narrower worker packet before any phase completion claim.',
|
|
3287
|
+
};
|
|
3288
|
+
const receipt = {
|
|
3289
|
+
...receiptBase,
|
|
3290
|
+
receiptHash: sha256Json(receiptBase),
|
|
3291
|
+
};
|
|
3292
|
+
const receiptPath = workerIngestPath(state.taskId, receiptId);
|
|
3293
|
+
writeFileSync(receiptPath, JSON.stringify(receipt, null, 2) + '\n', { mode: 0o600 });
|
|
3294
|
+
const qa = {
|
|
3295
|
+
at: nowIso(),
|
|
3296
|
+
ok: accepted,
|
|
3297
|
+
gaps,
|
|
3298
|
+
artifactSha256: outputHash,
|
|
3299
|
+
source: 'worker-ingest',
|
|
3300
|
+
verification,
|
|
3301
|
+
};
|
|
3302
|
+
const qaLearningLoop = buildQaLearningLoop(state, phase, qa, 'worker-ingest', path.resolve(file));
|
|
3303
|
+
const phases = state.phases.map((item) => item.phaseId === phase.phaseId
|
|
3304
|
+
? {
|
|
3305
|
+
...item,
|
|
3306
|
+
status: accepted ? item.status : 'qa_failed',
|
|
3307
|
+
qa: accepted ? item.qa : qa,
|
|
3308
|
+
}
|
|
3309
|
+
: item);
|
|
3310
|
+
const checkpoint = {
|
|
3311
|
+
at: nowIso(),
|
|
3312
|
+
phase: phase.phaseId,
|
|
3313
|
+
receipt: 'worker-output-ingest',
|
|
3314
|
+
executor,
|
|
3315
|
+
accepted,
|
|
3316
|
+
receiptPath,
|
|
3317
|
+
receiptHash: receipt.receiptHash,
|
|
3318
|
+
changedFiles: scope.changedFiles,
|
|
3319
|
+
verification,
|
|
3320
|
+
gaps,
|
|
3321
|
+
};
|
|
3322
|
+
state = saveTask({
|
|
3323
|
+
...state,
|
|
3324
|
+
status: accepted ? state.status : 'blocked',
|
|
3325
|
+
activePhaseId: phase.phaseId,
|
|
3326
|
+
phases,
|
|
3327
|
+
checkpoints: [...state.checkpoints, checkpoint],
|
|
3328
|
+
qualityLoops: [...(state.qualityLoops || []), qaLearningLoop].slice(-50),
|
|
3329
|
+
}, {
|
|
3330
|
+
type: accepted ? 'worker_output_ingested' : 'worker_output_qa_failed',
|
|
3331
|
+
phaseId: phase.phaseId,
|
|
3332
|
+
executor,
|
|
3333
|
+
receipt,
|
|
3334
|
+
qaLearningLoop,
|
|
3335
|
+
});
|
|
3336
|
+
const substrateOpen = await openTaskSubstrate(state, accepted ? 'worker_output_ingested' : 'worker_output_qa_failed', phase.phaseId);
|
|
3337
|
+
const hiveRuntimeReport = await publishWorkerHiveContext(state, phaseById(state, phase.phaseId) || phase, accepted ? 'aria_task_worker_output_ingested' : 'aria_task_worker_output_qa_failed', {
|
|
3338
|
+
worker_executor: executor,
|
|
3339
|
+
worker_phase_id: phase.phaseId,
|
|
3340
|
+
worker_output_hash: outputHash,
|
|
3341
|
+
worker_ingest_receipt_hash: receipt.receiptHash,
|
|
3342
|
+
accepted,
|
|
3343
|
+
changed_files: stringArray(scope.changedFiles),
|
|
3344
|
+
gaps,
|
|
3345
|
+
verification,
|
|
3346
|
+
latest_qa: qa,
|
|
3347
|
+
substrate_open: compactSubstrateOpen(substrateOpen),
|
|
3348
|
+
});
|
|
3349
|
+
state = await consumeTaskPhaseBoundary(state, 'worker_output_ingested', phaseById(state, phase.phaseId) || phase, {
|
|
3350
|
+
step: 'bounded-worker-ingest-qa',
|
|
3351
|
+
summary: accepted ? 'Worker output passed bounded scope and verification checks' : 'Worker output failed bounded scope or verification checks',
|
|
3352
|
+
evidence: `receiptPath=${receiptPath}; changedFiles=${stringArray(scope.changedFiles).length}; verificationRan=${verification.ran === true}`,
|
|
3353
|
+
qa,
|
|
3354
|
+
gaps,
|
|
3355
|
+
action: accepted ? 'codex-review-before-phase-complete' : 'correct-worker-output-before-phase-complete',
|
|
3356
|
+
});
|
|
3357
|
+
await publishQaLearningContext(state, qaLearningLoop);
|
|
3358
|
+
await recordRuntimeLedger(state, accepted ? 'worker_output_ingested' : 'worker_output_qa_failed', {
|
|
3359
|
+
phase: phaseById(state, phase.phaseId) || phase,
|
|
3360
|
+
executor,
|
|
3361
|
+
accepted,
|
|
3362
|
+
receiptPath,
|
|
3363
|
+
receiptHash: receipt.receiptHash,
|
|
3364
|
+
summary: receipt.summary,
|
|
3365
|
+
}, {
|
|
3366
|
+
qa,
|
|
3367
|
+
qaLearningLoop,
|
|
3368
|
+
gaps,
|
|
3369
|
+
fileClaims: stringArray(scope.changedFiles).map((filePath) => ({ path: filePath, claim: 'worker_changed', source: 'worker_output' })),
|
|
3370
|
+
workerIngestReceipt: receipt,
|
|
3371
|
+
substrateOpen,
|
|
3372
|
+
hiveRuntimeReport,
|
|
3373
|
+
});
|
|
3374
|
+
console.log(JSON.stringify({
|
|
3375
|
+
ok: accepted,
|
|
3376
|
+
accepted,
|
|
3377
|
+
taskId: state.taskId,
|
|
3378
|
+
phaseId: phase.phaseId,
|
|
3379
|
+
executor,
|
|
3380
|
+
gaps,
|
|
3381
|
+
receiptPath,
|
|
3382
|
+
receiptHash: receipt.receiptHash,
|
|
3383
|
+
next: receipt.nextAction,
|
|
3384
|
+
}, null, 2));
|
|
3385
|
+
if (!accepted)
|
|
3386
|
+
process.exit(1);
|
|
3387
|
+
}
|
|
3388
|
+
async function statusTask(args) {
|
|
3389
|
+
const { flags, rest } = parseFlags(args);
|
|
3390
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
3391
|
+
const state = loadTask(taskId);
|
|
3392
|
+
const health = await runtimeGet('/health').catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) }));
|
|
3393
|
+
const actionLedgerEvents = readActionLedgerEvents({ home: HOME, projectId: `aria-task-${taskId}`, taskId });
|
|
3394
|
+
const actionLedgerProjection = projectActionLedger(actionLedgerEvents);
|
|
3395
|
+
const compiledValidation = validateCompiledWorkUnitForExecution(state.compiledWorkUnit || null);
|
|
3396
|
+
console.log(JSON.stringify({
|
|
3397
|
+
ok: true,
|
|
3398
|
+
task: state,
|
|
3399
|
+
compiledWorkUnit: {
|
|
3400
|
+
summary: compiledWorkUnitSummary(state.compiledWorkUnit || null),
|
|
3401
|
+
path: state.compiledWorkUnitPath || null,
|
|
3402
|
+
validation: compiledValidation,
|
|
3403
|
+
},
|
|
3404
|
+
paths: { statePath: taskPath(taskId), eventsPath: eventPath(taskId), runtimePublishOutboxPath: runtimePublishOutboxPath(taskId) },
|
|
3405
|
+
actionLedger: {
|
|
3406
|
+
eventCount: actionLedgerProjection.eventCount,
|
|
3407
|
+
latestEvent: actionLedgerProjection.latestEvent,
|
|
3408
|
+
task: actionLedgerProjection.tasks[taskId] || null,
|
|
3409
|
+
compiledWorkUnits: actionLedgerProjection.compiledWorkUnits,
|
|
3410
|
+
correctionRequired: actionLedgerProjection.correctionRequired,
|
|
3411
|
+
latestQa: actionLedgerProjection.latestQa,
|
|
3412
|
+
latestLearningDelta: actionLedgerProjection.latestLearningDelta,
|
|
3413
|
+
latestAtlas: actionLedgerProjection.latestAtlas,
|
|
3414
|
+
sentinelFindingCount: actionLedgerProjection.sentinelFindings.length,
|
|
3415
|
+
},
|
|
3416
|
+
partialCloseoutDrift: detectPartialCloseoutDrift(state),
|
|
3417
|
+
runtime: health,
|
|
3418
|
+
}, null, 2));
|
|
3419
|
+
}
|
|
3420
|
+
async function qaTask(args) {
|
|
3421
|
+
const { flags, rest } = parseFlags(args);
|
|
3422
|
+
const taskId = sanitizeTaskId(rest[0] || flagString(flags, 'id') || latestTaskId());
|
|
3423
|
+
const file = flagString(flags, 'file');
|
|
3424
|
+
const text = file ? readFileSync(path.resolve(file), 'utf8') : rest.slice(1).join(' ');
|
|
3425
|
+
if (!text.trim())
|
|
3426
|
+
throw new Error('aria task qa requires --file <path> or inline text after task id');
|
|
3427
|
+
const gaps = methodGaps(text);
|
|
3428
|
+
const state = loadTask(taskId);
|
|
3429
|
+
const checkpoint = {
|
|
3430
|
+
at: nowIso(),
|
|
3431
|
+
phase: 'qa',
|
|
3432
|
+
summary: gaps.length ? 'QA failed method contract' : 'QA passed method contract',
|
|
3433
|
+
gaps,
|
|
3434
|
+
artifactSha256: sha256(text),
|
|
3435
|
+
};
|
|
3436
|
+
const current = activePhase(state);
|
|
3437
|
+
const qaLearningLoop = buildQaLearningLoop(state, current, {
|
|
3438
|
+
ok: gaps.length === 0,
|
|
3439
|
+
gaps,
|
|
3440
|
+
artifactSha256: sha256(text),
|
|
3441
|
+
}, 'qa', file ? path.resolve(file) : undefined);
|
|
3442
|
+
const phases = current
|
|
3443
|
+
? state.phases.map((phase) => phase.phaseId === current.phaseId
|
|
3444
|
+
? { ...phase, status: gaps.length ? 'qa_failed' : phase.status, qa: { at: String(checkpoint.at), ok: gaps.length === 0, gaps, artifactSha256: sha256(text) } }
|
|
3445
|
+
: phase)
|
|
3446
|
+
: state.phases;
|
|
3447
|
+
let next = saveTask({
|
|
3448
|
+
...state,
|
|
3449
|
+
phases,
|
|
3450
|
+
checkpoints: [...state.checkpoints, checkpoint],
|
|
3451
|
+
qualityLoops: [...(state.qualityLoops || []), qaLearningLoop].slice(-50),
|
|
3452
|
+
status: gaps.length ? 'blocked' : state.status,
|
|
3453
|
+
}, { type: 'qa', checkpoint, qaLearningLoop });
|
|
3454
|
+
next = await consumeTaskPhaseBoundary(next, 'qa', activePhase(next), {
|
|
3455
|
+
step: 'task-qa',
|
|
3456
|
+
summary: checkpoint.summary,
|
|
3457
|
+
evidence: file ? path.resolve(file) : 'inline qa artifact',
|
|
3458
|
+
qa: { ok: gaps.length === 0, gaps, artifactSha256: sha256(text) },
|
|
3459
|
+
gaps,
|
|
3460
|
+
action: gaps.length ? 'correct-qa-findings' : 'continue',
|
|
3461
|
+
});
|
|
3462
|
+
await publishQaLearningContext(next, qaLearningLoop);
|
|
3463
|
+
await recordRuntimeLedger(next, 'qa', checkpoint, { gaps, qaLearningLoop });
|
|
3464
|
+
console.log(JSON.stringify({ ok: gaps.length === 0, taskId, gaps, qaLearningLoop }, null, 2));
|
|
3465
|
+
if (gaps.length)
|
|
3466
|
+
process.exit(1);
|
|
3467
|
+
}
|
|
3468
|
+
export async function handleTaskCommand(args, cwd = process.cwd()) {
|
|
3469
|
+
const subCommand = args[0] || 'help';
|
|
3470
|
+
const rest = args.slice(1);
|
|
3471
|
+
if (subCommand === 'help' || subCommand === '--help' || subCommand === '-h') {
|
|
3472
|
+
console.log([
|
|
3473
|
+
'',
|
|
3474
|
+
' aria task start --goal "..." Create a ledger-backed CLI-executed task and print reinjection context.',
|
|
3475
|
+
' aria task continue [taskId] Re-fire skills and print the reinjection packet for the active task.',
|
|
3476
|
+
' aria task enqueue [taskId] Add a phase with --phase "...".',
|
|
3477
|
+
' aria task next [taskId] Claim/resume the next phase for this LLM/CLI session.',
|
|
3478
|
+
' aria task run [taskId] Parent CLI ledger/QA loop only; add --executor codex for real Codex execution.',
|
|
3479
|
+
' aria task run --executor codex Launch wrapped Codex exec with the runtime-built skill packet for the active phase.',
|
|
3480
|
+
' aria task run --executor spark Prepare/dispatch a bounded cheap-worker packet, then ingest through Aria QA gates.',
|
|
3481
|
+
' aria task complete [taskId] Complete active phase; requires --summary and --evidence; forced QA court autofires when --qa-file is absent.',
|
|
3482
|
+
' aria task close [taskId] Finalize task after all phases pass QA, runtime skill floors, and closeout-drift gates.',
|
|
3483
|
+
' aria task recover [taskId] Reopen blocked phase with --reason and re-fire skills.',
|
|
3484
|
+
' aria task checkpoint [taskId] Append a task checkpoint and runtime ledger event.',
|
|
3485
|
+
' aria task worker-packet [taskId] Write a bounded cheap-worker packet with --executor, --allowed-files, and --verify.',
|
|
3486
|
+
' aria task worker-ingest [taskId] Ingest worker JSON, enforce scope/verification, and keep completion authority in Aria/Codex.',
|
|
3487
|
+
' aria task qa [taskId] --file x.md Check full Qiyas-15 and full Tadabbur artifacts.',
|
|
3488
|
+
' aria task status [taskId] Show task state plus runtime health.',
|
|
3489
|
+
'',
|
|
3490
|
+
' Start phases with --phases "scope|execute|qa|harden|verify".',
|
|
3491
|
+
' Task runner accepts --executor codex|spark, --allowed-files, --forbidden-files, --verify, --dispatch-command, --dry-run, --qa-file, --fix-qa-file, --max-recoveries, --auto-qa, and --all.',
|
|
3492
|
+
'',
|
|
3493
|
+
' This is a CLI/LLM executor harness. Worker dispatch is explicit, packet-scoped, and re-ingested through QA.',
|
|
3494
|
+
'',
|
|
3495
|
+
].join('\n'));
|
|
3496
|
+
return;
|
|
3497
|
+
}
|
|
3498
|
+
if (subCommand === 'start')
|
|
3499
|
+
return startTask(rest, cwd);
|
|
3500
|
+
if (subCommand === 'continue')
|
|
3501
|
+
return continueTask(rest);
|
|
3502
|
+
if (subCommand === 'enqueue')
|
|
3503
|
+
return enqueueTask(rest);
|
|
3504
|
+
if (subCommand === 'next')
|
|
3505
|
+
return nextTask(rest);
|
|
3506
|
+
if (subCommand === 'run')
|
|
3507
|
+
return runTask(rest);
|
|
3508
|
+
if (subCommand === 'complete')
|
|
3509
|
+
return completeTask(rest);
|
|
3510
|
+
if (subCommand === 'close' || subCommand === 'finalize')
|
|
3511
|
+
return closeTask(rest);
|
|
3512
|
+
if (subCommand === 'recover')
|
|
3513
|
+
return recoverTask(rest);
|
|
3514
|
+
if (subCommand === 'checkpoint')
|
|
3515
|
+
return checkpointTask(rest);
|
|
3516
|
+
if (subCommand === 'worker-packet')
|
|
3517
|
+
return workerPacketTask(rest);
|
|
3518
|
+
if (subCommand === 'worker-ingest')
|
|
3519
|
+
return workerIngestTask(rest);
|
|
3520
|
+
if (subCommand === 'status')
|
|
3521
|
+
return statusTask(rest);
|
|
3522
|
+
if (subCommand === 'qa')
|
|
3523
|
+
return qaTask(rest);
|
|
3524
|
+
throw new Error(`Unknown aria task subcommand: ${subCommand}`);
|
|
3525
|
+
}
|
|
3526
|
+
//# sourceMappingURL=task-runner.js.map
|