@rpamis/comet 0.4.0-beta.6 → 0.4.0-beta.7
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/README.md +209 -74
- package/assets/manifest.json +14 -5
- package/assets/skills/comet/SKILL.md +17 -282
- package/assets/skills/comet/reference/comet-yaml-fields.md +1 -1
- package/assets/skills/comet/reference/context-recovery.md +3 -3
- package/assets/skills/comet/reference/intent-frame.md +2 -2
- package/assets/skills/comet/reference/scripts.md +2 -2
- package/assets/skills/comet/rules/comet-workflow-guard.en.md +32 -0
- package/assets/skills/comet/rules/comet-workflow-guard.md +32 -0
- package/assets/skills/comet/scripts/comet-entry-runtime.mjs +7834 -0
- package/assets/skills/comet/scripts/comet-hook-router.mjs +10307 -0
- package/assets/skills/comet/scripts/comet-runtime.mjs +612 -499
- package/assets/skills/comet-any/SKILL.md +4 -4
- package/assets/skills/comet-any/reference/authoring-subagents.md +1 -1
- package/assets/skills/comet-any/reference/bundle-authoring.md +1 -1
- package/assets/skills/comet-any/reference/subagents/reference-author.md +1 -1
- package/assets/skills/comet-any/reference/subagents/script-author.md +1 -1
- package/assets/skills/comet-any/reference/subagents/skill-core-author.md +1 -1
- package/assets/skills/comet-any/reference/subagents/skill-reviewer.md +2 -2
- package/assets/skills/comet-any/reference/subagents/workflow-entry-author.md +3 -3
- package/assets/skills/comet-archive/SKILL.md +1 -2
- package/assets/skills/comet-build/SKILL.md +1 -1
- package/assets/skills/comet-classic/SKILL.md +293 -0
- package/assets/skills/comet-design/SKILL.md +1 -1
- package/assets/skills/comet-hotfix/SKILL.md +4 -4
- package/assets/skills/comet-native/SKILL.md +257 -0
- package/assets/skills/comet-native/reference/artifacts.md +204 -0
- package/assets/skills/comet-native/reference/commands.md +118 -0
- package/assets/skills/comet-native/reference/recovery.md +143 -0
- package/assets/skills/comet-native/scripts/comet-native-hook-guard.mjs +4 -0
- package/assets/skills/comet-native/scripts/comet-native-runtime.mjs +28898 -0
- package/assets/skills/comet-open/SKILL.md +4 -4
- package/assets/skills/comet-tweak/SKILL.md +7 -7
- package/assets/skills-zh/comet/SKILL.md +17 -270
- package/assets/skills-zh/comet/reference/comet-yaml-fields.md +1 -1
- package/assets/skills-zh/comet/reference/context-recovery.md +3 -3
- package/assets/skills-zh/comet/reference/intent-frame.md +2 -2
- package/assets/skills-zh/comet/reference/scripts.md +2 -2
- package/assets/skills-zh/comet-any/SKILL.md +4 -4
- package/assets/skills-zh/comet-any/reference/authoring-subagents.md +1 -1
- package/assets/skills-zh/comet-any/reference/bundle-authoring.md +1 -1
- package/assets/skills-zh/comet-any/reference/subagents/reference-author.md +1 -1
- package/assets/skills-zh/comet-any/reference/subagents/script-author.md +1 -1
- package/assets/skills-zh/comet-any/reference/subagents/skill-core-author.md +1 -1
- package/assets/skills-zh/comet-any/reference/subagents/skill-reviewer.md +2 -2
- package/assets/skills-zh/comet-any/reference/subagents/workflow-entry-author.md +3 -3
- package/assets/skills-zh/comet-archive/SKILL.md +1 -2
- package/assets/skills-zh/comet-build/SKILL.md +1 -1
- package/assets/skills-zh/comet-classic/SKILL.md +281 -0
- package/assets/skills-zh/comet-design/SKILL.md +1 -1
- package/assets/skills-zh/comet-hotfix/SKILL.md +4 -4
- package/assets/skills-zh/comet-native/SKILL.md +257 -0
- package/assets/skills-zh/comet-native/reference/artifacts.md +206 -0
- package/assets/skills-zh/comet-native/reference/commands.md +118 -0
- package/assets/skills-zh/comet-native/reference/recovery.md +143 -0
- package/assets/skills-zh/comet-open/SKILL.md +4 -4
- package/assets/skills-zh/comet-tweak/SKILL.md +7 -7
- package/dist/app/cli/index.js +59 -13
- package/dist/app/cli/index.js.map +1 -1
- package/dist/app/commands/command-result.d.ts +6 -0
- package/dist/app/commands/command-result.d.ts.map +1 -0
- package/dist/app/commands/command-result.js +4 -0
- package/dist/app/commands/command-result.js.map +1 -0
- package/dist/app/commands/doctor.d.ts +1 -0
- package/dist/app/commands/doctor.d.ts.map +1 -1
- package/dist/app/commands/doctor.js +201 -26
- package/dist/app/commands/doctor.js.map +1 -1
- package/dist/app/commands/eval.d.ts +3 -1
- package/dist/app/commands/eval.d.ts.map +1 -1
- package/dist/app/commands/eval.js +17 -7
- package/dist/app/commands/eval.js.map +1 -1
- package/dist/app/commands/i18n.d.ts +1 -1
- package/dist/app/commands/i18n.d.ts.map +1 -1
- package/dist/app/commands/i18n.js +6 -2
- package/dist/app/commands/i18n.js.map +1 -1
- package/dist/app/commands/init.d.ts +10 -2
- package/dist/app/commands/init.d.ts.map +1 -1
- package/dist/app/commands/init.js +331 -50
- package/dist/app/commands/init.js.map +1 -1
- package/dist/app/commands/native.d.ts +2 -0
- package/dist/app/commands/native.d.ts.map +1 -0
- package/dist/app/commands/native.js +10 -0
- package/dist/app/commands/native.js.map +1 -0
- package/dist/app/commands/project-scope-selection.d.ts.map +1 -1
- package/dist/app/commands/project-scope-selection.js +2 -0
- package/dist/app/commands/project-scope-selection.js.map +1 -1
- package/dist/app/commands/resume-probe.d.ts.map +1 -1
- package/dist/app/commands/resume-probe.js +8 -2
- package/dist/app/commands/resume-probe.js.map +1 -1
- package/dist/app/commands/status.d.ts +0 -32
- package/dist/app/commands/status.d.ts.map +1 -1
- package/dist/app/commands/status.js +44 -177
- package/dist/app/commands/status.js.map +1 -1
- package/dist/app/commands/update.d.ts +20 -4
- package/dist/app/commands/update.d.ts.map +1 -1
- package/dist/app/commands/update.js +698 -90
- package/dist/app/commands/update.js.map +1 -1
- package/dist/app/commands/workflow.d.ts +6 -0
- package/dist/app/commands/workflow.d.ts.map +1 -0
- package/dist/app/commands/workflow.js +11 -0
- package/dist/app/commands/workflow.js.map +1 -0
- package/dist/config/repository-layout.json +21 -1
- package/dist/domains/comet-classic/classic-archive.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-archive.js +3 -0
- package/dist/domains/comet-classic/classic-archive.js.map +1 -1
- package/dist/domains/comet-classic/classic-current-change.d.ts +3 -5
- package/dist/domains/comet-classic/classic-current-change.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-current-change.js +31 -57
- package/dist/domains/comet-classic/classic-current-change.js.map +1 -1
- package/dist/domains/comet-classic/classic-hook-guard.d.ts +9 -0
- package/dist/domains/comet-classic/classic-hook-guard.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-hook-guard.js +84 -11
- package/dist/domains/comet-classic/classic-hook-guard.js.map +1 -1
- package/dist/domains/comet-classic/classic-project-config.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-project-config.js +12 -8
- package/dist/domains/comet-classic/classic-project-config.js.map +1 -1
- package/dist/domains/comet-classic/classic-runtime-run.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-runtime-run.js +9 -1
- package/dist/domains/comet-classic/classic-runtime-run.js.map +1 -1
- package/dist/domains/comet-entry/current-selection-repair.d.ts +17 -0
- package/dist/domains/comet-entry/current-selection-repair.d.ts.map +1 -0
- package/dist/domains/comet-entry/current-selection-repair.js +19 -0
- package/dist/domains/comet-entry/current-selection-repair.js.map +1 -0
- package/dist/domains/comet-entry/current-selection.d.ts +28 -0
- package/dist/domains/comet-entry/current-selection.d.ts.map +1 -0
- package/dist/domains/comet-entry/current-selection.js +116 -0
- package/dist/domains/comet-entry/current-selection.js.map +1 -0
- package/dist/domains/comet-entry/entry-runtime-entry.d.ts +2 -0
- package/dist/domains/comet-entry/entry-runtime-entry.d.ts.map +1 -0
- package/dist/domains/comet-entry/entry-runtime-entry.js +3 -0
- package/dist/domains/comet-entry/entry-runtime-entry.js.map +1 -0
- package/dist/domains/comet-entry/entry-runtime.d.ts +7 -0
- package/dist/domains/comet-entry/entry-runtime.d.ts.map +1 -0
- package/dist/domains/comet-entry/entry-runtime.js +55 -0
- package/dist/domains/comet-entry/entry-runtime.js.map +1 -0
- package/dist/domains/comet-entry/hook-adapter.d.ts +6 -0
- package/dist/domains/comet-entry/hook-adapter.d.ts.map +1 -0
- package/dist/domains/comet-entry/hook-adapter.js +202 -0
- package/dist/domains/comet-entry/hook-adapter.js.map +1 -0
- package/dist/domains/comet-entry/hook-router-entry.d.ts +8 -0
- package/dist/domains/comet-entry/hook-router-entry.d.ts.map +1 -0
- package/dist/domains/comet-entry/hook-router-entry.js +92 -0
- package/dist/domains/comet-entry/hook-router-entry.js.map +1 -0
- package/dist/domains/comet-entry/hook-router.d.ts +32 -0
- package/dist/domains/comet-entry/hook-router.d.ts.map +1 -0
- package/dist/domains/comet-entry/hook-router.js +133 -0
- package/dist/domains/comet-entry/hook-router.js.map +1 -0
- package/dist/domains/comet-entry/hook-types.d.ts +20 -0
- package/dist/domains/comet-entry/hook-types.d.ts.map +1 -0
- package/dist/domains/comet-entry/hook-types.js +2 -0
- package/dist/domains/comet-entry/hook-types.js.map +1 -0
- package/dist/domains/comet-entry/init-workflow.d.ts +16 -0
- package/dist/domains/comet-entry/init-workflow.d.ts.map +1 -0
- package/dist/domains/comet-entry/init-workflow.js +103 -0
- package/dist/domains/comet-entry/init-workflow.js.map +1 -0
- package/dist/domains/comet-entry/project-status.d.ts +3 -0
- package/dist/domains/comet-entry/project-status.d.ts.map +1 -0
- package/dist/domains/comet-entry/project-status.js +222 -0
- package/dist/domains/comet-entry/project-status.js.map +1 -0
- package/dist/domains/comet-entry/resolve-entry.d.ts +3 -0
- package/dist/domains/comet-entry/resolve-entry.d.ts.map +1 -0
- package/dist/domains/comet-entry/resolve-entry.js +22 -0
- package/dist/domains/comet-entry/resolve-entry.js.map +1 -0
- package/dist/domains/comet-entry/resume-probe.d.ts +34 -0
- package/dist/domains/comet-entry/resume-probe.d.ts.map +1 -0
- package/dist/domains/comet-entry/resume-probe.js +458 -0
- package/dist/domains/comet-entry/resume-probe.js.map +1 -0
- package/dist/domains/comet-entry/types.d.ts +59 -0
- package/dist/domains/comet-entry/types.d.ts.map +1 -0
- package/dist/domains/comet-entry/types.js +2 -0
- package/dist/domains/comet-entry/types.js.map +1 -0
- package/dist/domains/comet-entry/workflow-resolution.d.ts +8 -0
- package/dist/domains/comet-entry/workflow-resolution.d.ts.map +1 -0
- package/dist/domains/comet-entry/workflow-resolution.js +16 -0
- package/dist/domains/comet-entry/workflow-resolution.js.map +1 -0
- package/dist/domains/comet-native/index.d.ts +35 -0
- package/dist/domains/comet-native/index.d.ts.map +1 -0
- package/dist/domains/comet-native/index.js +35 -0
- package/dist/domains/comet-native/index.js.map +1 -0
- package/dist/domains/comet-native/native-acceptance.d.ts +42 -0
- package/dist/domains/comet-native/native-acceptance.d.ts.map +1 -0
- package/dist/domains/comet-native/native-acceptance.js +503 -0
- package/dist/domains/comet-native/native-acceptance.js.map +1 -0
- package/dist/domains/comet-native/native-archive-content.d.ts +26 -0
- package/dist/domains/comet-native/native-archive-content.d.ts.map +1 -0
- package/dist/domains/comet-native/native-archive-content.js +159 -0
- package/dist/domains/comet-native/native-archive-content.js.map +1 -0
- package/dist/domains/comet-native/native-archive-inspection.d.ts +9 -0
- package/dist/domains/comet-native/native-archive-inspection.d.ts.map +1 -0
- package/dist/domains/comet-native/native-archive-inspection.js +94 -0
- package/dist/domains/comet-native/native-archive-inspection.js.map +1 -0
- package/dist/domains/comet-native/native-archive-preflight.d.ts +52 -0
- package/dist/domains/comet-native/native-archive-preflight.d.ts.map +1 -0
- package/dist/domains/comet-native/native-archive-preflight.js +214 -0
- package/dist/domains/comet-native/native-archive-preflight.js.map +1 -0
- package/dist/domains/comet-native/native-archive-transaction.d.ts +19 -0
- package/dist/domains/comet-native/native-archive-transaction.d.ts.map +1 -0
- package/dist/domains/comet-native/native-archive-transaction.js +1181 -0
- package/dist/domains/comet-native/native-archive-transaction.js.map +1 -0
- package/dist/domains/comet-native/native-archive.d.ts +36 -0
- package/dist/domains/comet-native/native-archive.d.ts.map +1 -0
- package/dist/domains/comet-native/native-archive.js +403 -0
- package/dist/domains/comet-native/native-archive.js.map +1 -0
- package/dist/domains/comet-native/native-artifacts.d.ts +10 -0
- package/dist/domains/comet-native/native-artifacts.d.ts.map +1 -0
- package/dist/domains/comet-native/native-artifacts.js +204 -0
- package/dist/domains/comet-native/native-artifacts.js.map +1 -0
- package/dist/domains/comet-native/native-atomic-file.d.ts +10 -0
- package/dist/domains/comet-native/native-atomic-file.d.ts.map +1 -0
- package/dist/domains/comet-native/native-atomic-file.js +175 -0
- package/dist/domains/comet-native/native-atomic-file.js.map +1 -0
- package/dist/domains/comet-native/native-bounded-file.d.ts +19 -0
- package/dist/domains/comet-native/native-bounded-file.d.ts.map +1 -0
- package/dist/domains/comet-native/native-bounded-file.js +180 -0
- package/dist/domains/comet-native/native-bounded-file.js.map +1 -0
- package/dist/domains/comet-native/native-build-evidence.d.ts +42 -0
- package/dist/domains/comet-native/native-build-evidence.d.ts.map +1 -0
- package/dist/domains/comet-native/native-build-evidence.js +257 -0
- package/dist/domains/comet-native/native-build-evidence.js.map +1 -0
- package/dist/domains/comet-native/native-canonical-hash.d.ts +10 -0
- package/dist/domains/comet-native/native-canonical-hash.d.ts.map +1 -0
- package/dist/domains/comet-native/native-canonical-hash.js +100 -0
- package/dist/domains/comet-native/native-canonical-hash.js.map +1 -0
- package/dist/domains/comet-native/native-change-recovery.d.ts +11 -0
- package/dist/domains/comet-native/native-change-recovery.d.ts.map +1 -0
- package/dist/domains/comet-native/native-change-recovery.js +15 -0
- package/dist/domains/comet-native/native-change-recovery.js.map +1 -0
- package/dist/domains/comet-native/native-change.d.ts +61 -0
- package/dist/domains/comet-native/native-change.d.ts.map +1 -0
- package/dist/domains/comet-native/native-change.js +696 -0
- package/dist/domains/comet-native/native-change.js.map +1 -0
- package/dist/domains/comet-native/native-check-receipt-model.d.ts +63 -0
- package/dist/domains/comet-native/native-check-receipt-model.d.ts.map +1 -0
- package/dist/domains/comet-native/native-check-receipt-model.js +347 -0
- package/dist/domains/comet-native/native-check-receipt-model.js.map +1 -0
- package/dist/domains/comet-native/native-check-receipt-storage.d.ts +10 -0
- package/dist/domains/comet-native/native-check-receipt-storage.d.ts.map +1 -0
- package/dist/domains/comet-native/native-check-receipt-storage.js +196 -0
- package/dist/domains/comet-native/native-check-receipt-storage.js.map +1 -0
- package/dist/domains/comet-native/native-check-receipt.d.ts +19 -0
- package/dist/domains/comet-native/native-check-receipt.d.ts.map +1 -0
- package/dist/domains/comet-native/native-check-receipt.js +446 -0
- package/dist/domains/comet-native/native-check-receipt.js.map +1 -0
- package/dist/domains/comet-native/native-check.d.ts +18 -0
- package/dist/domains/comet-native/native-check.d.ts.map +1 -0
- package/dist/domains/comet-native/native-check.js +29 -0
- package/dist/domains/comet-native/native-check.js.map +1 -0
- package/dist/domains/comet-native/native-checkpoint-journal.d.ts +13 -0
- package/dist/domains/comet-native/native-checkpoint-journal.d.ts.map +1 -0
- package/dist/domains/comet-native/native-checkpoint-journal.js +53 -0
- package/dist/domains/comet-native/native-checkpoint-journal.js.map +1 -0
- package/dist/domains/comet-native/native-checkpoint-storage.d.ts +43 -0
- package/dist/domains/comet-native/native-checkpoint-storage.d.ts.map +1 -0
- package/dist/domains/comet-native/native-checkpoint-storage.js +487 -0
- package/dist/domains/comet-native/native-checkpoint-storage.js.map +1 -0
- package/dist/domains/comet-native/native-cli-entry.d.ts +2 -0
- package/dist/domains/comet-native/native-cli-entry.d.ts.map +1 -0
- package/dist/domains/comet-native/native-cli-entry.js +18 -0
- package/dist/domains/comet-native/native-cli-entry.js.map +1 -0
- package/dist/domains/comet-native/native-cli.d.ts +7 -0
- package/dist/domains/comet-native/native-cli.d.ts.map +1 -0
- package/dist/domains/comet-native/native-cli.js +642 -0
- package/dist/domains/comet-native/native-cli.js.map +1 -0
- package/dist/domains/comet-native/native-config.d.ts +15 -0
- package/dist/domains/comet-native/native-config.d.ts.map +1 -0
- package/dist/domains/comet-native/native-config.js +281 -0
- package/dist/domains/comet-native/native-config.js.map +1 -0
- package/dist/domains/comet-native/native-conflict-inspection.d.ts +17 -0
- package/dist/domains/comet-native/native-conflict-inspection.d.ts.map +1 -0
- package/dist/domains/comet-native/native-conflict-inspection.js +90 -0
- package/dist/domains/comet-native/native-conflict-inspection.js.map +1 -0
- package/dist/domains/comet-native/native-conflict-radar.d.ts +75 -0
- package/dist/domains/comet-native/native-conflict-radar.d.ts.map +1 -0
- package/dist/domains/comet-native/native-conflict-radar.js +326 -0
- package/dist/domains/comet-native/native-conflict-radar.js.map +1 -0
- package/dist/domains/comet-native/native-continuation.d.ts +9 -0
- package/dist/domains/comet-native/native-continuation.d.ts.map +1 -0
- package/dist/domains/comet-native/native-continuation.js +146 -0
- package/dist/domains/comet-native/native-continuation.js.map +1 -0
- package/dist/domains/comet-native/native-contract-files.d.ts +24 -0
- package/dist/domains/comet-native/native-contract-files.d.ts.map +1 -0
- package/dist/domains/comet-native/native-contract-files.js +66 -0
- package/dist/domains/comet-native/native-contract-files.js.map +1 -0
- package/dist/domains/comet-native/native-contract.d.ts +41 -0
- package/dist/domains/comet-native/native-contract.d.ts.map +1 -0
- package/dist/domains/comet-native/native-contract.js +141 -0
- package/dist/domains/comet-native/native-contract.js.map +1 -0
- package/dist/domains/comet-native/native-diagnostics.d.ts +18 -0
- package/dist/domains/comet-native/native-diagnostics.d.ts.map +1 -0
- package/dist/domains/comet-native/native-diagnostics.js +522 -0
- package/dist/domains/comet-native/native-diagnostics.js.map +1 -0
- package/dist/domains/comet-native/native-doctor.d.ts +12 -0
- package/dist/domains/comet-native/native-doctor.d.ts.map +1 -0
- package/dist/domains/comet-native/native-doctor.js +768 -0
- package/dist/domains/comet-native/native-doctor.js.map +1 -0
- package/dist/domains/comet-native/native-evidence-retention.d.ts +37 -0
- package/dist/domains/comet-native/native-evidence-retention.d.ts.map +1 -0
- package/dist/domains/comet-native/native-evidence-retention.js +885 -0
- package/dist/domains/comet-native/native-evidence-retention.js.map +1 -0
- package/dist/domains/comet-native/native-evidence-storage.d.ts +41 -0
- package/dist/domains/comet-native/native-evidence-storage.d.ts.map +1 -0
- package/dist/domains/comet-native/native-evidence-storage.js +351 -0
- package/dist/domains/comet-native/native-evidence-storage.js.map +1 -0
- package/dist/domains/comet-native/native-findings.d.ts +8 -0
- package/dist/domains/comet-native/native-findings.d.ts.map +1 -0
- package/dist/domains/comet-native/native-findings.js +238 -0
- package/dist/domains/comet-native/native-findings.js.map +1 -0
- package/dist/domains/comet-native/native-guards.d.ts +7 -0
- package/dist/domains/comet-native/native-guards.d.ts.map +1 -0
- package/dist/domains/comet-native/native-guards.js +126 -0
- package/dist/domains/comet-native/native-guards.js.map +1 -0
- package/dist/domains/comet-native/native-hash.d.ts +3 -0
- package/dist/domains/comet-native/native-hash.d.ts.map +1 -0
- package/dist/domains/comet-native/native-hash.js +12 -0
- package/dist/domains/comet-native/native-hash.js.map +1 -0
- package/dist/domains/comet-native/native-hook-guard.d.ts +17 -0
- package/dist/domains/comet-native/native-hook-guard.d.ts.map +1 -0
- package/dist/domains/comet-native/native-hook-guard.js +154 -0
- package/dist/domains/comet-native/native-hook-guard.js.map +1 -0
- package/dist/domains/comet-native/native-lock.d.ts +47 -0
- package/dist/domains/comet-native/native-lock.d.ts.map +1 -0
- package/dist/domains/comet-native/native-lock.js +395 -0
- package/dist/domains/comet-native/native-lock.js.map +1 -0
- package/dist/domains/comet-native/native-mutation-lock.d.ts +5 -0
- package/dist/domains/comet-native/native-mutation-lock.d.ts.map +1 -0
- package/dist/domains/comet-native/native-mutation-lock.js +66 -0
- package/dist/domains/comet-native/native-mutation-lock.js.map +1 -0
- package/dist/domains/comet-native/native-paths.d.ts +10 -0
- package/dist/domains/comet-native/native-paths.d.ts.map +1 -0
- package/dist/domains/comet-native/native-paths.js +171 -0
- package/dist/domains/comet-native/native-paths.js.map +1 -0
- package/dist/domains/comet-native/native-progress-checkpoint.d.ts +13 -0
- package/dist/domains/comet-native/native-progress-checkpoint.d.ts.map +1 -0
- package/dist/domains/comet-native/native-progress-checkpoint.js +104 -0
- package/dist/domains/comet-native/native-progress-checkpoint.js.map +1 -0
- package/dist/domains/comet-native/native-protected-file.d.ts +113 -0
- package/dist/domains/comet-native/native-protected-file.d.ts.map +1 -0
- package/dist/domains/comet-native/native-protected-file.js +509 -0
- package/dist/domains/comet-native/native-protected-file.js.map +1 -0
- package/dist/domains/comet-native/native-redaction.d.ts +2 -0
- package/dist/domains/comet-native/native-redaction.d.ts.map +1 -0
- package/dist/domains/comet-native/native-redaction.js +18 -0
- package/dist/domains/comet-native/native-redaction.js.map +1 -0
- package/dist/domains/comet-native/native-repair-integration.d.ts +42 -0
- package/dist/domains/comet-native/native-repair-integration.d.ts.map +1 -0
- package/dist/domains/comet-native/native-repair-integration.js +184 -0
- package/dist/domains/comet-native/native-repair-integration.js.map +1 -0
- package/dist/domains/comet-native/native-repair-runtime.d.ts +73 -0
- package/dist/domains/comet-native/native-repair-runtime.d.ts.map +1 -0
- package/dist/domains/comet-native/native-repair-runtime.js +509 -0
- package/dist/domains/comet-native/native-repair-runtime.js.map +1 -0
- package/dist/domains/comet-native/native-repair-stagnation.d.ts +85 -0
- package/dist/domains/comet-native/native-repair-stagnation.d.ts.map +1 -0
- package/dist/domains/comet-native/native-repair-stagnation.js +256 -0
- package/dist/domains/comet-native/native-repair-stagnation.js.map +1 -0
- package/dist/domains/comet-native/native-resume-view.d.ts +14 -0
- package/dist/domains/comet-native/native-resume-view.d.ts.map +1 -0
- package/dist/domains/comet-native/native-resume-view.js +105 -0
- package/dist/domains/comet-native/native-resume-view.js.map +1 -0
- package/dist/domains/comet-native/native-revision.d.ts +20 -0
- package/dist/domains/comet-native/native-revision.d.ts.map +1 -0
- package/dist/domains/comet-native/native-revision.js +32 -0
- package/dist/domains/comet-native/native-revision.js.map +1 -0
- package/dist/domains/comet-native/native-root-move.d.ts +20 -0
- package/dist/domains/comet-native/native-root-move.d.ts.map +1 -0
- package/dist/domains/comet-native/native-root-move.js +812 -0
- package/dist/domains/comet-native/native-root-move.js.map +1 -0
- package/dist/domains/comet-native/native-run-consistency.d.ts +3 -0
- package/dist/domains/comet-native/native-run-consistency.d.ts.map +1 -0
- package/dist/domains/comet-native/native-run-consistency.js +136 -0
- package/dist/domains/comet-native/native-run-consistency.js.map +1 -0
- package/dist/domains/comet-native/native-run-store.d.ts +41 -0
- package/dist/domains/comet-native/native-run-store.d.ts.map +1 -0
- package/dist/domains/comet-native/native-run-store.js +451 -0
- package/dist/domains/comet-native/native-run-store.js.map +1 -0
- package/dist/domains/comet-native/native-runtime-package.d.ts +16 -0
- package/dist/domains/comet-native/native-runtime-package.d.ts.map +1 -0
- package/dist/domains/comet-native/native-runtime-package.js +72 -0
- package/dist/domains/comet-native/native-runtime-package.js.map +1 -0
- package/dist/domains/comet-native/native-schema-migration.d.ts +11 -0
- package/dist/domains/comet-native/native-schema-migration.d.ts.map +1 -0
- package/dist/domains/comet-native/native-schema-migration.js +899 -0
- package/dist/domains/comet-native/native-schema-migration.js.map +1 -0
- package/dist/domains/comet-native/native-selection.d.ts +12 -0
- package/dist/domains/comet-native/native-selection.d.ts.map +1 -0
- package/dist/domains/comet-native/native-selection.js +52 -0
- package/dist/domains/comet-native/native-selection.js.map +1 -0
- package/dist/domains/comet-native/native-sensitive-paths.d.ts +7 -0
- package/dist/domains/comet-native/native-sensitive-paths.d.ts.map +1 -0
- package/dist/domains/comet-native/native-sensitive-paths.js +69 -0
- package/dist/domains/comet-native/native-sensitive-paths.js.map +1 -0
- package/dist/domains/comet-native/native-snapshot.d.ts +74 -0
- package/dist/domains/comet-native/native-snapshot.d.ts.map +1 -0
- package/dist/domains/comet-native/native-snapshot.js +2308 -0
- package/dist/domains/comet-native/native-snapshot.js.map +1 -0
- package/dist/domains/comet-native/native-specs.d.ts +12 -0
- package/dist/domains/comet-native/native-specs.d.ts.map +1 -0
- package/dist/domains/comet-native/native-specs.js +270 -0
- package/dist/domains/comet-native/native-specs.js.map +1 -0
- package/dist/domains/comet-native/native-trajectory-limits.d.ts +7 -0
- package/dist/domains/comet-native/native-trajectory-limits.d.ts.map +1 -0
- package/dist/domains/comet-native/native-trajectory-limits.js +13 -0
- package/dist/domains/comet-native/native-trajectory-limits.js.map +1 -0
- package/dist/domains/comet-native/native-trajectory-recovery.d.ts +37 -0
- package/dist/domains/comet-native/native-trajectory-recovery.d.ts.map +1 -0
- package/dist/domains/comet-native/native-trajectory-recovery.js +133 -0
- package/dist/domains/comet-native/native-trajectory-recovery.js.map +1 -0
- package/dist/domains/comet-native/native-trajectory.d.ts +16 -0
- package/dist/domains/comet-native/native-trajectory.d.ts.map +1 -0
- package/dist/domains/comet-native/native-trajectory.js +27 -0
- package/dist/domains/comet-native/native-trajectory.js.map +1 -0
- package/dist/domains/comet-native/native-transaction.d.ts +45 -0
- package/dist/domains/comet-native/native-transaction.d.ts.map +1 -0
- package/dist/domains/comet-native/native-transaction.js +846 -0
- package/dist/domains/comet-native/native-transaction.js.map +1 -0
- package/dist/domains/comet-native/native-transition-evidence.d.ts +4 -0
- package/dist/domains/comet-native/native-transition-evidence.d.ts.map +1 -0
- package/dist/domains/comet-native/native-transition-evidence.js +20 -0
- package/dist/domains/comet-native/native-transition-evidence.js.map +1 -0
- package/dist/domains/comet-native/native-transition-journal.d.ts +30 -0
- package/dist/domains/comet-native/native-transition-journal.d.ts.map +1 -0
- package/dist/domains/comet-native/native-transition-journal.js +819 -0
- package/dist/domains/comet-native/native-transition-journal.js.map +1 -0
- package/dist/domains/comet-native/native-transitions.d.ts +13 -0
- package/dist/domains/comet-native/native-transitions.d.ts.map +1 -0
- package/dist/domains/comet-native/native-transitions.js +632 -0
- package/dist/domains/comet-native/native-transitions.js.map +1 -0
- package/dist/domains/comet-native/native-types.d.ts +547 -0
- package/dist/domains/comet-native/native-types.d.ts.map +1 -0
- package/dist/domains/comet-native/native-types.js +8 -0
- package/dist/domains/comet-native/native-types.js.map +1 -0
- package/dist/domains/comet-native/native-verification-evidence.d.ts +86 -0
- package/dist/domains/comet-native/native-verification-evidence.d.ts.map +1 -0
- package/dist/domains/comet-native/native-verification-evidence.js +480 -0
- package/dist/domains/comet-native/native-verification-evidence.js.map +1 -0
- package/dist/domains/comet-native/native-verification-runtime.d.ts +58 -0
- package/dist/domains/comet-native/native-verification-runtime.d.ts.map +1 -0
- package/dist/domains/comet-native/native-verification-runtime.js +321 -0
- package/dist/domains/comet-native/native-verification-runtime.js.map +1 -0
- package/dist/domains/comet-native/native-verification-scope.d.ts +117 -0
- package/dist/domains/comet-native/native-verification-scope.d.ts.map +1 -0
- package/dist/domains/comet-native/native-verification-scope.js +1040 -0
- package/dist/domains/comet-native/native-verification-scope.js.map +1 -0
- package/dist/domains/comet-native/native-workspace.d.ts +46 -0
- package/dist/domains/comet-native/native-workspace.d.ts.map +1 -0
- package/dist/domains/comet-native/native-workspace.js +276 -0
- package/dist/domains/comet-native/native-workspace.js.map +1 -0
- package/dist/domains/dashboard/collector.d.ts.map +1 -1
- package/dist/domains/dashboard/collector.js +9 -1
- package/dist/domains/dashboard/collector.js.map +1 -1
- package/dist/domains/dashboard/native-adapter.d.ts +157 -0
- package/dist/domains/dashboard/native-adapter.d.ts.map +1 -0
- package/dist/domains/dashboard/native-adapter.js +302 -0
- package/dist/domains/dashboard/native-adapter.js.map +1 -0
- package/dist/domains/dashboard/native-collector.d.ts +6 -0
- package/dist/domains/dashboard/native-collector.d.ts.map +1 -0
- package/dist/domains/dashboard/native-collector.js +285 -0
- package/dist/domains/dashboard/native-collector.js.map +1 -0
- package/dist/domains/dashboard/types.d.ts +5 -0
- package/dist/domains/dashboard/types.d.ts.map +1 -1
- package/dist/domains/dashboard/web/assets/{arc-TGVUG2WN.js → arc-CxdiLJ50.js} +1 -1
- package/dist/domains/dashboard/web/assets/{architectureDiagram-3BPJPVTR-ASHmiHoP.js → architectureDiagram-3BPJPVTR-D5YCQu4e.js} +1 -1
- package/dist/domains/dashboard/web/assets/{blockDiagram-GPEHLZMM-CwASxBKe.js → blockDiagram-GPEHLZMM-8NfdCOQ8.js} +1 -1
- package/dist/domains/dashboard/web/assets/{c4Diagram-AAUBKEIU-BU8z_WNk.js → c4Diagram-AAUBKEIU-B3cFnNT7.js} +1 -1
- package/dist/domains/dashboard/web/assets/channel-B6AFly29.js +1 -0
- package/dist/domains/dashboard/web/assets/{chunk-2J33WTMH-CBGlUx4_.js → chunk-2J33WTMH-CBNfW-Dr.js} +1 -1
- package/dist/domains/dashboard/web/assets/{chunk-4BX2VUAB-CS-iGcFz.js → chunk-4BX2VUAB-vWyemRBr.js} +1 -1
- package/dist/domains/dashboard/web/assets/{chunk-55IACEB6-BUtCVJat.js → chunk-55IACEB6-H6haOo2C.js} +1 -1
- package/dist/domains/dashboard/web/assets/{chunk-727SXJPM-C94tj_pf.js → chunk-727SXJPM-D02UjGND.js} +1 -1
- package/dist/domains/dashboard/web/assets/{chunk-AQP2D5EJ-BFOKcpdG.js → chunk-AQP2D5EJ-wKsbOw_T.js} +1 -1
- package/dist/domains/dashboard/web/assets/{chunk-FMBD7UC4-Dmx8B-st.js → chunk-FMBD7UC4-eYFEZimP.js} +1 -1
- package/dist/domains/dashboard/web/assets/{chunk-ND2GUHAM-DYV00CNn.js → chunk-ND2GUHAM-fMaIDDI2.js} +1 -1
- package/dist/domains/dashboard/web/assets/{chunk-QZHKN3VN-DMJJyQnw.js → chunk-QZHKN3VN-C9rhF6Hm.js} +1 -1
- package/dist/domains/dashboard/web/assets/classDiagram-4FO5ZUOK-BcnrxOTt.js +1 -0
- package/dist/domains/dashboard/web/assets/classDiagram-v2-Q7XG4LA2-BcnrxOTt.js +1 -0
- package/dist/domains/dashboard/web/assets/{cose-bilkent-S5V4N54A-P4nE2rea.js → cose-bilkent-S5V4N54A-CbaShPub.js} +1 -1
- package/dist/domains/dashboard/web/assets/{cynefin-VYW2F7L2-C-R1HXDv.js → cynefin-VYW2F7L2-DN4emAQv.js} +1 -1
- package/dist/domains/dashboard/web/assets/{dagre-BM42HDAG-BH8d-C9z.js → dagre-BM42HDAG-BpSzbk_V.js} +1 -1
- package/dist/domains/dashboard/web/assets/demo-BuVau32v.js +25 -0
- package/dist/domains/dashboard/web/assets/{diagram-2AECGRRQ-DpXTgQIH.js → diagram-2AECGRRQ-CfXwGGpQ.js} +1 -1
- package/dist/domains/dashboard/web/assets/{diagram-5GNKFQAL-DSiFJzSw.js → diagram-5GNKFQAL-DMp0Zmot.js} +1 -1
- package/dist/domains/dashboard/web/assets/{diagram-KO2AKTUF-DULMkben.js → diagram-KO2AKTUF-C7ZvofsM.js} +1 -1
- package/dist/domains/dashboard/web/assets/{diagram-LMA3HP47-Pi8m_NO9.js → diagram-LMA3HP47-BjmxFnap.js} +1 -1
- package/dist/domains/dashboard/web/assets/{diagram-OG6HWLK6-BSe6bCWm.js → diagram-OG6HWLK6-DFBG1Iqy.js} +1 -1
- package/dist/domains/dashboard/web/assets/{erDiagram-TEJ5UH35-zb-FEcbq.js → erDiagram-TEJ5UH35-MpNT7dzt.js} +1 -1
- package/dist/domains/dashboard/web/assets/{flowDiagram-I6XJVG4X-Dr-Gk0z2.js → flowDiagram-I6XJVG4X-_1wAR6c1.js} +1 -1
- package/dist/domains/dashboard/web/assets/{ganttDiagram-6RSMTGT7-qs6Zb2A6.js → ganttDiagram-6RSMTGT7-DJKjDeWl.js} +1 -1
- package/dist/domains/dashboard/web/assets/{gitGraphDiagram-PVQCEYII-BQ314orT.js → gitGraphDiagram-PVQCEYII-BL7yUEn-.js} +1 -1
- package/dist/domains/dashboard/web/assets/index-CjE9mHGb.js +24 -0
- package/dist/domains/dashboard/web/assets/index-D-AGxvI4.css +1 -0
- package/dist/domains/dashboard/web/assets/{infoDiagram-5YYISTIA-O0bQp98A.js → infoDiagram-5YYISTIA-Bt5fqrOd.js} +1 -1
- package/dist/domains/dashboard/web/assets/{ishikawaDiagram-YF4QCWOH-BPC7wbKh.js → ishikawaDiagram-YF4QCWOH-COCMcjBM.js} +1 -1
- package/dist/domains/dashboard/web/assets/{journeyDiagram-JHISSGLW-ohViOd4b.js → journeyDiagram-JHISSGLW-DGcpcWny.js} +1 -1
- package/dist/domains/dashboard/web/assets/{kanban-definition-UN3LZRKU-CHleNdbG.js → kanban-definition-UN3LZRKU-QSBNsWMP.js} +1 -1
- package/dist/domains/dashboard/web/assets/{linear-CyqiW--Q.js → linear-9uyeeBZf.js} +1 -1
- package/dist/domains/dashboard/web/assets/{mermaid.core-qS9XvtaK.js → mermaid.core-CkNdB471.js} +4 -4
- package/dist/domains/dashboard/web/assets/{mindmap-definition-RKZ34NQL-oaGkqO9l.js → mindmap-definition-RKZ34NQL-CiNxI0gP.js} +1 -1
- package/dist/domains/dashboard/web/assets/{pieDiagram-4H26LBE5-CPcB-AFh.js → pieDiagram-4H26LBE5-BLJ6QnRO.js} +1 -1
- package/dist/domains/dashboard/web/assets/{quadrantDiagram-W4KKPZXB-LFy52Qtj.js → quadrantDiagram-W4KKPZXB-CflW-eFH.js} +1 -1
- package/dist/domains/dashboard/web/assets/{requirementDiagram-4Y6WPE33-BdjeaYP_.js → requirementDiagram-4Y6WPE33-B9HLmRWH.js} +1 -1
- package/dist/domains/dashboard/web/assets/{sankeyDiagram-5OEKKPKP-DDJ4styL.js → sankeyDiagram-5OEKKPKP-6xnco5k5.js} +1 -1
- package/dist/domains/dashboard/web/assets/{sequenceDiagram-3UESZ5HK-BL5bFNoz.js → sequenceDiagram-3UESZ5HK-Dp1rujNZ.js} +1 -1
- package/dist/domains/dashboard/web/assets/{stateDiagram-AJRCARHV-BNUfikui.js → stateDiagram-AJRCARHV-C1Xc90ek.js} +1 -1
- package/dist/domains/dashboard/web/assets/stateDiagram-v2-BHNVJYJU-p-qmzXyE.js +1 -0
- package/dist/domains/dashboard/web/assets/{timeline-definition-PNZ67QCA--ps2uu6L.js → timeline-definition-PNZ67QCA-g9s-m5Z4.js} +1 -1
- package/dist/domains/dashboard/web/assets/{vennDiagram-CIIHVFJN-C2q8q26c.js → vennDiagram-CIIHVFJN-rkEyhyCc.js} +1 -1
- package/dist/domains/dashboard/web/assets/{wardleyDiagram-YWT4CUSO-BUH9gXqd.js → wardleyDiagram-YWT4CUSO-CJLrWGXc.js} +1 -1
- package/dist/domains/dashboard/web/assets/{xychartDiagram-2RQKCTM6-B-DielEy.js → xychartDiagram-2RQKCTM6-BxJvPNqo.js} +1 -1
- package/dist/domains/dashboard/web/index.html +2 -2
- package/dist/domains/engine/storage-layout.d.ts +14 -0
- package/dist/domains/engine/storage-layout.d.ts.map +1 -0
- package/dist/domains/engine/storage-layout.js +32 -0
- package/dist/domains/engine/storage-layout.js.map +1 -0
- package/dist/domains/engine/storage-run.d.ts +9 -0
- package/dist/domains/engine/storage-run.d.ts.map +1 -0
- package/dist/domains/engine/storage-run.js +116 -0
- package/dist/domains/engine/storage-run.js.map +1 -0
- package/dist/domains/factory/package.d.ts.map +1 -1
- package/dist/domains/factory/package.js +5 -3
- package/dist/domains/factory/package.js.map +1 -1
- package/dist/domains/integrations/openspec.d.ts.map +1 -1
- package/dist/domains/integrations/openspec.js +8 -6
- package/dist/domains/integrations/openspec.js.map +1 -1
- package/dist/domains/skill/platform-inspect.d.ts +6 -2
- package/dist/domains/skill/platform-inspect.d.ts.map +1 -1
- package/dist/domains/skill/platform-inspect.js +52 -8
- package/dist/domains/skill/platform-inspect.js.map +1 -1
- package/dist/domains/skill/platform-install.d.ts +18 -7
- package/dist/domains/skill/platform-install.d.ts.map +1 -1
- package/dist/domains/skill/platform-install.js +338 -71
- package/dist/domains/skill/platform-install.js.map +1 -1
- package/dist/domains/skill/project-instructions.d.ts.map +1 -1
- package/dist/domains/skill/project-instructions.js +12 -6
- package/dist/domains/skill/project-instructions.js.map +1 -1
- package/dist/domains/skill/uninstall.d.ts.map +1 -1
- package/dist/domains/skill/uninstall.js +15 -3
- package/dist/domains/skill/uninstall.js.map +1 -1
- package/dist/domains/workflow-contract/builtins.d.ts +6 -0
- package/dist/domains/workflow-contract/builtins.d.ts.map +1 -1
- package/dist/domains/workflow-contract/builtins.js +137 -0
- package/dist/domains/workflow-contract/builtins.js.map +1 -1
- package/dist/domains/workflow-contract/index.d.ts +3 -1
- package/dist/domains/workflow-contract/index.d.ts.map +1 -1
- package/dist/domains/workflow-contract/index.js +2 -1
- package/dist/domains/workflow-contract/index.js.map +1 -1
- package/dist/domains/workflow-contract/normalize.d.ts.map +1 -1
- package/dist/domains/workflow-contract/normalize.js +28 -10
- package/dist/domains/workflow-contract/normalize.js.map +1 -1
- package/dist/domains/workflow-contract/project-config.d.ts +7 -0
- package/dist/domains/workflow-contract/project-config.d.ts.map +1 -0
- package/dist/domains/workflow-contract/project-config.js +110 -0
- package/dist/domains/workflow-contract/project-config.js.map +1 -0
- package/dist/domains/workflow-contract/types.d.ts +4 -2
- package/dist/domains/workflow-contract/types.d.ts.map +1 -1
- package/dist/domains/workflow-contract/validation.d.ts.map +1 -1
- package/dist/domains/workflow-contract/validation.js +14 -5
- package/dist/domains/workflow-contract/validation.js.map +1 -1
- package/dist/platform/install/detect.d.ts +3 -1
- package/dist/platform/install/detect.d.ts.map +1 -1
- package/dist/platform/install/detect.js +4 -1
- package/dist/platform/install/detect.js.map +1 -1
- package/dist/platform/install/project-registry.js +2 -2
- package/dist/platform/install/project-registry.js.map +1 -1
- package/dist/platform/paths/repository-layout.d.ts +16 -0
- package/dist/platform/paths/repository-layout.d.ts.map +1 -1
- package/dist/platform/paths/repository-layout.js.map +1 -1
- package/eval/local/README.md +50 -0
- package/eval/local/scripts/compare_baselines.py +127 -1
- package/eval/local/scripts/regression_check.py +3 -4
- package/eval/local/tasks/comet-native-clarification/environment/Dockerfile +27 -0
- package/eval/local/tasks/comet-native-clarification/environment/test_wordcount.py +25 -0
- package/eval/local/tasks/comet-native-clarification/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-clarification/instruction.md +7 -0
- package/eval/local/tasks/comet-native-clarification/task.toml +40 -0
- package/eval/local/tasks/comet-native-clarification/validation/test_native_clarification.py +193 -0
- package/eval/local/tasks/comet-native-clarification-modes/environment/Dockerfile +27 -0
- package/eval/local/tasks/comet-native-clarification-modes/environment/test_wordcount.py +25 -0
- package/eval/local/tasks/comet-native-clarification-modes/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-clarification-modes/instruction.md +13 -0
- package/eval/local/tasks/comet-native-clarification-modes/task.toml +39 -0
- package/eval/local/tasks/comet-native-clarification-modes/validation/test_native_clarification_modes.py +235 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/.comet/config.yaml +6 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/Dockerfile +28 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/docs/comet/changes/add-character-counting/brief.md +17 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/docs/comet/changes/add-character-counting/comet-state.yaml +12 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/docs/comet/changes/add-character-counting/runtime/transition.json +69 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/docs/comet/changes/add-character-counting/specs/character-counting/spec.md +3 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/test_wordcount.py +20 -0
- package/eval/local/tasks/comet-native-interrupted-transition/environment/wordcount.py +27 -0
- package/eval/local/tasks/comet-native-interrupted-transition/instruction.md +7 -0
- package/eval/local/tasks/comet-native-interrupted-transition/task.toml +35 -0
- package/eval/local/tasks/comet-native-interrupted-transition/validation/test_native_interrupted_transition.py +63 -0
- package/eval/local/tasks/comet-native-repository-fact/environment/Dockerfile +26 -0
- package/eval/local/tasks/comet-native-repository-fact/environment/PRODUCT_RULES.md +3 -0
- package/eval/local/tasks/comet-native-repository-fact/environment/test_wordcount.py +20 -0
- package/eval/local/tasks/comet-native-repository-fact/environment/wordcount.py +27 -0
- package/eval/local/tasks/comet-native-repository-fact/instruction.md +7 -0
- package/eval/local/tasks/comet-native-repository-fact/task.toml +35 -0
- package/eval/local/tasks/comet-native-repository-fact/validation/test_native_repository_fact.py +53 -0
- package/eval/local/tasks/comet-native-wave-b-decision-resume/environment/Dockerfile +27 -0
- package/eval/local/tasks/comet-native-wave-b-decision-resume/environment/test_wordcount.py +27 -0
- package/eval/local/tasks/comet-native-wave-b-decision-resume/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-wave-b-decision-resume/instruction.md +9 -0
- package/eval/local/tasks/comet-native-wave-b-decision-resume/task.toml +40 -0
- package/eval/local/tasks/comet-native-wave-b-decision-resume/validation/test_native_wave_b_decision_resume.py +208 -0
- package/eval/local/tasks/comet-native-wave-c-verification-integrity/environment/Dockerfile +27 -0
- package/eval/local/tasks/comet-native-wave-c-verification-integrity/environment/test_wordcount.py +27 -0
- package/eval/local/tasks/comet-native-wave-c-verification-integrity/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-wave-c-verification-integrity/instruction.md +11 -0
- package/eval/local/tasks/comet-native-wave-c-verification-integrity/task.toml +36 -0
- package/eval/local/tasks/comet-native-wave-c-verification-integrity/validation/test_native_wave_c_verification_integrity.py +344 -0
- package/eval/local/tasks/comet-native-wave-d-stagnation-stop/environment/Dockerfile +27 -0
- package/eval/local/tasks/comet-native-wave-d-stagnation-stop/environment/test_wordcount.py +27 -0
- package/eval/local/tasks/comet-native-wave-d-stagnation-stop/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-wave-d-stagnation-stop/instruction.md +11 -0
- package/eval/local/tasks/comet-native-wave-d-stagnation-stop/task.toml +37 -0
- package/eval/local/tasks/comet-native-wave-d-stagnation-stop/validation/test_native_wave_d_stagnation_stop.py +284 -0
- package/eval/local/tasks/comet-native-wave-e-parallel-safety/environment/.include-trusted-native-runtime +1 -0
- package/eval/local/tasks/comet-native-wave-e-parallel-safety/environment/Dockerfile +27 -0
- package/eval/local/tasks/comet-native-wave-e-parallel-safety/environment/test_wordcount.py +27 -0
- package/eval/local/tasks/comet-native-wave-e-parallel-safety/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-wave-e-parallel-safety/instruction.md +9 -0
- package/eval/local/tasks/comet-native-wave-e-parallel-safety/task.toml +37 -0
- package/eval/local/tasks/comet-native-wave-e-parallel-safety/validation/test_native_wave_e_parallel_safety.py +309 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/environment/.include-current-comet-cli +1 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/environment/Dockerfile +31 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/environment/current-comet-package.json +18 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/environment/current-comet.sh +14 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/environment/test_wordcount.py +27 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/instruction.md +7 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/task.toml +36 -0
- package/eval/local/tasks/comet-native-wave-f-dashboard-readonly/validation/test_native_wave_f_dashboard_readonly.py +469 -0
- package/eval/local/tasks/comet-native-workflow/environment/Dockerfile +27 -0
- package/eval/local/tasks/comet-native-workflow/environment/test_wordcount.py +25 -0
- package/eval/local/tasks/comet-native-workflow/environment/wordcount.py +36 -0
- package/eval/local/tasks/comet-native-workflow/instruction.md +14 -0
- package/eval/local/tasks/comet-native-workflow/task.toml +36 -0
- package/eval/local/tasks/comet-native-workflow/validation/test_native_workflow.py +149 -0
- package/eval/local/tasks/index.yaml +61 -0
- package/eval/local/tests/conftest.py +407 -22
- package/eval/local/tests/scaffold/test_aligned_comparison.py +1012 -0
- package/eval/local/tests/scaffold/test_conftest_helpers.py +187 -7
- package/eval/local/tests/scaffold/test_logging.py +135 -1
- package/eval/local/tests/scaffold/test_manifests.py +2 -0
- package/eval/local/tests/scaffold/test_native_aligned_eval.py +346 -0
- package/eval/local/tests/scaffold/test_native_wave_evaluations.py +1889 -0
- package/eval/local/tests/scaffold/test_profiles.py +33 -0
- package/eval/local/tests/scaffold/test_sample_quality.py +57 -0
- package/eval/local/tests/scaffold/test_tasks.py +377 -1
- package/eval/local/tests/scaffold/test_treatments.py +59 -13
- package/eval/local/tests/scaffold/test_utils.py +277 -4
- package/eval/local/tests/tasks/__init__.py +1 -0
- package/eval/local/tests/tasks/test_tasks.py +104 -78
- package/eval/local/tests/tasks/test_validation_scripts.py +37 -0
- package/eval/local/treatments/comet/comet_native_phase1.yaml +66 -0
- package/eval/scaffold/python/aligned_comparison.py +1631 -0
- package/eval/scaffold/python/generic_llm_judge.py +3 -1
- package/eval/scaffold/python/llm_judge.py +0 -3
- package/eval/scaffold/python/logging.py +115 -16
- package/eval/scaffold/python/manifests.py +2 -0
- package/eval/scaffold/python/native_eval.py +138 -0
- package/eval/scaffold/python/pass_at_k.py +0 -1
- package/eval/scaffold/python/report_outputs.py +226 -44
- package/eval/scaffold/python/sample_quality.py +45 -2
- package/eval/scaffold/python/tasks.py +11 -0
- package/eval/scaffold/python/utils.py +108 -20
- package/eval/scaffold/python/validation/__init__.py +15 -5
- package/eval/scaffold/python/validation/comet_workflow.py +10 -5
- package/eval/scaffold/python/validation/generic_rubric.py +1 -2
- package/eval/scaffold/python/validation/native_wave.py +2154 -0
- package/eval/scaffold/python/validation/native_workflow.py +252 -0
- package/eval/scaffold/python/validation/rubric.py +0 -2
- package/eval/scaffold/shell/completion-point.sh +18 -0
- package/eval/scaffold/shell/decision-point.sh +35 -0
- package/eval/scaffold/shell/docker.sh +150 -9
- package/eval/scaffold/shell/run-claude-loop.sh +57 -27
- package/package.json +19 -5
- package/dist/domains/dashboard/web/assets/channel-kp6Ng2JJ.js +0 -1
- package/dist/domains/dashboard/web/assets/classDiagram-4FO5ZUOK-yBDjgMY_.js +0 -1
- package/dist/domains/dashboard/web/assets/classDiagram-v2-Q7XG4LA2-yBDjgMY_.js +0 -1
- package/dist/domains/dashboard/web/assets/demo-DQyfozbi.js +0 -1
- package/dist/domains/dashboard/web/assets/index-BLAfkNTu.css +0 -1
- package/dist/domains/dashboard/web/assets/index-DtLUOcAW.js +0 -24
- package/dist/domains/dashboard/web/assets/stateDiagram-v2-BHNVJYJU-DGrsmWts.js +0 -1
- package/eval/.env.example +0 -52
- package/eval/langsmith/.env.example +0 -16
|
@@ -0,0 +1,1181 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { atomicWriteJson } from './native-atomic-file.js';
|
|
4
|
+
import { inspectNativeArchiveContent, } from './native-archive-content.js';
|
|
5
|
+
import { resolveContainedNativePath } from './native-paths.js';
|
|
6
|
+
import { captureNativeProtectedDirectoryGuard, copyNativeProtectedFile, ensureNativeProtectedDirectory, readNativeProtectedFile, } from './native-protected-file.js';
|
|
7
|
+
import { appendNativeTransactionEvent, nativeTransactionPaths, parseNativeArchiveTransactionJournalV2, readNativeTransactionEvents, resolveNativeTransactionPaths, } from './native-transaction.js';
|
|
8
|
+
const NATIVE_ARCHIVE_COPY_MAX_BYTES = 16 * 1024 * 1024;
|
|
9
|
+
const NATIVE_ARCHIVE_JOURNAL_MAX_BYTES = 256 * 1024;
|
|
10
|
+
const NATIVE_ARCHIVE_CAS_RECORD_MAX_BYTES = 16 * 1024;
|
|
11
|
+
const NATIVE_ARCHIVE_CAS_SCHEMA = 'comet.native.archive-cas.v1';
|
|
12
|
+
function resolveRefLexically(paths, ref) {
|
|
13
|
+
const target = path.resolve(paths.nativeRoot, ...ref.split('/'));
|
|
14
|
+
if (path.relative(paths.nativeRoot, target).split(path.sep).includes('..')) {
|
|
15
|
+
throw new Error(`Unsafe Native Archive transaction ref: ${ref}`);
|
|
16
|
+
}
|
|
17
|
+
return target;
|
|
18
|
+
}
|
|
19
|
+
async function resolveRef(paths, ref) {
|
|
20
|
+
return resolveContainedNativePath(paths.nativeRoot, resolveRefLexically(paths, ref));
|
|
21
|
+
}
|
|
22
|
+
function sameContent(actual, expectedHash, expectedKind = 'file') {
|
|
23
|
+
return expectedHash === null
|
|
24
|
+
? actual === null
|
|
25
|
+
: actual?.kind === expectedKind && actual.hash === expectedHash;
|
|
26
|
+
}
|
|
27
|
+
function contentDescription(value) {
|
|
28
|
+
return value === null ? 'missing' : `${value.kind}:${value.hash}`;
|
|
29
|
+
}
|
|
30
|
+
async function assertContent(options) {
|
|
31
|
+
const actual = await inspectNativeArchiveContent(options.target);
|
|
32
|
+
if (!sameContent(actual, options.expectedHash, options.expectedKind)) {
|
|
33
|
+
throw new Error(`${options.label} content changed: expected ${options.expectedHash ?? 'missing'}, got ${contentDescription(actual)}`);
|
|
34
|
+
}
|
|
35
|
+
return actual;
|
|
36
|
+
}
|
|
37
|
+
export async function createNativeArchiveTransactionV2(paths, journal) {
|
|
38
|
+
const validated = parseNativeArchiveTransactionJournalV2(journal);
|
|
39
|
+
const tx = await resolveNativeTransactionPaths(paths, validated.id);
|
|
40
|
+
await fs.mkdir(tx.staged, { recursive: true });
|
|
41
|
+
await fs.mkdir(tx.backups, { recursive: true });
|
|
42
|
+
await atomicWriteJson(tx.journal, validated, { containedRoot: paths.nativeRoot });
|
|
43
|
+
await appendNativeTransactionEvent(paths, validated.id, 'prepared');
|
|
44
|
+
}
|
|
45
|
+
export async function readNativeArchiveTransactionV2(paths, id) {
|
|
46
|
+
const tx = await resolveNativeTransactionPaths(paths, id);
|
|
47
|
+
const snapshot = await readNativeProtectedFile({
|
|
48
|
+
root: paths.nativeRoot,
|
|
49
|
+
file: tx.journal,
|
|
50
|
+
maxBytes: NATIVE_ARCHIVE_JOURNAL_MAX_BYTES,
|
|
51
|
+
label: `Native Archive transaction journal ${id}`,
|
|
52
|
+
});
|
|
53
|
+
const journal = parseNativeArchiveTransactionJournalV2(JSON.parse(snapshot.bytes.toString('utf8')));
|
|
54
|
+
if (journal.id !== id)
|
|
55
|
+
throw new Error(`Invalid Native Archive transaction journal: ${id}`);
|
|
56
|
+
return journal;
|
|
57
|
+
}
|
|
58
|
+
async function setStatus(paths, journal, status) {
|
|
59
|
+
const updated = parseNativeArchiveTransactionJournalV2({ ...journal, status });
|
|
60
|
+
const tx = await resolveNativeTransactionPaths(paths, updated.id);
|
|
61
|
+
await atomicWriteJson(tx.journal, updated, { containedRoot: paths.nativeRoot });
|
|
62
|
+
return updated;
|
|
63
|
+
}
|
|
64
|
+
function fileObjectIdentity(stat) {
|
|
65
|
+
return {
|
|
66
|
+
dev: stat.dev,
|
|
67
|
+
ino: stat.ino,
|
|
68
|
+
birthtimeMs: stat.birthtimeMs,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function fileVersion(stat) {
|
|
72
|
+
return {
|
|
73
|
+
...fileObjectIdentity(stat),
|
|
74
|
+
ctimeMs: stat.ctimeMs,
|
|
75
|
+
mtimeMs: stat.mtimeMs,
|
|
76
|
+
size: stat.size,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function sameFileObject(expected, actual) {
|
|
80
|
+
if (expected.dev !== 0 || expected.ino !== 0 || actual.dev !== 0 || actual.ino !== 0) {
|
|
81
|
+
return (expected.dev === actual.dev &&
|
|
82
|
+
expected.ino === actual.ino &&
|
|
83
|
+
expected.birthtimeMs === actual.birthtimeMs);
|
|
84
|
+
}
|
|
85
|
+
return expected.birthtimeMs === actual.birthtimeMs;
|
|
86
|
+
}
|
|
87
|
+
function sameFileVersion(expected, actual) {
|
|
88
|
+
return (sameFileObject(expected, actual) &&
|
|
89
|
+
expected.birthtimeMs === actual.birthtimeMs &&
|
|
90
|
+
expected.ctimeMs === actual.ctimeMs &&
|
|
91
|
+
expected.mtimeMs === actual.mtimeMs &&
|
|
92
|
+
expected.size === actual.size);
|
|
93
|
+
}
|
|
94
|
+
async function pathExists(target) {
|
|
95
|
+
try {
|
|
96
|
+
await fs.lstat(target);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (error.code === 'ENOENT')
|
|
101
|
+
return false;
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function captureStableArchiveFile(options) {
|
|
106
|
+
const before = await fs.lstat(options.file);
|
|
107
|
+
if (!before.isFile() || before.isSymbolicLink()) {
|
|
108
|
+
throw new Error(`${options.label} must be a regular file`);
|
|
109
|
+
}
|
|
110
|
+
const beforeVersion = fileVersion(before);
|
|
111
|
+
const snapshot = await readNativeProtectedFile({
|
|
112
|
+
root: options.paths.nativeRoot,
|
|
113
|
+
file: options.file,
|
|
114
|
+
maxBytes: NATIVE_ARCHIVE_COPY_MAX_BYTES,
|
|
115
|
+
label: options.label,
|
|
116
|
+
});
|
|
117
|
+
const after = await fs.lstat(options.file);
|
|
118
|
+
if (!after.isFile() ||
|
|
119
|
+
after.isSymbolicLink() ||
|
|
120
|
+
!sameFileVersion(beforeVersion, fileVersion(after)) ||
|
|
121
|
+
snapshot.hash !== options.expectedHash) {
|
|
122
|
+
throw new Error(`${options.label} content changed or object identity changed while binding`);
|
|
123
|
+
}
|
|
124
|
+
return { identity: fileObjectIdentity(after), size: snapshot.size };
|
|
125
|
+
}
|
|
126
|
+
function parseCasRecord(value, operation, role, expectedHash) {
|
|
127
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
128
|
+
throw new Error(`Archive CAS ${operation.id} ${role} record must be an object`);
|
|
129
|
+
}
|
|
130
|
+
const record = value;
|
|
131
|
+
const keys = Object.keys(record).sort();
|
|
132
|
+
if (keys.join(',') !== 'hash,identity,operationId,role,schema') {
|
|
133
|
+
throw new Error(`Archive CAS ${operation.id} ${role} record has an invalid shape`);
|
|
134
|
+
}
|
|
135
|
+
const identity = record.identity;
|
|
136
|
+
if (!identity || typeof identity !== 'object' || Array.isArray(identity)) {
|
|
137
|
+
throw new Error(`Archive CAS ${operation.id} ${role} identity must be an object`);
|
|
138
|
+
}
|
|
139
|
+
const identityRecord = identity;
|
|
140
|
+
if (Object.keys(identityRecord).sort().join(',') !== 'birthtimeMs,dev,ino') {
|
|
141
|
+
throw new Error(`Archive CAS ${operation.id} ${role} identity has an invalid shape`);
|
|
142
|
+
}
|
|
143
|
+
for (const field of ['dev', 'ino', 'birthtimeMs']) {
|
|
144
|
+
if (typeof identityRecord[field] !== 'number' ||
|
|
145
|
+
!Number.isFinite(identityRecord[field]) ||
|
|
146
|
+
identityRecord[field] < 0) {
|
|
147
|
+
throw new Error(`Archive CAS ${operation.id} ${role} identity ${field} is invalid`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (record.schema !== NATIVE_ARCHIVE_CAS_SCHEMA ||
|
|
151
|
+
record.operationId !== operation.id ||
|
|
152
|
+
record.role !== role ||
|
|
153
|
+
record.hash !== expectedHash) {
|
|
154
|
+
throw new Error(`Archive CAS ${operation.id} ${role} record is not transaction-bound`);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
schema: NATIVE_ARCHIVE_CAS_SCHEMA,
|
|
158
|
+
operationId: operation.id,
|
|
159
|
+
role,
|
|
160
|
+
hash: expectedHash,
|
|
161
|
+
identity: {
|
|
162
|
+
dev: identityRecord.dev,
|
|
163
|
+
ino: identityRecord.ino,
|
|
164
|
+
birthtimeMs: identityRecord.birthtimeMs,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function archiveCasPaths(paths, journal, operation, target) {
|
|
169
|
+
const tx = await resolveNativeTransactionPaths(paths, journal.id);
|
|
170
|
+
const directory = path.join(tx.backups, '.cas');
|
|
171
|
+
const prefix = `.${path.basename(target)}.comet-archive-cas-${journal.id}-${operation.id}`;
|
|
172
|
+
const result = {
|
|
173
|
+
directory,
|
|
174
|
+
originalRecord: path.join(directory, `${operation.id}.original.json`),
|
|
175
|
+
postRecord: path.join(directory, `${operation.id}.post.json`),
|
|
176
|
+
candidate: path.join(directory, `${operation.id}.candidate`),
|
|
177
|
+
originalQuarantine: path.join(path.dirname(target), `${prefix}.original`),
|
|
178
|
+
rollbackQuarantine: path.join(path.dirname(target), `${prefix}.rollback`),
|
|
179
|
+
};
|
|
180
|
+
await Promise.all(Object.values(result).map((item) => resolveContainedNativePath(paths.nativeRoot, item)));
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
async function readCasRecord(options) {
|
|
184
|
+
if (!(await pathExists(options.file)))
|
|
185
|
+
return null;
|
|
186
|
+
const snapshot = await readNativeProtectedFile({
|
|
187
|
+
root: options.paths.nativeRoot,
|
|
188
|
+
file: options.file,
|
|
189
|
+
maxBytes: NATIVE_ARCHIVE_CAS_RECORD_MAX_BYTES,
|
|
190
|
+
label: `Archive CAS ${options.operation.id} ${options.role} record`,
|
|
191
|
+
});
|
|
192
|
+
return parseCasRecord(JSON.parse(snapshot.bytes.toString('utf8')), options.operation, options.role, options.expectedHash);
|
|
193
|
+
}
|
|
194
|
+
async function persistCasRecord(options) {
|
|
195
|
+
const existing = await readCasRecord(options);
|
|
196
|
+
if (existing) {
|
|
197
|
+
if (!sameFileObject(existing.identity, options.identity)) {
|
|
198
|
+
throw new Error(`Archive CAS ${options.operation.id} ${options.role} object identity changed`);
|
|
199
|
+
}
|
|
200
|
+
return existing;
|
|
201
|
+
}
|
|
202
|
+
await ensureNativeProtectedDirectory({
|
|
203
|
+
root: options.paths.nativeRoot,
|
|
204
|
+
directory: path.dirname(options.file),
|
|
205
|
+
label: `Archive CAS ${options.operation.id} records`,
|
|
206
|
+
});
|
|
207
|
+
const record = {
|
|
208
|
+
schema: NATIVE_ARCHIVE_CAS_SCHEMA,
|
|
209
|
+
operationId: options.operation.id,
|
|
210
|
+
role: options.role,
|
|
211
|
+
hash: options.expectedHash,
|
|
212
|
+
identity: options.identity,
|
|
213
|
+
};
|
|
214
|
+
try {
|
|
215
|
+
await atomicWriteJson(options.file, record, {
|
|
216
|
+
containedRoot: options.paths.nativeRoot,
|
|
217
|
+
exclusive: true,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
if (error.code !== 'EEXIST')
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
const persisted = await readCasRecord(options);
|
|
225
|
+
if (!persisted || !sameFileObject(persisted.identity, options.identity)) {
|
|
226
|
+
throw new Error(`Archive CAS ${options.operation.id} ${options.role} record changed`);
|
|
227
|
+
}
|
|
228
|
+
return persisted;
|
|
229
|
+
}
|
|
230
|
+
async function validateFileAgainstCasRecord(options) {
|
|
231
|
+
const current = await captureStableArchiveFile({
|
|
232
|
+
paths: options.paths,
|
|
233
|
+
file: options.file,
|
|
234
|
+
expectedHash: options.record.hash,
|
|
235
|
+
label: options.label,
|
|
236
|
+
});
|
|
237
|
+
if (!sameFileObject(options.record.identity, current.identity)) {
|
|
238
|
+
throw new Error(`${options.label} object identity changed`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async function bindCurrentTarget(options) {
|
|
242
|
+
const current = await captureStableArchiveFile({
|
|
243
|
+
paths: options.paths,
|
|
244
|
+
file: options.file,
|
|
245
|
+
expectedHash: options.expectedHash,
|
|
246
|
+
label: options.label,
|
|
247
|
+
});
|
|
248
|
+
const record = await persistCasRecord({
|
|
249
|
+
paths: options.paths,
|
|
250
|
+
file: options.recordFile,
|
|
251
|
+
operation: options.operation,
|
|
252
|
+
role: options.role,
|
|
253
|
+
expectedHash: options.expectedHash,
|
|
254
|
+
identity: current.identity,
|
|
255
|
+
});
|
|
256
|
+
await validateFileAgainstCasRecord({
|
|
257
|
+
paths: options.paths,
|
|
258
|
+
file: options.file,
|
|
259
|
+
operation: options.operation,
|
|
260
|
+
record,
|
|
261
|
+
label: options.label,
|
|
262
|
+
});
|
|
263
|
+
return record;
|
|
264
|
+
}
|
|
265
|
+
async function restoreUnexpectedQuarantine(options) {
|
|
266
|
+
if (!(await pathExists(options.quarantine)) || (await pathExists(options.target)))
|
|
267
|
+
return;
|
|
268
|
+
const guard = await captureNativeProtectedDirectoryGuard({
|
|
269
|
+
root: options.paths.nativeRoot,
|
|
270
|
+
directory: path.dirname(options.target),
|
|
271
|
+
label: `Archive CAS ${options.operation.id} quarantine restoration`,
|
|
272
|
+
});
|
|
273
|
+
await guard.verify();
|
|
274
|
+
try {
|
|
275
|
+
await fs.link(options.quarantine, options.target);
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
if (error.code === 'EEXIST')
|
|
279
|
+
return;
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
await guard.verify();
|
|
283
|
+
const [quarantine, target] = await Promise.all([
|
|
284
|
+
fs.lstat(options.quarantine),
|
|
285
|
+
fs.lstat(options.target),
|
|
286
|
+
]);
|
|
287
|
+
if (!sameFileObject(fileObjectIdentity(quarantine), fileObjectIdentity(target))) {
|
|
288
|
+
throw new Error(`Archive CAS ${options.operation.id} could not restore quarantined content`);
|
|
289
|
+
}
|
|
290
|
+
await fs.unlink(options.quarantine);
|
|
291
|
+
await guard.verify();
|
|
292
|
+
}
|
|
293
|
+
async function quarantineBoundTarget(options) {
|
|
294
|
+
if (await pathExists(options.quarantine)) {
|
|
295
|
+
await validateFileAgainstCasRecord({
|
|
296
|
+
paths: options.paths,
|
|
297
|
+
file: options.quarantine,
|
|
298
|
+
operation: options.operation,
|
|
299
|
+
record: options.record,
|
|
300
|
+
label: `Archive ${options.phase} quarantine ${options.operation.target}`,
|
|
301
|
+
});
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const guard = await captureNativeProtectedDirectoryGuard({
|
|
305
|
+
root: options.paths.nativeRoot,
|
|
306
|
+
directory: path.dirname(options.target),
|
|
307
|
+
label: `Archive ${options.phase} target ${options.operation.target}`,
|
|
308
|
+
});
|
|
309
|
+
await validateFileAgainstCasRecord({
|
|
310
|
+
paths: options.paths,
|
|
311
|
+
file: options.target,
|
|
312
|
+
operation: options.operation,
|
|
313
|
+
record: options.record,
|
|
314
|
+
label: `Archive ${options.phase} target ${options.operation.target}`,
|
|
315
|
+
});
|
|
316
|
+
await options.hooks?.afterArchiveTargetBound?.(options.phase, options.operation, options.target);
|
|
317
|
+
await guard.verify();
|
|
318
|
+
await validateFileAgainstCasRecord({
|
|
319
|
+
paths: options.paths,
|
|
320
|
+
file: options.target,
|
|
321
|
+
operation: options.operation,
|
|
322
|
+
record: options.record,
|
|
323
|
+
label: `Archive ${options.phase} target ${options.operation.target}`,
|
|
324
|
+
});
|
|
325
|
+
try {
|
|
326
|
+
await fs.rename(options.target, options.quarantine);
|
|
327
|
+
await guard.verify();
|
|
328
|
+
await validateFileAgainstCasRecord({
|
|
329
|
+
paths: options.paths,
|
|
330
|
+
file: options.quarantine,
|
|
331
|
+
operation: options.operation,
|
|
332
|
+
record: options.record,
|
|
333
|
+
label: `Archive ${options.phase} quarantine ${options.operation.target}`,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
await restoreUnexpectedQuarantine(options);
|
|
338
|
+
throw new Error(`Archive ${options.phase} target ${options.operation.target} changed during quarantine`, { cause: error });
|
|
339
|
+
}
|
|
340
|
+
await options.hooks?.afterArchiveTargetQuarantined?.(options.phase, options.operation, options.quarantine);
|
|
341
|
+
}
|
|
342
|
+
async function removeExactCasFile(options) {
|
|
343
|
+
if (!(await pathExists(options.file)))
|
|
344
|
+
return;
|
|
345
|
+
await validateFileAgainstCasRecord(options);
|
|
346
|
+
const guard = await captureNativeProtectedDirectoryGuard({
|
|
347
|
+
root: options.paths.nativeRoot,
|
|
348
|
+
directory: path.dirname(options.file),
|
|
349
|
+
label: options.label,
|
|
350
|
+
});
|
|
351
|
+
await guard.verify();
|
|
352
|
+
await validateFileAgainstCasRecord(options);
|
|
353
|
+
await fs.unlink(options.file);
|
|
354
|
+
await guard.verify();
|
|
355
|
+
}
|
|
356
|
+
async function ensureBackup(paths, operation, hooks) {
|
|
357
|
+
if (!operation.backup || operation.expectedTargetHash === null)
|
|
358
|
+
return;
|
|
359
|
+
const target = await resolveRef(paths, operation.target);
|
|
360
|
+
const backup = await resolveRef(paths, operation.backup);
|
|
361
|
+
const existing = await inspectNativeArchiveContent(backup);
|
|
362
|
+
if (existing !== null) {
|
|
363
|
+
if (!sameContent(existing, operation.expectedTargetHash)) {
|
|
364
|
+
throw new Error(`Archive transaction backup content changed: ${operation.backup}`);
|
|
365
|
+
}
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
await assertContent({
|
|
369
|
+
target,
|
|
370
|
+
expectedHash: operation.expectedTargetHash,
|
|
371
|
+
label: `Archive transaction target ${operation.target}`,
|
|
372
|
+
});
|
|
373
|
+
await copyNativeProtectedFile({
|
|
374
|
+
sourceRoot: paths.nativeRoot,
|
|
375
|
+
source: target,
|
|
376
|
+
targetRoot: paths.nativeRoot,
|
|
377
|
+
target: backup,
|
|
378
|
+
maxBytes: NATIVE_ARCHIVE_COPY_MAX_BYTES,
|
|
379
|
+
label: `Archive transaction backup ${operation.backup}`,
|
|
380
|
+
expectedHash: operation.expectedTargetHash,
|
|
381
|
+
expectedTargetHash: null,
|
|
382
|
+
exclusive: true,
|
|
383
|
+
hooks: {
|
|
384
|
+
afterParentChainCaptured: () => hooks?.afterProtectedCopySourceParentCaptured?.('backup', operation.target),
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
await assertContent({
|
|
388
|
+
target: backup,
|
|
389
|
+
expectedHash: operation.expectedTargetHash,
|
|
390
|
+
label: `Archive transaction backup ${operation.backup}`,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
async function ensureOriginalTargetQuarantined(options) {
|
|
394
|
+
const expectedHash = options.operation.expectedTargetHash;
|
|
395
|
+
if (expectedHash === null) {
|
|
396
|
+
throw new Error(`Archive operation ${options.operation.id} has no original target to quarantine`);
|
|
397
|
+
}
|
|
398
|
+
const cas = await archiveCasPaths(options.paths, options.journal, options.operation, options.target);
|
|
399
|
+
let record = await readCasRecord({
|
|
400
|
+
paths: options.paths,
|
|
401
|
+
file: cas.originalRecord,
|
|
402
|
+
operation: options.operation,
|
|
403
|
+
role: 'original',
|
|
404
|
+
expectedHash,
|
|
405
|
+
});
|
|
406
|
+
if (await pathExists(cas.originalQuarantine)) {
|
|
407
|
+
if (!record) {
|
|
408
|
+
throw new Error(`Archive apply quarantine ${options.operation.target} has no bound object identity`);
|
|
409
|
+
}
|
|
410
|
+
await validateFileAgainstCasRecord({
|
|
411
|
+
paths: options.paths,
|
|
412
|
+
file: cas.originalQuarantine,
|
|
413
|
+
operation: options.operation,
|
|
414
|
+
record,
|
|
415
|
+
label: `Archive apply quarantine ${options.operation.target}`,
|
|
416
|
+
});
|
|
417
|
+
await ensureBackup(options.paths, options.operation, options.hooks);
|
|
418
|
+
return { record, quarantine: cas.originalQuarantine };
|
|
419
|
+
}
|
|
420
|
+
if (!(await pathExists(options.target))) {
|
|
421
|
+
throw new Error(`Archive apply target ${options.operation.target} disappeared before quarantine`);
|
|
422
|
+
}
|
|
423
|
+
record ??= await bindCurrentTarget({
|
|
424
|
+
paths: options.paths,
|
|
425
|
+
file: options.target,
|
|
426
|
+
recordFile: cas.originalRecord,
|
|
427
|
+
operation: options.operation,
|
|
428
|
+
role: 'original',
|
|
429
|
+
expectedHash,
|
|
430
|
+
label: `Archive apply target ${options.operation.target}`,
|
|
431
|
+
});
|
|
432
|
+
await validateFileAgainstCasRecord({
|
|
433
|
+
paths: options.paths,
|
|
434
|
+
file: options.target,
|
|
435
|
+
operation: options.operation,
|
|
436
|
+
record,
|
|
437
|
+
label: `Archive apply target ${options.operation.target}`,
|
|
438
|
+
});
|
|
439
|
+
await ensureBackup(options.paths, options.operation, options.hooks);
|
|
440
|
+
await quarantineBoundTarget({
|
|
441
|
+
paths: options.paths,
|
|
442
|
+
operation: options.operation,
|
|
443
|
+
phase: 'apply',
|
|
444
|
+
target: options.target,
|
|
445
|
+
quarantine: cas.originalQuarantine,
|
|
446
|
+
record,
|
|
447
|
+
hooks: options.hooks,
|
|
448
|
+
});
|
|
449
|
+
return { record, quarantine: cas.originalQuarantine };
|
|
450
|
+
}
|
|
451
|
+
async function ensureWriteCandidate(options) {
|
|
452
|
+
const cas = await archiveCasPaths(options.paths, options.journal, options.operation, options.target);
|
|
453
|
+
if (await pathExists(cas.candidate)) {
|
|
454
|
+
await captureStableArchiveFile({
|
|
455
|
+
paths: options.paths,
|
|
456
|
+
file: cas.candidate,
|
|
457
|
+
expectedHash: options.operation.stagedHash,
|
|
458
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
459
|
+
});
|
|
460
|
+
return cas.candidate;
|
|
461
|
+
}
|
|
462
|
+
await ensureNativeProtectedDirectory({
|
|
463
|
+
root: options.paths.nativeRoot,
|
|
464
|
+
directory: cas.directory,
|
|
465
|
+
label: `Archive CAS ${options.operation.id} records`,
|
|
466
|
+
});
|
|
467
|
+
await copyNativeProtectedFile({
|
|
468
|
+
sourceRoot: options.paths.nativeRoot,
|
|
469
|
+
source: options.staged,
|
|
470
|
+
targetRoot: options.paths.nativeRoot,
|
|
471
|
+
target: cas.candidate,
|
|
472
|
+
maxBytes: NATIVE_ARCHIVE_COPY_MAX_BYTES,
|
|
473
|
+
label: `Archive transaction staged file ${options.operation.staged}`,
|
|
474
|
+
expectedHash: options.operation.stagedHash,
|
|
475
|
+
expectedTargetHash: null,
|
|
476
|
+
exclusive: true,
|
|
477
|
+
hooks: {
|
|
478
|
+
afterParentChainCaptured: () => options.hooks?.afterProtectedCopySourceParentCaptured?.('apply', options.operation.staged),
|
|
479
|
+
},
|
|
480
|
+
});
|
|
481
|
+
return cas.candidate;
|
|
482
|
+
}
|
|
483
|
+
async function ensureWriteInstalled(options) {
|
|
484
|
+
const expectedHash = options.operation.stagedHash;
|
|
485
|
+
const cas = await archiveCasPaths(options.paths, options.journal, options.operation, options.target);
|
|
486
|
+
let record = await readCasRecord({
|
|
487
|
+
paths: options.paths,
|
|
488
|
+
file: cas.postRecord,
|
|
489
|
+
operation: options.operation,
|
|
490
|
+
role: 'post',
|
|
491
|
+
expectedHash,
|
|
492
|
+
});
|
|
493
|
+
if (record && (await pathExists(options.target))) {
|
|
494
|
+
await validateFileAgainstCasRecord({
|
|
495
|
+
paths: options.paths,
|
|
496
|
+
file: options.target,
|
|
497
|
+
operation: options.operation,
|
|
498
|
+
record,
|
|
499
|
+
label: `Archive write target ${options.operation.target}`,
|
|
500
|
+
});
|
|
501
|
+
if (await pathExists(cas.candidate)) {
|
|
502
|
+
await removeExactCasFile({
|
|
503
|
+
paths: options.paths,
|
|
504
|
+
file: cas.candidate,
|
|
505
|
+
operation: options.operation,
|
|
506
|
+
record,
|
|
507
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
return record;
|
|
511
|
+
}
|
|
512
|
+
if (await pathExists(options.target)) {
|
|
513
|
+
const candidate = await ensureWriteCandidate(options);
|
|
514
|
+
const candidateIdentity = await captureStableArchiveFile({
|
|
515
|
+
paths: options.paths,
|
|
516
|
+
file: candidate,
|
|
517
|
+
expectedHash,
|
|
518
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
519
|
+
});
|
|
520
|
+
const targetIdentity = await captureStableArchiveFile({
|
|
521
|
+
paths: options.paths,
|
|
522
|
+
file: options.target,
|
|
523
|
+
expectedHash,
|
|
524
|
+
label: `Archive write target ${options.operation.target}`,
|
|
525
|
+
});
|
|
526
|
+
if (!sameFileObject(candidateIdentity.identity, targetIdentity.identity)) {
|
|
527
|
+
throw new Error(`Archive write target ${options.operation.target} is occupied by an external object`);
|
|
528
|
+
}
|
|
529
|
+
record = await persistCasRecord({
|
|
530
|
+
paths: options.paths,
|
|
531
|
+
file: cas.postRecord,
|
|
532
|
+
operation: options.operation,
|
|
533
|
+
role: 'post',
|
|
534
|
+
expectedHash,
|
|
535
|
+
identity: targetIdentity.identity,
|
|
536
|
+
});
|
|
537
|
+
await removeExactCasFile({
|
|
538
|
+
paths: options.paths,
|
|
539
|
+
file: candidate,
|
|
540
|
+
operation: options.operation,
|
|
541
|
+
record,
|
|
542
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
543
|
+
});
|
|
544
|
+
return record;
|
|
545
|
+
}
|
|
546
|
+
const candidate = await ensureWriteCandidate(options);
|
|
547
|
+
const candidateIdentity = await captureStableArchiveFile({
|
|
548
|
+
paths: options.paths,
|
|
549
|
+
file: candidate,
|
|
550
|
+
expectedHash,
|
|
551
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
552
|
+
});
|
|
553
|
+
await ensureNativeProtectedDirectory({
|
|
554
|
+
root: options.paths.nativeRoot,
|
|
555
|
+
directory: path.dirname(options.target),
|
|
556
|
+
label: `Archive write target ${options.operation.target}`,
|
|
557
|
+
});
|
|
558
|
+
const guard = await captureNativeProtectedDirectoryGuard({
|
|
559
|
+
root: options.paths.nativeRoot,
|
|
560
|
+
directory: path.dirname(options.target),
|
|
561
|
+
label: `Archive write target ${options.operation.target}`,
|
|
562
|
+
});
|
|
563
|
+
await options.hooks?.beforeArchiveTargetInstall?.('apply', options.operation, options.target);
|
|
564
|
+
await guard.verify();
|
|
565
|
+
await validateFileAgainstCasRecord({
|
|
566
|
+
paths: options.paths,
|
|
567
|
+
file: candidate,
|
|
568
|
+
operation: options.operation,
|
|
569
|
+
record: {
|
|
570
|
+
schema: NATIVE_ARCHIVE_CAS_SCHEMA,
|
|
571
|
+
operationId: options.operation.id,
|
|
572
|
+
role: 'post',
|
|
573
|
+
hash: expectedHash,
|
|
574
|
+
identity: candidateIdentity.identity,
|
|
575
|
+
},
|
|
576
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
577
|
+
});
|
|
578
|
+
try {
|
|
579
|
+
await fs.link(candidate, options.target);
|
|
580
|
+
}
|
|
581
|
+
catch (error) {
|
|
582
|
+
if (error.code === 'EEXIST') {
|
|
583
|
+
throw new Error(`Archive write target ${options.operation.target} was created before exclusive install`, { cause: error });
|
|
584
|
+
}
|
|
585
|
+
throw error;
|
|
586
|
+
}
|
|
587
|
+
await guard.verify();
|
|
588
|
+
await options.hooks?.afterArchiveTargetInstalled?.('apply', options.operation, options.target);
|
|
589
|
+
const targetIdentity = await captureStableArchiveFile({
|
|
590
|
+
paths: options.paths,
|
|
591
|
+
file: options.target,
|
|
592
|
+
expectedHash,
|
|
593
|
+
label: `Archive write target ${options.operation.target}`,
|
|
594
|
+
});
|
|
595
|
+
if (!sameFileObject(candidateIdentity.identity, targetIdentity.identity)) {
|
|
596
|
+
throw new Error(`Archive write target ${options.operation.target} changed during install`);
|
|
597
|
+
}
|
|
598
|
+
record = await persistCasRecord({
|
|
599
|
+
paths: options.paths,
|
|
600
|
+
file: cas.postRecord,
|
|
601
|
+
operation: options.operation,
|
|
602
|
+
role: 'post',
|
|
603
|
+
expectedHash,
|
|
604
|
+
identity: targetIdentity.identity,
|
|
605
|
+
});
|
|
606
|
+
await removeExactCasFile({
|
|
607
|
+
paths: options.paths,
|
|
608
|
+
file: candidate,
|
|
609
|
+
operation: options.operation,
|
|
610
|
+
record,
|
|
611
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
612
|
+
});
|
|
613
|
+
return record;
|
|
614
|
+
}
|
|
615
|
+
async function applyWrite(paths, journal, operation, hooks) {
|
|
616
|
+
const target = await resolveRef(paths, operation.target);
|
|
617
|
+
const staged = await resolveRef(paths, operation.staged);
|
|
618
|
+
await assertContent({
|
|
619
|
+
target: staged,
|
|
620
|
+
expectedHash: operation.stagedHash,
|
|
621
|
+
label: `Archive transaction staged file ${operation.staged}`,
|
|
622
|
+
});
|
|
623
|
+
if (operation.expectedTargetHash !== null) {
|
|
624
|
+
const cas = await archiveCasPaths(paths, journal, operation, target);
|
|
625
|
+
const postRecord = await readCasRecord({
|
|
626
|
+
paths,
|
|
627
|
+
file: cas.postRecord,
|
|
628
|
+
operation,
|
|
629
|
+
role: 'post',
|
|
630
|
+
expectedHash: operation.stagedHash,
|
|
631
|
+
});
|
|
632
|
+
if (!postRecord || !(await pathExists(target))) {
|
|
633
|
+
await ensureOriginalTargetQuarantined({ paths, journal, operation, target, hooks });
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
const actual = await inspectNativeArchiveContent(target);
|
|
638
|
+
if (actual !== null && !sameContent(actual, operation.stagedHash)) {
|
|
639
|
+
throw new Error(`Archive transaction target ${operation.target} changed before create: ${contentDescription(actual)}`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
await ensureWriteInstalled({
|
|
643
|
+
paths,
|
|
644
|
+
journal,
|
|
645
|
+
operation,
|
|
646
|
+
staged,
|
|
647
|
+
target,
|
|
648
|
+
hooks,
|
|
649
|
+
});
|
|
650
|
+
await assertContent({
|
|
651
|
+
target,
|
|
652
|
+
expectedHash: operation.stagedHash,
|
|
653
|
+
label: `Archive transaction target ${operation.target}`,
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
async function applyRemove(paths, journal, operation, hooks) {
|
|
657
|
+
const target = await resolveRef(paths, operation.target);
|
|
658
|
+
await ensureOriginalTargetQuarantined({ paths, journal, operation, target, hooks });
|
|
659
|
+
await assertContent({
|
|
660
|
+
target,
|
|
661
|
+
expectedHash: null,
|
|
662
|
+
label: `Archive transaction target ${operation.target}`,
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
async function applyMove(paths, operation) {
|
|
666
|
+
const source = await resolveRef(paths, operation.source);
|
|
667
|
+
const target = await resolveRef(paths, operation.target);
|
|
668
|
+
const [sourceContent, targetContent] = await Promise.all([
|
|
669
|
+
inspectNativeArchiveContent(source),
|
|
670
|
+
inspectNativeArchiveContent(target),
|
|
671
|
+
]);
|
|
672
|
+
if (sourceContent === null &&
|
|
673
|
+
sameContent(targetContent, operation.expectedSourceHash, 'directory')) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
if (!sameContent(sourceContent, operation.expectedSourceHash, 'directory') ||
|
|
677
|
+
targetContent !== null) {
|
|
678
|
+
throw new Error(`Archive transaction move ${operation.id} content changed: source=${contentDescription(sourceContent)}, target=${contentDescription(targetContent)}`);
|
|
679
|
+
}
|
|
680
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
681
|
+
await fs.rename(source, target);
|
|
682
|
+
await assertContent({
|
|
683
|
+
target,
|
|
684
|
+
expectedHash: operation.expectedSourceHash,
|
|
685
|
+
expectedKind: 'directory',
|
|
686
|
+
label: `Archive transaction move target ${operation.target}`,
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
async function applyOperation(paths, journal, operation, hooks) {
|
|
690
|
+
if (operation.type === 'write')
|
|
691
|
+
return applyWrite(paths, journal, operation, hooks);
|
|
692
|
+
if (operation.type === 'remove')
|
|
693
|
+
return applyRemove(paths, journal, operation, hooks);
|
|
694
|
+
return applyMove(paths, operation);
|
|
695
|
+
}
|
|
696
|
+
function completedOperationIds(options) {
|
|
697
|
+
let operationIndex = 0;
|
|
698
|
+
let startedCurrent = false;
|
|
699
|
+
const completed = [];
|
|
700
|
+
for (const event of options.events) {
|
|
701
|
+
if (event.type !== 'operation-started' && event.type !== 'operation-completed')
|
|
702
|
+
continue;
|
|
703
|
+
const expected = options.journal.operations[operationIndex];
|
|
704
|
+
if (!expected || event.operationId !== expected.id) {
|
|
705
|
+
throw new Error(`Native Archive transaction ${options.journal.id} operation events are out of order`);
|
|
706
|
+
}
|
|
707
|
+
if (event.type === 'operation-started') {
|
|
708
|
+
startedCurrent = true;
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
if (!startedCurrent) {
|
|
712
|
+
throw new Error(`Native Archive transaction ${options.journal.id} completed an operation before it started`);
|
|
713
|
+
}
|
|
714
|
+
completed.push(expected.id);
|
|
715
|
+
operationIndex += 1;
|
|
716
|
+
startedCurrent = false;
|
|
717
|
+
}
|
|
718
|
+
return completed;
|
|
719
|
+
}
|
|
720
|
+
async function assertCompletedOperation(paths, journal, operation, finalizationStarted) {
|
|
721
|
+
const target = await resolveRef(paths, operation.target);
|
|
722
|
+
if (operation.type === 'write') {
|
|
723
|
+
const staged = await resolveRef(paths, operation.staged);
|
|
724
|
+
await assertContent({
|
|
725
|
+
target: staged,
|
|
726
|
+
expectedHash: operation.stagedHash,
|
|
727
|
+
label: `Completed Archive staged file ${operation.staged}`,
|
|
728
|
+
});
|
|
729
|
+
const cas = await archiveCasPaths(paths, journal, operation, target);
|
|
730
|
+
const postRecord = await readCasRecord({
|
|
731
|
+
paths,
|
|
732
|
+
file: cas.postRecord,
|
|
733
|
+
operation,
|
|
734
|
+
role: 'post',
|
|
735
|
+
expectedHash: operation.stagedHash,
|
|
736
|
+
});
|
|
737
|
+
if (!postRecord) {
|
|
738
|
+
throw new Error(`Completed Archive target ${operation.target} has no CAS identity`);
|
|
739
|
+
}
|
|
740
|
+
await validateFileAgainstCasRecord({
|
|
741
|
+
paths,
|
|
742
|
+
file: target,
|
|
743
|
+
operation,
|
|
744
|
+
record: postRecord,
|
|
745
|
+
label: `Completed Archive target ${operation.target}`,
|
|
746
|
+
});
|
|
747
|
+
if (operation.expectedTargetHash !== null) {
|
|
748
|
+
await assertContent({
|
|
749
|
+
target: await resolveRef(paths, operation.backup),
|
|
750
|
+
expectedHash: operation.expectedTargetHash,
|
|
751
|
+
label: `Completed Archive backup ${operation.backup}`,
|
|
752
|
+
});
|
|
753
|
+
const originalRecord = await readCasRecord({
|
|
754
|
+
paths,
|
|
755
|
+
file: cas.originalRecord,
|
|
756
|
+
operation,
|
|
757
|
+
role: 'original',
|
|
758
|
+
expectedHash: operation.expectedTargetHash,
|
|
759
|
+
});
|
|
760
|
+
if (!originalRecord) {
|
|
761
|
+
throw new Error(`Completed Archive target ${operation.target} has no original CAS identity`);
|
|
762
|
+
}
|
|
763
|
+
if (await pathExists(cas.originalQuarantine)) {
|
|
764
|
+
await validateFileAgainstCasRecord({
|
|
765
|
+
paths,
|
|
766
|
+
file: cas.originalQuarantine,
|
|
767
|
+
operation,
|
|
768
|
+
record: originalRecord,
|
|
769
|
+
label: `Completed Archive original quarantine ${operation.target}`,
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
else if (!finalizationStarted) {
|
|
773
|
+
throw new Error(`Completed Archive original quarantine ${operation.target} disappeared`);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
if (operation.type === 'remove') {
|
|
779
|
+
await assertContent({
|
|
780
|
+
target,
|
|
781
|
+
expectedHash: null,
|
|
782
|
+
label: `Completed Archive target ${operation.target}`,
|
|
783
|
+
});
|
|
784
|
+
await assertContent({
|
|
785
|
+
target: await resolveRef(paths, operation.backup),
|
|
786
|
+
expectedHash: operation.expectedTargetHash,
|
|
787
|
+
label: `Completed Archive backup ${operation.backup}`,
|
|
788
|
+
});
|
|
789
|
+
const cas = await archiveCasPaths(paths, journal, operation, target);
|
|
790
|
+
const originalRecord = await readCasRecord({
|
|
791
|
+
paths,
|
|
792
|
+
file: cas.originalRecord,
|
|
793
|
+
operation,
|
|
794
|
+
role: 'original',
|
|
795
|
+
expectedHash: operation.expectedTargetHash,
|
|
796
|
+
});
|
|
797
|
+
if (!originalRecord) {
|
|
798
|
+
throw new Error(`Completed Archive remove ${operation.target} has no original CAS identity`);
|
|
799
|
+
}
|
|
800
|
+
if (await pathExists(cas.originalQuarantine)) {
|
|
801
|
+
await validateFileAgainstCasRecord({
|
|
802
|
+
paths,
|
|
803
|
+
file: cas.originalQuarantine,
|
|
804
|
+
operation,
|
|
805
|
+
record: originalRecord,
|
|
806
|
+
label: `Completed Archive original quarantine ${operation.target}`,
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
else if (!finalizationStarted) {
|
|
810
|
+
throw new Error(`Completed Archive original quarantine ${operation.target} disappeared`);
|
|
811
|
+
}
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (finalizationStarted)
|
|
815
|
+
return;
|
|
816
|
+
await assertContent({
|
|
817
|
+
target: await resolveRef(paths, operation.source),
|
|
818
|
+
expectedHash: null,
|
|
819
|
+
label: `Completed Archive move source ${operation.source}`,
|
|
820
|
+
});
|
|
821
|
+
await assertContent({
|
|
822
|
+
target,
|
|
823
|
+
expectedHash: operation.expectedSourceHash,
|
|
824
|
+
expectedKind: 'directory',
|
|
825
|
+
label: `Completed Archive move target ${operation.target}`,
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
export async function applyNativeArchiveTransactionV2(paths, journal, hooks) {
|
|
829
|
+
let current = journal.status === 'prepared' ? await setStatus(paths, journal, 'applying') : journal;
|
|
830
|
+
if (current.status !== 'applying') {
|
|
831
|
+
throw new Error(`Native Archive transaction ${current.id} cannot apply from ${current.status}`);
|
|
832
|
+
}
|
|
833
|
+
const events = await readNativeTransactionEvents(paths, current.id);
|
|
834
|
+
const completedIds = completedOperationIds({ journal: current, events });
|
|
835
|
+
const completed = new Set(completedIds);
|
|
836
|
+
const finalizationStarted = events.some((event) => event.type === 'archive-finalization-started');
|
|
837
|
+
for (const operation of current.operations.slice(0, completedIds.length)) {
|
|
838
|
+
await assertCompletedOperation(paths, current, operation, finalizationStarted);
|
|
839
|
+
}
|
|
840
|
+
let completedCount = completed.size;
|
|
841
|
+
for (const operation of current.operations) {
|
|
842
|
+
if (completed.has(operation.id))
|
|
843
|
+
continue;
|
|
844
|
+
await appendNativeTransactionEvent(paths, current.id, 'operation-started', operation.id);
|
|
845
|
+
await applyOperation(paths, current, operation, hooks);
|
|
846
|
+
await appendNativeTransactionEvent(paths, current.id, 'operation-completed', operation.id);
|
|
847
|
+
completedCount += 1;
|
|
848
|
+
await hooks?.afterOperation?.(operation, completedCount);
|
|
849
|
+
}
|
|
850
|
+
current = await readNativeArchiveTransactionV2(paths, current.id);
|
|
851
|
+
return current;
|
|
852
|
+
}
|
|
853
|
+
async function fileMatchesCasRecord(options) {
|
|
854
|
+
try {
|
|
855
|
+
await validateFileAgainstCasRecord(options);
|
|
856
|
+
return true;
|
|
857
|
+
}
|
|
858
|
+
catch {
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
async function installOriginalTarget(options) {
|
|
863
|
+
await validateFileAgainstCasRecord({
|
|
864
|
+
paths: options.paths,
|
|
865
|
+
file: options.quarantine,
|
|
866
|
+
operation: options.operation,
|
|
867
|
+
record: options.record,
|
|
868
|
+
label: `Archive rollback original quarantine ${options.operation.target}`,
|
|
869
|
+
});
|
|
870
|
+
const guard = await captureNativeProtectedDirectoryGuard({
|
|
871
|
+
root: options.paths.nativeRoot,
|
|
872
|
+
directory: path.dirname(options.target),
|
|
873
|
+
label: `Archive rollback target ${options.operation.target}`,
|
|
874
|
+
});
|
|
875
|
+
await options.hooks?.beforeArchiveTargetInstall?.('rollback', options.operation, options.target);
|
|
876
|
+
await guard.verify();
|
|
877
|
+
await validateFileAgainstCasRecord({
|
|
878
|
+
paths: options.paths,
|
|
879
|
+
file: options.quarantine,
|
|
880
|
+
operation: options.operation,
|
|
881
|
+
record: options.record,
|
|
882
|
+
label: `Archive rollback original quarantine ${options.operation.target}`,
|
|
883
|
+
});
|
|
884
|
+
try {
|
|
885
|
+
await fs.link(options.quarantine, options.target);
|
|
886
|
+
}
|
|
887
|
+
catch (error) {
|
|
888
|
+
if (error.code === 'EEXIST') {
|
|
889
|
+
throw new Error(`Archive rollback target ${options.operation.target} was created before exclusive restore`, { cause: error });
|
|
890
|
+
}
|
|
891
|
+
throw error;
|
|
892
|
+
}
|
|
893
|
+
await guard.verify();
|
|
894
|
+
await options.hooks?.afterArchiveTargetInstalled?.('rollback', options.operation, options.target);
|
|
895
|
+
await validateFileAgainstCasRecord({
|
|
896
|
+
paths: options.paths,
|
|
897
|
+
file: options.target,
|
|
898
|
+
operation: options.operation,
|
|
899
|
+
record: options.record,
|
|
900
|
+
label: `Archive rollback target ${options.operation.target}`,
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
async function removeWriteCandidateIfPresent(options) {
|
|
904
|
+
if (options.operation.type !== 'write')
|
|
905
|
+
return;
|
|
906
|
+
const cas = await archiveCasPaths(options.paths, options.journal, options.operation, options.target);
|
|
907
|
+
if (!(await pathExists(cas.candidate)))
|
|
908
|
+
return;
|
|
909
|
+
const current = await captureStableArchiveFile({
|
|
910
|
+
paths: options.paths,
|
|
911
|
+
file: cas.candidate,
|
|
912
|
+
expectedHash: options.operation.stagedHash,
|
|
913
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
914
|
+
});
|
|
915
|
+
await removeExactCasFile({
|
|
916
|
+
paths: options.paths,
|
|
917
|
+
file: cas.candidate,
|
|
918
|
+
operation: options.operation,
|
|
919
|
+
record: {
|
|
920
|
+
schema: NATIVE_ARCHIVE_CAS_SCHEMA,
|
|
921
|
+
operationId: options.operation.id,
|
|
922
|
+
role: 'post',
|
|
923
|
+
hash: options.operation.stagedHash,
|
|
924
|
+
identity: current.identity,
|
|
925
|
+
},
|
|
926
|
+
label: `Archive write candidate ${options.operation.target}`,
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
async function rollbackWriteOrRemove(paths, journal, operation, hooks) {
|
|
930
|
+
const target = await resolveRef(paths, operation.target);
|
|
931
|
+
const cas = await archiveCasPaths(paths, journal, operation, target);
|
|
932
|
+
const originalHash = operation.expectedTargetHash;
|
|
933
|
+
const originalRecord = originalHash === null
|
|
934
|
+
? null
|
|
935
|
+
: await readCasRecord({
|
|
936
|
+
paths,
|
|
937
|
+
file: cas.originalRecord,
|
|
938
|
+
operation,
|
|
939
|
+
role: 'original',
|
|
940
|
+
expectedHash: originalHash,
|
|
941
|
+
});
|
|
942
|
+
let postRecord = operation.type === 'write'
|
|
943
|
+
? await readCasRecord({
|
|
944
|
+
paths,
|
|
945
|
+
file: cas.postRecord,
|
|
946
|
+
operation,
|
|
947
|
+
role: 'post',
|
|
948
|
+
expectedHash: operation.stagedHash,
|
|
949
|
+
})
|
|
950
|
+
: null;
|
|
951
|
+
if (operation.type === 'write' &&
|
|
952
|
+
!postRecord &&
|
|
953
|
+
(await pathExists(cas.candidate)) &&
|
|
954
|
+
(await pathExists(target))) {
|
|
955
|
+
const candidate = await captureStableArchiveFile({
|
|
956
|
+
paths,
|
|
957
|
+
file: cas.candidate,
|
|
958
|
+
expectedHash: operation.stagedHash,
|
|
959
|
+
label: `Archive write candidate ${operation.target}`,
|
|
960
|
+
});
|
|
961
|
+
const current = await captureStableArchiveFile({
|
|
962
|
+
paths,
|
|
963
|
+
file: target,
|
|
964
|
+
expectedHash: operation.stagedHash,
|
|
965
|
+
label: `Archive rollback target ${operation.target}`,
|
|
966
|
+
});
|
|
967
|
+
if (sameFileObject(candidate.identity, current.identity)) {
|
|
968
|
+
postRecord = await persistCasRecord({
|
|
969
|
+
paths,
|
|
970
|
+
file: cas.postRecord,
|
|
971
|
+
operation,
|
|
972
|
+
role: 'post',
|
|
973
|
+
expectedHash: operation.stagedHash,
|
|
974
|
+
identity: current.identity,
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
if (await pathExists(cas.rollbackQuarantine)) {
|
|
979
|
+
if (!postRecord) {
|
|
980
|
+
throw new Error(`Archive rollback quarantine ${operation.target} has no CAS identity`);
|
|
981
|
+
}
|
|
982
|
+
await validateFileAgainstCasRecord({
|
|
983
|
+
paths,
|
|
984
|
+
file: cas.rollbackQuarantine,
|
|
985
|
+
operation,
|
|
986
|
+
record: postRecord,
|
|
987
|
+
label: `Archive rollback quarantine ${operation.target}`,
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
if (await pathExists(target)) {
|
|
991
|
+
const alreadyRestored = originalRecord !== null &&
|
|
992
|
+
(await fileMatchesCasRecord({
|
|
993
|
+
paths,
|
|
994
|
+
file: target,
|
|
995
|
+
operation,
|
|
996
|
+
record: originalRecord,
|
|
997
|
+
label: `Archive rollback target ${operation.target}`,
|
|
998
|
+
}));
|
|
999
|
+
if (!alreadyRestored) {
|
|
1000
|
+
if (!postRecord) {
|
|
1001
|
+
if (!originalRecord) {
|
|
1002
|
+
const actual = await inspectNativeArchiveContent(target);
|
|
1003
|
+
if (sameContent(actual, originalHash)) {
|
|
1004
|
+
await removeWriteCandidateIfPresent({ paths, journal, operation, target });
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
throw new Error(`Archive rollback target ${operation.target} is occupied by an external object`);
|
|
1009
|
+
}
|
|
1010
|
+
await quarantineBoundTarget({
|
|
1011
|
+
paths,
|
|
1012
|
+
operation,
|
|
1013
|
+
phase: 'rollback',
|
|
1014
|
+
target,
|
|
1015
|
+
quarantine: cas.rollbackQuarantine,
|
|
1016
|
+
record: postRecord,
|
|
1017
|
+
hooks,
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
if (originalHash === null) {
|
|
1022
|
+
if (await pathExists(target)) {
|
|
1023
|
+
throw new Error(`Archive rollback create target ${operation.target} could not be removed`);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
else if (!(await pathExists(target))) {
|
|
1027
|
+
if (!originalRecord || !(await pathExists(cas.originalQuarantine))) {
|
|
1028
|
+
throw new Error(`Archive rollback original target ${operation.target} cannot be recovered safely`);
|
|
1029
|
+
}
|
|
1030
|
+
await installOriginalTarget({
|
|
1031
|
+
paths,
|
|
1032
|
+
operation,
|
|
1033
|
+
target,
|
|
1034
|
+
quarantine: cas.originalQuarantine,
|
|
1035
|
+
record: originalRecord,
|
|
1036
|
+
hooks,
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
if (originalRecord && (await pathExists(cas.originalQuarantine))) {
|
|
1040
|
+
await removeExactCasFile({
|
|
1041
|
+
paths,
|
|
1042
|
+
file: cas.originalQuarantine,
|
|
1043
|
+
operation,
|
|
1044
|
+
record: originalRecord,
|
|
1045
|
+
label: `Archive rollback original quarantine ${operation.target}`,
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
if (postRecord && (await pathExists(cas.rollbackQuarantine))) {
|
|
1049
|
+
await removeExactCasFile({
|
|
1050
|
+
paths,
|
|
1051
|
+
file: cas.rollbackQuarantine,
|
|
1052
|
+
operation,
|
|
1053
|
+
record: postRecord,
|
|
1054
|
+
label: `Archive rollback quarantine ${operation.target}`,
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
await removeWriteCandidateIfPresent({ paths, journal, operation, target });
|
|
1058
|
+
await assertContent({
|
|
1059
|
+
target,
|
|
1060
|
+
expectedHash: originalHash,
|
|
1061
|
+
label: `Archive rollback target ${operation.target}`,
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
async function rollbackMove(paths, operation) {
|
|
1065
|
+
const source = await resolveRef(paths, operation.source);
|
|
1066
|
+
const target = await resolveRef(paths, operation.target);
|
|
1067
|
+
const [sourceContent, targetContent] = await Promise.all([
|
|
1068
|
+
inspectNativeArchiveContent(source),
|
|
1069
|
+
inspectNativeArchiveContent(target),
|
|
1070
|
+
]);
|
|
1071
|
+
if (sameContent(sourceContent, operation.expectedSourceHash, 'directory') &&
|
|
1072
|
+
targetContent === null) {
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
if (sourceContent !== null ||
|
|
1076
|
+
!sameContent(targetContent, operation.expectedSourceHash, 'directory')) {
|
|
1077
|
+
throw new Error(`Archive rollback move ${operation.id} content changed: source=${contentDescription(sourceContent)}, target=${contentDescription(targetContent)}`);
|
|
1078
|
+
}
|
|
1079
|
+
await fs.mkdir(path.dirname(source), { recursive: true });
|
|
1080
|
+
await fs.rename(target, source);
|
|
1081
|
+
}
|
|
1082
|
+
export async function rollbackNativeArchiveTransactionV2(paths, journal, hooks) {
|
|
1083
|
+
const events = await readNativeTransactionEvents(paths, journal.id);
|
|
1084
|
+
if (events.some((event) => event.type === 'archive-finalization-started' || event.type === 'archive-finalized')) {
|
|
1085
|
+
throw new Error('An archive whose finalization started can only be recovered by continuing it');
|
|
1086
|
+
}
|
|
1087
|
+
let current = await setStatus(paths, journal, 'rolling-back');
|
|
1088
|
+
await appendNativeTransactionEvent(paths, current.id, 'rollback-started');
|
|
1089
|
+
const started = new Set(events
|
|
1090
|
+
.filter((event) => event.type === 'operation-started' || event.type === 'operation-completed')
|
|
1091
|
+
.map((event) => event.operationId));
|
|
1092
|
+
for (const operation of [...current.operations].reverse()) {
|
|
1093
|
+
if (!started.has(operation.id))
|
|
1094
|
+
continue;
|
|
1095
|
+
if (operation.type === 'move')
|
|
1096
|
+
await rollbackMove(paths, operation);
|
|
1097
|
+
else
|
|
1098
|
+
await rollbackWriteOrRemove(paths, current, operation, hooks);
|
|
1099
|
+
}
|
|
1100
|
+
await appendNativeTransactionEvent(paths, current.id, 'rollback-completed');
|
|
1101
|
+
current = await setStatus(paths, current, 'rolled-back');
|
|
1102
|
+
return current;
|
|
1103
|
+
}
|
|
1104
|
+
async function assertCommittedArchiveCasTarget(paths, journal, operation) {
|
|
1105
|
+
const target = await resolveRef(paths, operation.target);
|
|
1106
|
+
if (operation.type === 'write') {
|
|
1107
|
+
const cas = await archiveCasPaths(paths, journal, operation, target);
|
|
1108
|
+
const postRecord = await readCasRecord({
|
|
1109
|
+
paths,
|
|
1110
|
+
file: cas.postRecord,
|
|
1111
|
+
operation,
|
|
1112
|
+
role: 'post',
|
|
1113
|
+
expectedHash: operation.stagedHash,
|
|
1114
|
+
});
|
|
1115
|
+
if (!postRecord) {
|
|
1116
|
+
throw new Error(`Archive commit target ${operation.target} has no CAS identity`);
|
|
1117
|
+
}
|
|
1118
|
+
await validateFileAgainstCasRecord({
|
|
1119
|
+
paths,
|
|
1120
|
+
file: target,
|
|
1121
|
+
operation,
|
|
1122
|
+
record: postRecord,
|
|
1123
|
+
label: `Archive commit target ${operation.target}`,
|
|
1124
|
+
});
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
await assertContent({
|
|
1128
|
+
target,
|
|
1129
|
+
expectedHash: null,
|
|
1130
|
+
label: `Archive commit target ${operation.target}`,
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
async function cleanupCommittedArchiveCas(paths, journal) {
|
|
1134
|
+
for (const operation of journal.operations) {
|
|
1135
|
+
if (operation.type === 'move')
|
|
1136
|
+
continue;
|
|
1137
|
+
const target = await resolveRef(paths, operation.target);
|
|
1138
|
+
const cas = await archiveCasPaths(paths, journal, operation, target);
|
|
1139
|
+
if (await pathExists(cas.rollbackQuarantine)) {
|
|
1140
|
+
throw new Error(`Archive commit found an unfinished rollback for ${operation.target}`);
|
|
1141
|
+
}
|
|
1142
|
+
await assertCommittedArchiveCasTarget(paths, journal, operation);
|
|
1143
|
+
if (operation.expectedTargetHash !== null) {
|
|
1144
|
+
const originalRecord = await readCasRecord({
|
|
1145
|
+
paths,
|
|
1146
|
+
file: cas.originalRecord,
|
|
1147
|
+
operation,
|
|
1148
|
+
role: 'original',
|
|
1149
|
+
expectedHash: operation.expectedTargetHash,
|
|
1150
|
+
});
|
|
1151
|
+
if (!originalRecord) {
|
|
1152
|
+
throw new Error(`Archive commit target ${operation.target} has no original CAS identity`);
|
|
1153
|
+
}
|
|
1154
|
+
if (await pathExists(cas.originalQuarantine)) {
|
|
1155
|
+
await removeExactCasFile({
|
|
1156
|
+
paths,
|
|
1157
|
+
file: cas.originalQuarantine,
|
|
1158
|
+
operation,
|
|
1159
|
+
record: originalRecord,
|
|
1160
|
+
label: `Archive commit original quarantine ${operation.target}`,
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
await removeWriteCandidateIfPresent({ paths, journal, operation, target });
|
|
1165
|
+
}
|
|
1166
|
+
for (const operation of journal.operations) {
|
|
1167
|
+
if (operation.type !== 'move') {
|
|
1168
|
+
await assertCommittedArchiveCasTarget(paths, journal, operation);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
export async function finalizeNativeArchiveTransactionV2(paths, journal, event) {
|
|
1173
|
+
if (event === 'commit')
|
|
1174
|
+
await cleanupCommittedArchiveCas(paths, journal);
|
|
1175
|
+
await appendNativeTransactionEvent(paths, journal.id, event);
|
|
1176
|
+
return event === 'commit' ? setStatus(paths, journal, 'committed') : journal;
|
|
1177
|
+
}
|
|
1178
|
+
export function nativeArchiveTransactionPaths(paths, id) {
|
|
1179
|
+
return nativeTransactionPaths(paths, id);
|
|
1180
|
+
}
|
|
1181
|
+
//# sourceMappingURL=native-archive-transaction.js.map
|