agentplane 0.3.12 → 0.3.14
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/assets/RUNNER.md +1 -1
- package/assets/agents/ORCHESTRATOR.json +1 -1
- package/assets/agents/SKILL_EXTRACTOR.json +31 -0
- package/assets/codex-plugin/assets/header.png +0 -0
- package/assets/codex-plugin/assets/icon.svg +1 -0
- package/assets/codex-plugin/assets/logo.svg +1 -0
- package/assets/codex-plugin/skills/agentplane/SKILL.md +35 -0
- package/assets/framework.manifest.json +7 -0
- package/assets/policy/governance.md +4 -2
- package/assets/policy/incidents.md +4 -19
- package/assets/policy/workflow.branch_pr.md +10 -5
- package/assets/policy/workflow.release.md +5 -2
- package/dist/.build-manifest.json +409 -219
- package/dist/cli/exit-codes.d.ts.map +1 -1
- package/dist/cli/exit-codes.js +1 -0
- package/dist/cli/output.d.ts +29 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +33 -0
- package/dist/cli/reason-codes.d.ts +1 -1
- package/dist/cli/reason-codes.d.ts.map +1 -1
- package/dist/cli/reason-codes.js +12 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/core.js +36 -78
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/lifecycle.js +4 -12
- package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/project.js +27 -31
- package/dist/cli/run-cli/command-catalog/shared.d.ts +9 -6
- package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/shared.js +23 -6
- package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/task.js +6 -18
- package/dist/cli/run-cli/command-catalog.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/codex.d.ts +14 -0
- package/dist/cli/run-cli/commands/codex.d.ts.map +1 -0
- package/dist/cli/run-cli/commands/codex.js +100 -0
- package/dist/cli/run-cli/commands/core.d.ts +1 -0
- package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/core.js +1 -0
- package/dist/cli/run-cli/commands/init/recipes.d.ts +9 -1
- package/dist/cli/run-cli/commands/init/recipes.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/recipes.js +33 -22
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +26 -21
- package/dist/cli/run-cli/error-guidance.js +20 -0
- package/dist/cli/run-cli.js +1 -1
- package/dist/cli/run-cli.test-helpers.d.ts +1 -74
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +1 -766
- package/dist/commands/branch/cleanup-merged.d.ts.map +1 -1
- package/dist/commands/branch/cleanup-merged.js +5 -9
- package/dist/commands/branch/work-start.command.d.ts.map +1 -1
- package/dist/commands/branch/work-start.command.js +1 -0
- package/dist/commands/codex/plugin-install.d.ts +26 -0
- package/dist/commands/codex/plugin-install.d.ts.map +1 -0
- package/dist/commands/codex/plugin-install.js +209 -0
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +2 -0
- package/dist/commands/doctor/branch-pr.d.ts +1 -1
- package/dist/commands/doctor/branch-pr.d.ts.map +1 -1
- package/dist/commands/doctor/branch-pr.js +5 -2
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +4 -1
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +2 -1
- package/dist/commands/guard/impl/env.d.ts +6 -0
- package/dist/commands/guard/impl/env.d.ts.map +1 -1
- package/dist/commands/guard/impl/env.js +41 -0
- package/dist/commands/pr/integrate/cmd.d.ts.map +1 -1
- package/dist/commands/pr/integrate/cmd.js +81 -5
- package/dist/commands/pr/integrate/internal/prepare.d.ts.map +1 -1
- package/dist/commands/pr/integrate/internal/prepare.js +38 -7
- package/dist/commands/pr/internal/auto-commit.d.ts.map +1 -1
- package/dist/commands/pr/internal/auto-commit.js +13 -7
- package/dist/commands/pr/internal/sync-branch.d.ts +36 -0
- package/dist/commands/pr/internal/sync-branch.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-branch.js +113 -0
- package/dist/commands/pr/internal/sync-github.d.ts +28 -0
- package/dist/commands/pr/internal/sync-github.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-github.js +178 -0
- package/dist/commands/pr/internal/sync-model.d.ts +36 -0
- package/dist/commands/pr/internal/sync-model.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-model.js +1 -0
- package/dist/commands/pr/internal/sync-open-step.d.ts +10 -0
- package/dist/commands/pr/internal/sync-open-step.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-open-step.js +128 -0
- package/dist/commands/pr/internal/sync-support.d.ts +7 -0
- package/dist/commands/pr/internal/sync-support.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-support.js +29 -0
- package/dist/commands/pr/internal/sync-update-step.d.ts +6 -0
- package/dist/commands/pr/internal/sync-update-step.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-update-step.js +68 -0
- package/dist/commands/pr/internal/sync.d.ts +2 -6
- package/dist/commands/pr/internal/sync.d.ts.map +1 -1
- package/dist/commands/pr/internal/sync.js +83 -525
- package/dist/commands/pr/open.d.ts.map +1 -1
- package/dist/commands/pr/open.js +62 -7
- package/dist/commands/pr/pr.command.d.ts.map +1 -1
- package/dist/commands/pr/pr.command.js +7 -2
- package/dist/commands/recipes/active.command.d.ts +7 -0
- package/dist/commands/recipes/active.command.d.ts.map +1 -0
- package/dist/commands/recipes/active.command.js +12 -0
- package/dist/commands/recipes/add.command.d.ts +8 -0
- package/dist/commands/recipes/add.command.d.ts.map +1 -0
- package/dist/commands/recipes/add.command.js +33 -0
- package/dist/commands/recipes/detach.command.d.ts +7 -0
- package/dist/commands/recipes/detach.command.d.ts.map +1 -0
- package/dist/commands/recipes/detach.command.js +19 -0
- package/dist/commands/recipes/disable.command.d.ts +7 -0
- package/dist/commands/recipes/disable.command.d.ts.map +1 -0
- package/dist/commands/recipes/disable.command.js +10 -0
- package/dist/commands/recipes/enable.command.d.ts +7 -0
- package/dist/commands/recipes/enable.command.d.ts.map +1 -0
- package/dist/commands/recipes/enable.command.js +10 -0
- package/dist/commands/recipes/explain-active.command.d.ts +5 -0
- package/dist/commands/recipes/explain-active.command.d.ts.map +1 -0
- package/dist/commands/recipes/explain-active.command.js +11 -0
- package/dist/commands/recipes/explain.command.d.ts.map +1 -1
- package/dist/commands/recipes/explain.command.js +4 -2
- package/dist/commands/recipes/impl/apply.d.ts +1 -1
- package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
- package/dist/commands/recipes/impl/apply.js +34 -16
- package/dist/commands/recipes/impl/commands/active.d.ts +6 -0
- package/dist/commands/recipes/impl/commands/active.d.ts.map +1 -0
- package/dist/commands/recipes/impl/commands/active.js +47 -0
- package/dist/commands/recipes/impl/commands/add.d.ts +8 -0
- package/dist/commands/recipes/impl/commands/add.d.ts.map +1 -0
- package/dist/commands/recipes/impl/commands/add.js +105 -0
- package/dist/commands/recipes/impl/commands/detach.d.ts +6 -0
- package/dist/commands/recipes/impl/commands/detach.d.ts.map +1 -0
- package/dist/commands/recipes/impl/commands/detach.js +99 -0
- package/dist/commands/recipes/impl/commands/disable.d.ts +6 -0
- package/dist/commands/recipes/impl/commands/disable.d.ts.map +1 -0
- package/dist/commands/recipes/impl/commands/disable.js +23 -0
- package/dist/commands/recipes/impl/commands/enable.d.ts +6 -0
- package/dist/commands/recipes/impl/commands/enable.d.ts.map +1 -0
- package/dist/commands/recipes/impl/commands/enable.js +41 -0
- package/dist/commands/recipes/impl/commands/explain-active.d.ts +5 -0
- package/dist/commands/recipes/impl/commands/explain-active.d.ts.map +1 -0
- package/dist/commands/recipes/impl/commands/explain-active.js +20 -0
- package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/explain.js +83 -36
- package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/info.js +39 -22
- package/dist/commands/recipes/impl/commands/install.d.ts +1 -1
- package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +35 -42
- package/dist/commands/recipes/impl/commands/list-remote.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list-remote.js +2 -3
- package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list.js +13 -12
- package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/remove.js +12 -2
- package/dist/commands/recipes/impl/commands/update.d.ts +7 -0
- package/dist/commands/recipes/impl/commands/update.d.ts.map +1 -0
- package/dist/commands/recipes/impl/commands/update.js +107 -0
- package/dist/commands/recipes/impl/commands.d.ts +7 -0
- package/dist/commands/recipes/impl/commands.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands.js +7 -0
- package/dist/commands/recipes/impl/constants.d.ts +1 -14
- package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
- package/dist/commands/recipes/impl/constants.js +1 -18
- package/dist/commands/recipes/impl/index.d.ts +1 -1
- package/dist/commands/recipes/impl/index.d.ts.map +1 -1
- package/dist/commands/recipes/impl/installed-recipes.d.ts +1 -1
- package/dist/commands/recipes/impl/installed-recipes.d.ts.map +1 -1
- package/dist/commands/recipes/impl/installed-recipes.js +1 -2
- package/dist/commands/recipes/impl/mutation-transaction.d.ts +7 -0
- package/dist/commands/recipes/impl/mutation-transaction.d.ts.map +1 -0
- package/dist/commands/recipes/impl/mutation-transaction.js +47 -0
- package/dist/commands/recipes/impl/overlay-project.d.ts +48 -0
- package/dist/commands/recipes/impl/overlay-project.d.ts.map +1 -0
- package/dist/commands/recipes/impl/overlay-project.js +320 -0
- package/dist/commands/recipes/impl/paths.d.ts +17 -2
- package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
- package/dist/commands/recipes/impl/paths.js +20 -5
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts +5 -4
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -1
- package/dist/commands/recipes/impl/project-installed-recipes.js +34 -76
- package/dist/commands/recipes/impl/project-recipe-state.d.ts +18 -0
- package/dist/commands/recipes/impl/project-recipe-state.d.ts.map +1 -0
- package/dist/commands/recipes/impl/project-recipe-state.js +94 -0
- package/dist/commands/recipes/impl/project-registry.d.ts +24 -0
- package/dist/commands/recipes/impl/project-registry.d.ts.map +1 -0
- package/dist/commands/recipes/impl/project-registry.js +124 -0
- package/dist/commands/recipes/impl/resolver.d.ts +1 -1
- package/dist/commands/recipes/impl/resolver.d.ts.map +1 -1
- package/dist/commands/recipes/impl/resolver.js +6 -4
- package/dist/commands/recipes/impl/types.d.ts +1 -240
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/recipes/impl/version.d.ts +5 -0
- package/dist/commands/recipes/impl/version.d.ts.map +1 -0
- package/dist/commands/recipes/impl/version.js +9 -0
- package/dist/commands/recipes/info.command.js +2 -2
- package/dist/commands/recipes/install.spec.js +4 -4
- package/dist/commands/recipes/list.command.js +4 -4
- package/dist/commands/recipes/remove.command.js +2 -2
- package/dist/commands/recipes/update.command.d.ts +8 -0
- package/dist/commands/recipes/update.command.d.ts.map +1 -0
- package/dist/commands/recipes/update.command.js +35 -0
- package/dist/commands/recipes.d.ts +10 -6
- package/dist/commands/recipes.d.ts.map +1 -1
- package/dist/commands/recipes.js +8 -5
- package/dist/commands/recipes.test-helpers.d.ts +3 -3
- package/dist/commands/recipes.test-helpers.d.ts.map +1 -1
- package/dist/commands/recipes.test-helpers.js +105 -15
- package/dist/commands/release/apply.command.d.ts +1 -1
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +15 -379
- package/dist/commands/release/apply.mutation.d.ts +1 -0
- package/dist/commands/release/apply.mutation.d.ts.map +1 -1
- package/dist/commands/release/apply.mutation.js +24 -1
- package/dist/commands/release/apply.pipeline.d.ts +22 -0
- package/dist/commands/release/apply.pipeline.d.ts.map +1 -0
- package/dist/commands/release/apply.pipeline.js +371 -0
- package/dist/commands/release/apply.preflight.d.ts +2 -0
- package/dist/commands/release/apply.preflight.d.ts.map +1 -1
- package/dist/commands/release/apply.preflight.js +13 -4
- package/dist/commands/release/apply.types.d.ts +27 -0
- package/dist/commands/release/apply.types.d.ts.map +1 -1
- package/dist/commands/release.test-helpers.d.ts +4 -0
- package/dist/commands/release.test-helpers.d.ts.map +1 -1
- package/dist/commands/release.test-helpers.js +7 -0
- package/dist/commands/scenario/execute.command.js +4 -4
- package/dist/commands/scenario/impl/commands.js +4 -4
- package/dist/commands/scenario/info.command.js +4 -4
- package/dist/commands/scenario/list.command.js +3 -3
- package/dist/commands/scenario/run.command.js +5 -5
- package/dist/commands/scenario/scenario.command.js +7 -7
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
- package/dist/commands/shared/reconcile-check.js +2 -2
- package/dist/commands/shared/task-backend.d.ts +6 -1
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +34 -2
- package/dist/commands/shared/task-handoff.d.ts +2 -1
- package/dist/commands/shared/task-handoff.d.ts.map +1 -1
- package/dist/commands/shared/task-handoff.js +15 -0
- package/dist/commands/shared/task-mutation.d.ts.map +1 -1
- package/dist/commands/shared/task-mutation.js +4 -4
- package/dist/commands/shared/task-store/intents.d.ts +34 -0
- package/dist/commands/shared/task-store/intents.d.ts.map +1 -0
- package/dist/commands/shared/task-store/intents.js +265 -0
- package/dist/commands/shared/task-store/readme.d.ts +28 -0
- package/dist/commands/shared/task-store/readme.d.ts.map +1 -0
- package/dist/commands/shared/task-store/readme.js +125 -0
- package/dist/commands/shared/task-store/store.d.ts +26 -0
- package/dist/commands/shared/task-store/store.d.ts.map +1 -0
- package/dist/commands/shared/task-store/store.js +105 -0
- package/dist/commands/shared/task-store/types.d.ts +94 -0
- package/dist/commands/shared/task-store/types.d.ts.map +1 -0
- package/dist/commands/shared/task-store/types.js +1 -0
- package/dist/commands/shared/task-store.d.ts +3 -109
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +2 -493
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +7 -2
- package/dist/commands/task/comment.d.ts.map +1 -1
- package/dist/commands/task/comment.js +7 -2
- package/dist/commands/task/finish-shared.d.ts.map +1 -1
- package/dist/commands/task/finish-shared.js +3 -3
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +102 -15
- package/dist/commands/task/handoff-show.command.d.ts.map +1 -1
- package/dist/commands/task/handoff-show.command.js +24 -0
- package/dist/commands/task/hosted-merge-sync.d.ts.map +1 -1
- package/dist/commands/task/hosted-merge-sync.js +9 -4
- package/dist/commands/task/list.run.d.ts.map +1 -1
- package/dist/commands/task/list.run.js +14 -4
- package/dist/commands/task/new.command.d.ts.map +1 -1
- package/dist/commands/task/new.command.js +16 -2
- package/dist/commands/task/new.js +2 -2
- package/dist/commands/task/show.d.ts.map +1 -1
- package/dist/commands/task/show.js +3 -3
- package/dist/commands/task/update.d.ts.map +1 -1
- package/dist/commands/task/update.js +11 -3
- package/dist/runner/adapters/codex.d.ts.map +1 -1
- package/dist/runner/adapters/codex.js +3 -33
- package/dist/runner/adapters/custom.d.ts.map +1 -1
- package/dist/runner/adapters/custom.js +3 -30
- package/dist/runner/adapters/runtime-shared.d.ts +14 -0
- package/dist/runner/adapters/runtime-shared.d.ts.map +1 -0
- package/dist/runner/adapters/runtime-shared.js +36 -0
- package/dist/runner/context/base-prompt-sources.d.ts +30 -0
- package/dist/runner/context/base-prompt-sources.d.ts.map +1 -0
- package/dist/runner/context/base-prompt-sources.js +144 -0
- package/dist/runner/context/base-prompts.d.ts +5 -23
- package/dist/runner/context/base-prompts.d.ts.map +1 -1
- package/dist/runner/context/base-prompts.js +10 -358
- package/dist/runner/context/overlay-prompt-blocks.d.ts +7 -0
- package/dist/runner/context/overlay-prompt-blocks.d.ts.map +1 -0
- package/dist/runner/context/overlay-prompt-blocks.js +72 -0
- package/dist/runner/context/prompt-block-shared.d.ts +54 -0
- package/dist/runner/context/prompt-block-shared.d.ts.map +1 -0
- package/dist/runner/context/prompt-block-shared.js +106 -0
- package/dist/runner/context/recipe-context.d.ts +2 -1
- package/dist/runner/context/recipe-context.d.ts.map +1 -1
- package/dist/runner/context/recipe-context.js +41 -8
- package/dist/runner/context/recipe-prompt-blocks.d.ts +6 -0
- package/dist/runner/context/recipe-prompt-blocks.d.ts.map +1 -0
- package/dist/runner/context/recipe-prompt-blocks.js +143 -0
- package/dist/runner/types.d.ts +4 -0
- package/dist/runner/types.d.ts.map +1 -1
- package/dist/runner/usecases/scenario-materialize-task.js +2 -2
- package/dist/runner/usecases/task-run-inspect.js +2 -2
- package/dist/runner/usecases/task-run-lifecycle-shared.js +2 -2
- package/dist/runner/usecases/task-run.d.ts.map +1 -1
- package/dist/runner/usecases/task-run.js +6 -3
- package/dist/runtime/behavior/resolve.d.ts +2 -1
- package/dist/runtime/behavior/resolve.d.ts.map +1 -1
- package/dist/runtime/behavior/resolve.js +25 -5
- package/dist/runtime/behavior/types.d.ts +1 -0
- package/dist/runtime/behavior/types.d.ts.map +1 -1
- package/dist/runtime/capabilities/recipe.d.ts +2 -1
- package/dist/runtime/capabilities/recipe.d.ts.map +1 -1
- package/dist/runtime/capabilities/recipe.js +88 -28
- package/dist/runtime/execution-context.d.ts +63 -0
- package/dist/runtime/execution-context.d.ts.map +1 -0
- package/dist/{usecases/context/resolve-context.js → runtime/execution-context.js} +23 -26
- package/dist/runtime/incidents/advice-strategy.d.ts +15 -0
- package/dist/runtime/incidents/advice-strategy.d.ts.map +1 -0
- package/dist/runtime/incidents/advice-strategy.js +54 -0
- package/dist/runtime/incidents/plan-strategy.d.ts +9 -0
- package/dist/runtime/incidents/plan-strategy.d.ts.map +1 -0
- package/dist/runtime/incidents/plan-strategy.js +205 -0
- package/dist/runtime/incidents/registry-strategy.d.ts +6 -0
- package/dist/runtime/incidents/registry-strategy.d.ts.map +1 -0
- package/dist/runtime/incidents/registry-strategy.js +280 -0
- package/dist/runtime/incidents/resolve.d.ts +3 -25
- package/dist/runtime/incidents/resolve.d.ts.map +1 -1
- package/dist/runtime/incidents/resolve.js +3 -683
- package/dist/runtime/incidents/shared.d.ts +34 -0
- package/dist/runtime/incidents/shared.d.ts.map +1 -0
- package/dist/runtime/incidents/shared.js +171 -0
- package/dist/shared/errors.d.ts +1 -1
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/runtime-source.d.ts.map +1 -1
- package/dist/shared/runtime-source.js +8 -3
- package/dist/testing/cli-harness/recipe-archives.d.ts +28 -0
- package/dist/testing/cli-harness/recipe-archives.d.ts.map +1 -0
- package/dist/testing/cli-harness/recipe-archives.js +374 -0
- package/dist/testing/cli-harness/stdio.d.ts +26 -0
- package/dist/testing/cli-harness/stdio.d.ts.map +1 -0
- package/dist/testing/cli-harness/stdio.js +84 -0
- package/dist/testing/cli-harness.d.ts +25 -0
- package/dist/testing/cli-harness.d.ts.map +1 -0
- package/dist/testing/cli-harness.js +313 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +1 -0
- package/package.json +7 -3
- package/dist/cli/recipes-bundled.d.ts +0 -10
- package/dist/cli/recipes-bundled.d.ts.map +0 -1
- package/dist/cli/recipes-bundled.js +0 -36
- package/dist/commands/recipes/impl/manifest.d.ts +0 -4
- package/dist/commands/recipes/impl/manifest.d.ts.map +0 -1
- package/dist/commands/recipes/impl/manifest.js +0 -229
- package/dist/commands/recipes/impl/normalize.d.ts +0 -8
- package/dist/commands/recipes/impl/normalize.d.ts.map +0 -1
- package/dist/commands/recipes/impl/normalize.js +0 -54
- package/dist/commands/recipes/impl/scenario.d.ts +0 -16
- package/dist/commands/recipes/impl/scenario.d.ts.map +0 -1
- package/dist/commands/recipes/impl/scenario.js +0 -262
- package/dist/recipes/bundled-recipes.d.ts +0 -17
- package/dist/recipes/bundled-recipes.d.ts.map +0 -1
- package/dist/recipes/bundled-recipes.js +0 -15
- package/dist/usecases/context/resolve-context.d.ts +0 -68
- package/dist/usecases/context/resolve-context.d.ts.map +0 -1
- package/dist/usecases/task/task-list-usecase.d.ts +0 -9
- package/dist/usecases/task/task-list-usecase.d.ts.map +0 -1
- package/dist/usecases/task/task-list-usecase.js +0 -17
- package/dist/usecases/task/task-new-usecase.d.ts +0 -9
- package/dist/usecases/task/task-new-usecase.d.ts.map +0 -1
- package/dist/usecases/task/task-new-usecase.js +0 -17
|
@@ -1,766 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
|
-
import { access, cp, mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
-
import os from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { promisify } from "node:util";
|
|
8
|
-
import { gzipSync } from "node:zlib";
|
|
9
|
-
import { afterAll, afterEach, beforeAll, beforeEach, expect, vi } from "vitest";
|
|
10
|
-
import { defaultConfig } from "@agentplaneorg/core";
|
|
11
|
-
import { runCli } from "./run-cli.js";
|
|
12
|
-
const execFileAsync = promisify(execFile);
|
|
13
|
-
let agentplaneHome = null;
|
|
14
|
-
const testRoots = new Set();
|
|
15
|
-
const originalAgentplaneHome = process.env.AGENTPLANE_HOME;
|
|
16
|
-
const originalNoUpdateCheck = process.env.AGENTPLANE_NO_UPDATE_CHECK;
|
|
17
|
-
const originalGitAuthorName = process.env.GIT_AUTHOR_NAME;
|
|
18
|
-
const originalGitAuthorEmail = process.env.GIT_AUTHOR_EMAIL;
|
|
19
|
-
const originalGitCommitterName = process.env.GIT_COMMITTER_NAME;
|
|
20
|
-
const originalGitCommitterEmail = process.env.GIT_COMMITTER_EMAIL;
|
|
21
|
-
const originalHookRunner = process.env.AGENTPLANE_HOOK_RUNNER;
|
|
22
|
-
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
23
|
-
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
24
|
-
let stdioSilenceDepth = 0;
|
|
25
|
-
const recipeArchiveCache = new Map();
|
|
26
|
-
let gitTemplateRoot = null;
|
|
27
|
-
let gitTemplatePromise = null;
|
|
28
|
-
async function ensureGitTemplateRoot() {
|
|
29
|
-
if (gitTemplateRoot)
|
|
30
|
-
return gitTemplateRoot;
|
|
31
|
-
gitTemplatePromise ??= (async () => {
|
|
32
|
-
const root = await mkdtemp(path.join(os.tmpdir(), "agentplane-git-template-"));
|
|
33
|
-
await execFileAsync("git", ["init", "-q"], { cwd: root, env: cleanGitEnv() });
|
|
34
|
-
// Tests must not rely on global git config. Configure author identity locally
|
|
35
|
-
// so any helper that creates commits works in CI.
|
|
36
|
-
await execFileAsync("git", ["config", "user.email", "agentplane-test@example.com"], {
|
|
37
|
-
cwd: root,
|
|
38
|
-
env: cleanGitEnv(),
|
|
39
|
-
});
|
|
40
|
-
await execFileAsync("git", ["config", "user.name", "agentplane-test"], {
|
|
41
|
-
cwd: root,
|
|
42
|
-
env: cleanGitEnv(),
|
|
43
|
-
});
|
|
44
|
-
return root;
|
|
45
|
-
})();
|
|
46
|
-
gitTemplateRoot = await gitTemplatePromise;
|
|
47
|
-
return gitTemplateRoot;
|
|
48
|
-
}
|
|
49
|
-
async function copyDirContents(src, dest) {
|
|
50
|
-
const entries = await readdir(src, { withFileTypes: true });
|
|
51
|
-
await Promise.all(entries.map((entry) => cp(path.join(src, entry.name), path.join(dest, entry.name), { recursive: true })));
|
|
52
|
-
}
|
|
53
|
-
export function registerAgentplaneHome() {
|
|
54
|
-
beforeAll(async () => {
|
|
55
|
-
agentplaneHome = await mkdtemp(path.join(os.tmpdir(), "agentplane-home-"));
|
|
56
|
-
process.env.AGENTPLANE_HOME = agentplaneHome;
|
|
57
|
-
process.env.AGENTPLANE_NO_UPDATE_CHECK = "1";
|
|
58
|
-
process.env.AGENTPLANE_HOOK_RUNNER ??= path.join(process.cwd(), "packages", "agentplane", "bin", "agentplane.js");
|
|
59
|
-
// Keep tests hermetic: never rely on global git config for commit authorship.
|
|
60
|
-
process.env.GIT_AUTHOR_NAME ??= "agentplane-test";
|
|
61
|
-
process.env.GIT_AUTHOR_EMAIL ??= "agentplane-test@example.com";
|
|
62
|
-
process.env.GIT_COMMITTER_NAME ??= "agentplane-test";
|
|
63
|
-
process.env.GIT_COMMITTER_EMAIL ??= "agentplane-test@example.com";
|
|
64
|
-
});
|
|
65
|
-
afterAll(async () => {
|
|
66
|
-
if (agentplaneHome) {
|
|
67
|
-
await rm(agentplaneHome, { recursive: true, force: true });
|
|
68
|
-
}
|
|
69
|
-
if (originalAgentplaneHome === undefined) {
|
|
70
|
-
delete process.env.AGENTPLANE_HOME;
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
process.env.AGENTPLANE_HOME = originalAgentplaneHome;
|
|
74
|
-
}
|
|
75
|
-
if (originalNoUpdateCheck === undefined) {
|
|
76
|
-
delete process.env.AGENTPLANE_NO_UPDATE_CHECK;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
process.env.AGENTPLANE_NO_UPDATE_CHECK = originalNoUpdateCheck;
|
|
80
|
-
}
|
|
81
|
-
if (originalGitAuthorName === undefined)
|
|
82
|
-
delete process.env.GIT_AUTHOR_NAME;
|
|
83
|
-
else
|
|
84
|
-
process.env.GIT_AUTHOR_NAME = originalGitAuthorName;
|
|
85
|
-
if (originalGitAuthorEmail === undefined)
|
|
86
|
-
delete process.env.GIT_AUTHOR_EMAIL;
|
|
87
|
-
else
|
|
88
|
-
process.env.GIT_AUTHOR_EMAIL = originalGitAuthorEmail;
|
|
89
|
-
if (originalGitCommitterName === undefined)
|
|
90
|
-
delete process.env.GIT_COMMITTER_NAME;
|
|
91
|
-
else
|
|
92
|
-
process.env.GIT_COMMITTER_NAME = originalGitCommitterName;
|
|
93
|
-
if (originalGitCommitterEmail === undefined)
|
|
94
|
-
delete process.env.GIT_COMMITTER_EMAIL;
|
|
95
|
-
else
|
|
96
|
-
process.env.GIT_COMMITTER_EMAIL = originalGitCommitterEmail;
|
|
97
|
-
if (originalHookRunner === undefined)
|
|
98
|
-
delete process.env.AGENTPLANE_HOOK_RUNNER;
|
|
99
|
-
else
|
|
100
|
-
process.env.AGENTPLANE_HOOK_RUNNER = originalHookRunner;
|
|
101
|
-
});
|
|
102
|
-
afterEach(async () => {
|
|
103
|
-
const roots = [...testRoots];
|
|
104
|
-
testRoots.clear();
|
|
105
|
-
await Promise.all(roots.map(async (root) => {
|
|
106
|
-
await rm(path.join(root, ".agentplane", ".upgrade"), { recursive: true, force: true });
|
|
107
|
-
await rm(path.join(root, ".agentplane", ".release"), { recursive: true, force: true });
|
|
108
|
-
}));
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
export function installRunCliIntegrationHarness() {
|
|
112
|
-
registerAgentplaneHome();
|
|
113
|
-
let restoreStdIO = null;
|
|
114
|
-
beforeEach(() => {
|
|
115
|
-
restoreStdIO = silenceStdIO();
|
|
116
|
-
});
|
|
117
|
-
afterEach(() => {
|
|
118
|
-
restoreStdIO?.();
|
|
119
|
-
restoreStdIO = null;
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
export function getAgentplaneHome() {
|
|
123
|
-
return agentplaneHome;
|
|
124
|
-
}
|
|
125
|
-
export function captureStdIO() {
|
|
126
|
-
let stdout = "";
|
|
127
|
-
let stderr = "";
|
|
128
|
-
const origStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
129
|
-
const origStderrWrite = process.stderr.write.bind(process.stderr);
|
|
130
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
131
|
-
process.stdout.write = (chunk) => {
|
|
132
|
-
stdout += String(chunk);
|
|
133
|
-
return true;
|
|
134
|
-
};
|
|
135
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
136
|
-
process.stderr.write = (chunk) => {
|
|
137
|
-
stderr += String(chunk);
|
|
138
|
-
return true;
|
|
139
|
-
};
|
|
140
|
-
return {
|
|
141
|
-
get stdout() {
|
|
142
|
-
return stdout;
|
|
143
|
-
},
|
|
144
|
-
get stderr() {
|
|
145
|
-
return stderr;
|
|
146
|
-
},
|
|
147
|
-
restore() {
|
|
148
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
149
|
-
process.stdout.write = origStdoutWrite;
|
|
150
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
151
|
-
process.stderr.write = origStderrWrite;
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
export function splitOutputLines(text) {
|
|
156
|
-
return text
|
|
157
|
-
.trim()
|
|
158
|
-
.split(/\r?\n/)
|
|
159
|
-
.map((line) => line.trimEnd())
|
|
160
|
-
.filter(Boolean);
|
|
161
|
-
}
|
|
162
|
-
export function parseAgentJsonEnvelope(stdout) {
|
|
163
|
-
return JSON.parse(stdout);
|
|
164
|
-
}
|
|
165
|
-
export function expectAgentJsonEnvelope(payload, opts) {
|
|
166
|
-
expect(payload.schema_version).toBe(1);
|
|
167
|
-
expect(payload.mode).toBe("agent_json_v1");
|
|
168
|
-
expect(payload.command).toBe(opts.command);
|
|
169
|
-
expect(payload.ok).toBe(opts.ok);
|
|
170
|
-
expect(payload.exit_code).toBe(opts.exitCode);
|
|
171
|
-
expect(Object.keys(payload)).toEqual(opts.hasData
|
|
172
|
-
? ["schema_version", "mode", "command", "ok", "exit_code", "stdout", "stderr", "data"]
|
|
173
|
-
: ["schema_version", "mode", "command", "ok", "exit_code", "stdout", "stderr"]);
|
|
174
|
-
expect(Object.hasOwn(payload, "data")).toBe(opts.hasData ?? false);
|
|
175
|
-
}
|
|
176
|
-
export function silenceStdIO() {
|
|
177
|
-
if (stdioSilenceDepth === 0) {
|
|
178
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
179
|
-
process.stdout.write = () => true;
|
|
180
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
181
|
-
process.stderr.write = () => true;
|
|
182
|
-
}
|
|
183
|
-
stdioSilenceDepth += 1;
|
|
184
|
-
return () => {
|
|
185
|
-
stdioSilenceDepth -= 1;
|
|
186
|
-
if (stdioSilenceDepth <= 0) {
|
|
187
|
-
stdioSilenceDepth = 0;
|
|
188
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
189
|
-
process.stdout.write = originalStdoutWrite;
|
|
190
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
191
|
-
process.stderr.write = originalStderrWrite;
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
export function stubTaskBackend(overrides = {}) {
|
|
196
|
-
return {
|
|
197
|
-
id: "local",
|
|
198
|
-
capabilities: {
|
|
199
|
-
canonical_source: "local",
|
|
200
|
-
projection: "canonical",
|
|
201
|
-
projection_read_mode: "fallback",
|
|
202
|
-
reads_from_projection_by_default: false,
|
|
203
|
-
writes_task_readmes: true,
|
|
204
|
-
supports_task_revisions: true,
|
|
205
|
-
supports_revision_guarded_writes: true,
|
|
206
|
-
may_access_network_on_read: false,
|
|
207
|
-
may_access_network_on_write: false,
|
|
208
|
-
supports_projection_refresh: false,
|
|
209
|
-
supports_push_sync: false,
|
|
210
|
-
supports_snapshot_export: false,
|
|
211
|
-
},
|
|
212
|
-
listTasks: vi.fn().mockResolvedValue([]),
|
|
213
|
-
getTask: vi.fn().mockResolvedValue(null),
|
|
214
|
-
writeTask: vi.fn().mockImplementation(() => Promise.resolve()),
|
|
215
|
-
...overrides,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
export async function runCliSilent(args) {
|
|
219
|
-
const io = captureStdIO();
|
|
220
|
-
try {
|
|
221
|
-
return await runCli(args);
|
|
222
|
-
}
|
|
223
|
-
finally {
|
|
224
|
-
io.restore();
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
export async function mkGitRepoRoot() {
|
|
228
|
-
const template = await ensureGitTemplateRoot();
|
|
229
|
-
const root = await mkdtemp(path.join(os.tmpdir(), "agentplane-cli-test-"));
|
|
230
|
-
await copyDirContents(template, root);
|
|
231
|
-
testRoots.add(root);
|
|
232
|
-
return root;
|
|
233
|
-
}
|
|
234
|
-
export async function mkTempDir() {
|
|
235
|
-
const root = await mkdtemp(path.join(os.tmpdir(), "agentplane-cli-test-"));
|
|
236
|
-
testRoots.add(root);
|
|
237
|
-
return root;
|
|
238
|
-
}
|
|
239
|
-
export async function writeDefaultConfig(root) {
|
|
240
|
-
const agentplaneDir = path.join(root, ".agentplane");
|
|
241
|
-
await mkdir(agentplaneDir, { recursive: true });
|
|
242
|
-
const configPath = path.join(agentplaneDir, "config.json");
|
|
243
|
-
await writeFile(configPath, JSON.stringify(defaultConfig(), null, 2), "utf8");
|
|
244
|
-
}
|
|
245
|
-
export async function writeAndConfigureRoot() {
|
|
246
|
-
const root = await mkGitRepoRoot();
|
|
247
|
-
await writeDefaultConfig(root);
|
|
248
|
-
return root;
|
|
249
|
-
}
|
|
250
|
-
export async function approveTaskPlan(root, taskId) {
|
|
251
|
-
await runCliSilent([
|
|
252
|
-
"task",
|
|
253
|
-
"plan",
|
|
254
|
-
"set",
|
|
255
|
-
taskId,
|
|
256
|
-
"--text",
|
|
257
|
-
"1) Do the work\n2) Verify the work",
|
|
258
|
-
"--updated-by",
|
|
259
|
-
"ORCHESTRATOR",
|
|
260
|
-
"--root",
|
|
261
|
-
root,
|
|
262
|
-
]);
|
|
263
|
-
await runCliSilent([
|
|
264
|
-
"task",
|
|
265
|
-
"plan",
|
|
266
|
-
"approve",
|
|
267
|
-
taskId,
|
|
268
|
-
"--by",
|
|
269
|
-
"USER",
|
|
270
|
-
"--note",
|
|
271
|
-
"OK",
|
|
272
|
-
"--root",
|
|
273
|
-
root,
|
|
274
|
-
]);
|
|
275
|
-
}
|
|
276
|
-
export async function recordVerificationOk(root, taskId) {
|
|
277
|
-
await runCliSilent([
|
|
278
|
-
"task",
|
|
279
|
-
"doc",
|
|
280
|
-
"set",
|
|
281
|
-
taskId,
|
|
282
|
-
"--section",
|
|
283
|
-
"Verify Steps",
|
|
284
|
-
"--text",
|
|
285
|
-
"Run verify for this task. Expected: verification records successfully.",
|
|
286
|
-
"--root",
|
|
287
|
-
root,
|
|
288
|
-
]);
|
|
289
|
-
await runCliSilent([
|
|
290
|
-
"verify",
|
|
291
|
-
taskId,
|
|
292
|
-
"--ok",
|
|
293
|
-
"--by",
|
|
294
|
-
"REVIEWER",
|
|
295
|
-
"--note",
|
|
296
|
-
"Ok to integrate",
|
|
297
|
-
"--quiet",
|
|
298
|
-
"--root",
|
|
299
|
-
root,
|
|
300
|
-
]);
|
|
301
|
-
}
|
|
302
|
-
export async function writeConfig(root, config) {
|
|
303
|
-
const agentplaneDir = path.join(root, ".agentplane");
|
|
304
|
-
await mkdir(agentplaneDir, { recursive: true });
|
|
305
|
-
const configPath = path.join(agentplaneDir, "config.json");
|
|
306
|
-
await writeFile(configPath, JSON.stringify(config, null, 2), "utf8");
|
|
307
|
-
}
|
|
308
|
-
export async function resetAgentplaneHomeRecipes() {
|
|
309
|
-
if (!agentplaneHome)
|
|
310
|
-
return;
|
|
311
|
-
await rm(path.join(agentplaneHome, "recipes"), { recursive: true, force: true });
|
|
312
|
-
await rm(path.join(agentplaneHome, "recipes.json"), { force: true });
|
|
313
|
-
await rm(path.join(agentplaneHome, "recipes-index.json"), { force: true });
|
|
314
|
-
}
|
|
315
|
-
export async function createRecipeArchive(opts) {
|
|
316
|
-
const normalizedTags = opts?.tags ? [...opts.tags].toSorted() : undefined;
|
|
317
|
-
const cacheKey = JSON.stringify({
|
|
318
|
-
id: opts?.id ?? "viewer",
|
|
319
|
-
version: opts?.version ?? "1.2.3",
|
|
320
|
-
name: opts?.name ?? "Viewer",
|
|
321
|
-
summary: opts?.summary ?? "Preview task artifacts",
|
|
322
|
-
description: opts?.description ?? "Provides a local viewer for task artifacts.",
|
|
323
|
-
tags: normalizedTags,
|
|
324
|
-
format: opts?.format ?? "tar",
|
|
325
|
-
wrapDir: opts?.wrapDir ?? false,
|
|
326
|
-
});
|
|
327
|
-
const cached = recipeArchiveCache.get(cacheKey);
|
|
328
|
-
if (cached)
|
|
329
|
-
return cached;
|
|
330
|
-
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-recipe-"));
|
|
331
|
-
const recipeDir = path.join(baseDir, opts?.wrapDir ? "bundle" : "recipe");
|
|
332
|
-
await mkdir(recipeDir, { recursive: true });
|
|
333
|
-
const manifest = {
|
|
334
|
-
schema_version: "1",
|
|
335
|
-
id: opts?.id ?? "viewer",
|
|
336
|
-
version: opts?.version ?? "1.2.3",
|
|
337
|
-
name: opts?.name ?? "Viewer",
|
|
338
|
-
summary: opts?.summary ?? "Preview task artifacts",
|
|
339
|
-
description: opts?.description ?? "Provides a local viewer for task artifacts.",
|
|
340
|
-
compatibility: {
|
|
341
|
-
min_agentplane_version: "0.3.5",
|
|
342
|
-
manifest_api_version: "1",
|
|
343
|
-
scenario_api_version: "1",
|
|
344
|
-
runtime_api_version: "1",
|
|
345
|
-
platforms: ["darwin", "linux"],
|
|
346
|
-
repo_types: ["generic"],
|
|
347
|
-
},
|
|
348
|
-
skills: [
|
|
349
|
-
{
|
|
350
|
-
id: "RECIPE_SKILL",
|
|
351
|
-
summary: "Recipe analysis skill",
|
|
352
|
-
kind: "agent-skill",
|
|
353
|
-
file: "skills/analysis.json",
|
|
354
|
-
},
|
|
355
|
-
],
|
|
356
|
-
agents: [
|
|
357
|
-
{
|
|
358
|
-
id: "RECIPE_AGENT",
|
|
359
|
-
display_name: "Recipe Agent",
|
|
360
|
-
role: "executor",
|
|
361
|
-
summary: "Recipe agent",
|
|
362
|
-
skills: ["RECIPE_SKILL"],
|
|
363
|
-
tools: ["RECIPE_TOOL"],
|
|
364
|
-
file: "agents/recipe.json",
|
|
365
|
-
},
|
|
366
|
-
],
|
|
367
|
-
tools: [
|
|
368
|
-
{ id: "RECIPE_TOOL", summary: "Recipe tool", runtime: "node", entrypoint: "tools/run.js" },
|
|
369
|
-
],
|
|
370
|
-
scenarios: [
|
|
371
|
-
{
|
|
372
|
-
id: "RECIPE_SCENARIO",
|
|
373
|
-
name: "Recipe Scenario",
|
|
374
|
-
summary: "Recipe scenario",
|
|
375
|
-
use_when: ["Task artifacts need local preview"],
|
|
376
|
-
required_inputs: ["task_id"],
|
|
377
|
-
outputs: ["report"],
|
|
378
|
-
permissions: ["filesystem-write"],
|
|
379
|
-
artifacts: ["artifact.txt"],
|
|
380
|
-
agents_involved: ["RECIPE_AGENT"],
|
|
381
|
-
skills_used: ["RECIPE_SKILL"],
|
|
382
|
-
tools_used: ["RECIPE_TOOL"],
|
|
383
|
-
run_profile: {
|
|
384
|
-
mode: "analysis",
|
|
385
|
-
sandbox: "workspace-write",
|
|
386
|
-
writes_artifacts_to: ["logs/", "reports/"],
|
|
387
|
-
},
|
|
388
|
-
file: "scenarios/recipe-scenario.json",
|
|
389
|
-
},
|
|
390
|
-
],
|
|
391
|
-
};
|
|
392
|
-
if (normalizedTags) {
|
|
393
|
-
manifest.tags = normalizedTags;
|
|
394
|
-
}
|
|
395
|
-
await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
396
|
-
const agentsDir = path.join(recipeDir, "agents");
|
|
397
|
-
await mkdir(agentsDir, { recursive: true });
|
|
398
|
-
await writeFile(path.join(agentsDir, "recipe.json"), JSON.stringify({
|
|
399
|
-
id: "RECIPE_AGENT",
|
|
400
|
-
role: "Recipe agent",
|
|
401
|
-
description: "Example agent installed from a recipe.",
|
|
402
|
-
}, null, 2), "utf8");
|
|
403
|
-
const skillsDir = path.join(recipeDir, "skills");
|
|
404
|
-
await mkdir(skillsDir, { recursive: true });
|
|
405
|
-
await writeFile(path.join(skillsDir, "analysis.json"), JSON.stringify({
|
|
406
|
-
id: "RECIPE_SKILL",
|
|
407
|
-
summary: "Recipe analysis skill",
|
|
408
|
-
kind: "agent-skill",
|
|
409
|
-
}, null, 2), "utf8");
|
|
410
|
-
const toolsDir = path.join(recipeDir, "tools");
|
|
411
|
-
await mkdir(toolsDir, { recursive: true });
|
|
412
|
-
await writeFile(path.join(toolsDir, "run.js"), [
|
|
413
|
-
'const fs = require("node:fs");',
|
|
414
|
-
'fs.writeFileSync(process.env.AGENTPLANE_RUN_DIR + "/artifact.txt", "ok");',
|
|
415
|
-
].join("\n"), "utf8");
|
|
416
|
-
const scenariosDir = path.join(recipeDir, "scenarios");
|
|
417
|
-
await mkdir(scenariosDir, { recursive: true });
|
|
418
|
-
await writeFile(path.join(scenariosDir, "recipe-scenario.json"), JSON.stringify({
|
|
419
|
-
schema_version: "1",
|
|
420
|
-
id: "RECIPE_SCENARIO",
|
|
421
|
-
summary: "Recipe scenario",
|
|
422
|
-
goal: "Preview installed tasks.",
|
|
423
|
-
task_template: {
|
|
424
|
-
title: "Recipe scenario task",
|
|
425
|
-
description: "Materialize a task from the recipe scenario.",
|
|
426
|
-
owner: "CODER",
|
|
427
|
-
priority: "med",
|
|
428
|
-
tags: ["code", "recipes"],
|
|
429
|
-
verify: ["bunx vitest run packages/agentplane/src/cli/run-cli.scenario.test.ts"],
|
|
430
|
-
doc: {
|
|
431
|
-
summary: "Recipe-backed task execution.",
|
|
432
|
-
scope: "Run the scenario without task materialization heuristics.",
|
|
433
|
-
plan: "1. Materialize the task. 2. Execute the shared runner.",
|
|
434
|
-
verify_steps: "1. Run scenario execution tests.",
|
|
435
|
-
rollback_plan: "Revert the generated task and runner artifacts.",
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
inputs: [{ name: "task_id", type: "string" }],
|
|
439
|
-
outputs: [{ name: "report", type: "html" }],
|
|
440
|
-
steps: [{ tool: "RECIPE_TOOL" }],
|
|
441
|
-
}, null, 2), "utf8");
|
|
442
|
-
const format = opts?.format ?? "tar";
|
|
443
|
-
const archivePath = format === "zip" ? path.join(baseDir, "recipe.zip") : path.join(baseDir, "recipe.tar.gz");
|
|
444
|
-
if (format === "zip") {
|
|
445
|
-
await (opts?.wrapDir
|
|
446
|
-
? execFileAsync("zip", ["-qr", archivePath, path.basename(recipeDir)], { cwd: baseDir })
|
|
447
|
-
: execFileAsync("zip", ["-qr", archivePath, "."], { cwd: recipeDir }));
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
450
|
-
await (opts?.wrapDir
|
|
451
|
-
? execFileAsync("tar", ["-czf", archivePath, "-C", baseDir, path.basename(recipeDir)])
|
|
452
|
-
: execFileAsync("tar", ["-czf", archivePath, "-C", recipeDir, "."]));
|
|
453
|
-
}
|
|
454
|
-
const payload = { archivePath, manifest };
|
|
455
|
-
recipeArchiveCache.set(cacheKey, payload);
|
|
456
|
-
return payload;
|
|
457
|
-
}
|
|
458
|
-
export async function createRecipeArchiveWithManifest(opts) {
|
|
459
|
-
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-recipe-bad-"));
|
|
460
|
-
const recipeDir = path.join(baseDir, opts.wrapDir ? "bundle" : "recipe");
|
|
461
|
-
await mkdir(recipeDir, { recursive: true });
|
|
462
|
-
await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(opts.manifest, null, 2));
|
|
463
|
-
if (opts.files) {
|
|
464
|
-
for (const [relPath, content] of Object.entries(opts.files)) {
|
|
465
|
-
const fullPath = path.join(recipeDir, relPath);
|
|
466
|
-
await mkdir(path.dirname(fullPath), { recursive: true });
|
|
467
|
-
await writeFile(fullPath, content, "utf8");
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
const format = opts.format ?? "tar";
|
|
471
|
-
const archivePath = format === "zip" ? path.join(baseDir, "recipe.zip") : path.join(baseDir, "recipe.tar.gz");
|
|
472
|
-
if (format === "zip") {
|
|
473
|
-
await (opts.wrapDir
|
|
474
|
-
? execFileAsync("zip", ["-qr", archivePath, path.basename(recipeDir)], { cwd: baseDir })
|
|
475
|
-
: execFileAsync("zip", ["-qr", archivePath, "."], { cwd: recipeDir }));
|
|
476
|
-
}
|
|
477
|
-
else {
|
|
478
|
-
await (opts.wrapDir
|
|
479
|
-
? execFileAsync("tar", ["-czf", archivePath, "-C", baseDir, path.basename(recipeDir)])
|
|
480
|
-
: execFileAsync("tar", ["-czf", archivePath, "-C", recipeDir, "."]));
|
|
481
|
-
}
|
|
482
|
-
return archivePath;
|
|
483
|
-
}
|
|
484
|
-
export async function createUnsafeRecipeArchive(opts) {
|
|
485
|
-
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-recipe-unsafe-"));
|
|
486
|
-
const recipeDir = path.join(baseDir, "recipe");
|
|
487
|
-
await mkdir(recipeDir, { recursive: true });
|
|
488
|
-
const manifest = {
|
|
489
|
-
schema_version: "1",
|
|
490
|
-
id: "unsafe",
|
|
491
|
-
version: "0.0.1",
|
|
492
|
-
name: "Unsafe",
|
|
493
|
-
summary: "Unsafe recipe",
|
|
494
|
-
description: "Used for archive validation tests.",
|
|
495
|
-
skills: [
|
|
496
|
-
{
|
|
497
|
-
id: "RECIPE_SKILL",
|
|
498
|
-
summary: "Recipe skill",
|
|
499
|
-
kind: "agent-skill",
|
|
500
|
-
file: "skills/recipe.json",
|
|
501
|
-
},
|
|
502
|
-
],
|
|
503
|
-
agents: [
|
|
504
|
-
{
|
|
505
|
-
id: "RECIPE_AGENT",
|
|
506
|
-
display_name: "Recipe Agent",
|
|
507
|
-
role: "executor",
|
|
508
|
-
summary: "Recipe agent",
|
|
509
|
-
skills: ["RECIPE_SKILL"],
|
|
510
|
-
tools: ["RECIPE_TOOL"],
|
|
511
|
-
file: "agents/recipe.json",
|
|
512
|
-
},
|
|
513
|
-
],
|
|
514
|
-
tools: [
|
|
515
|
-
{ id: "RECIPE_TOOL", summary: "Recipe tool", runtime: "bash", entrypoint: "tools/run.sh" },
|
|
516
|
-
],
|
|
517
|
-
scenarios: [
|
|
518
|
-
{
|
|
519
|
-
id: "RECIPE_SCENARIO",
|
|
520
|
-
name: "Recipe Scenario",
|
|
521
|
-
summary: "Recipe scenario",
|
|
522
|
-
use_when: ["Unsafe validation fixture"],
|
|
523
|
-
required_inputs: [],
|
|
524
|
-
outputs: [],
|
|
525
|
-
permissions: [],
|
|
526
|
-
artifacts: [],
|
|
527
|
-
agents_involved: ["RECIPE_AGENT"],
|
|
528
|
-
skills_used: ["RECIPE_SKILL"],
|
|
529
|
-
tools_used: ["RECIPE_TOOL"],
|
|
530
|
-
run_profile: { mode: "analysis" },
|
|
531
|
-
file: "scenarios/recipe-scenario.json",
|
|
532
|
-
},
|
|
533
|
-
],
|
|
534
|
-
};
|
|
535
|
-
await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
536
|
-
const agentsDir = path.join(recipeDir, "agents");
|
|
537
|
-
await mkdir(agentsDir, { recursive: true });
|
|
538
|
-
await writeFile(path.join(agentsDir, "recipe.json"), JSON.stringify({ id: "RECIPE_AGENT", role: "Recipe agent" }, null, 2), "utf8");
|
|
539
|
-
const skillsDir = path.join(recipeDir, "skills");
|
|
540
|
-
await mkdir(skillsDir, { recursive: true });
|
|
541
|
-
await writeFile(path.join(skillsDir, "recipe.json"), JSON.stringify({ id: "RECIPE_SKILL" }), "utf8");
|
|
542
|
-
const toolsDir = path.join(recipeDir, "tools");
|
|
543
|
-
await mkdir(toolsDir, { recursive: true });
|
|
544
|
-
await writeFile(path.join(toolsDir, "run.sh"), "#!/usr/bin/env bash\n", "utf8");
|
|
545
|
-
const scenariosDir = path.join(recipeDir, "scenarios");
|
|
546
|
-
await mkdir(scenariosDir, { recursive: true });
|
|
547
|
-
await writeFile(path.join(scenariosDir, "recipe-scenario.json"), JSON.stringify({
|
|
548
|
-
schema_version: "1",
|
|
549
|
-
id: "RECIPE_SCENARIO",
|
|
550
|
-
summary: "Recipe scenario",
|
|
551
|
-
goal: "Exercise unsafe archive validation.",
|
|
552
|
-
task_template: {
|
|
553
|
-
title: "Unsafe archive task",
|
|
554
|
-
description: "Validate unsafe archive handling.",
|
|
555
|
-
owner: "CODER",
|
|
556
|
-
},
|
|
557
|
-
inputs: [],
|
|
558
|
-
outputs: [],
|
|
559
|
-
steps: [{ tool: "RECIPE_TOOL" }],
|
|
560
|
-
}, null, 2), "utf8");
|
|
561
|
-
const entryPath = opts.entryPath ?? "../evil.txt";
|
|
562
|
-
await writeFile(path.join(baseDir, "evil.txt"), "evil", "utf8");
|
|
563
|
-
const archivePath = opts.format === "zip" ? path.join(baseDir, "unsafe.zip") : path.join(baseDir, "unsafe.tar.gz");
|
|
564
|
-
if (opts.format === "zip") {
|
|
565
|
-
await execFileAsync("zip", ["-qr", archivePath, ".", entryPath], { cwd: recipeDir });
|
|
566
|
-
return archivePath;
|
|
567
|
-
}
|
|
568
|
-
// Build a deterministic tar.gz containing a traversal entry, without relying on system tar behavior.
|
|
569
|
-
// This keeps the archive validation tests stable across GNU tar / bsdtar.
|
|
570
|
-
const tar = buildTar([
|
|
571
|
-
{
|
|
572
|
-
name: "./manifest.json",
|
|
573
|
-
data: Buffer.from(JSON.stringify(manifest, null, 2) + "\n", "utf8"),
|
|
574
|
-
},
|
|
575
|
-
{ name: entryPath, data: Buffer.from("evil\n", "utf8") },
|
|
576
|
-
]);
|
|
577
|
-
const gz = gzipSync(tar);
|
|
578
|
-
await writeFile(archivePath, gz);
|
|
579
|
-
return archivePath;
|
|
580
|
-
}
|
|
581
|
-
function buildTar(entries) {
|
|
582
|
-
const out = [];
|
|
583
|
-
for (const ent of entries) {
|
|
584
|
-
const header = tarHeader({
|
|
585
|
-
name: ent.name,
|
|
586
|
-
size: ent.data.length,
|
|
587
|
-
mtime: 0,
|
|
588
|
-
typeflag: "0",
|
|
589
|
-
});
|
|
590
|
-
out.push(header, ent.data, zeroPadTo512(ent.data.length));
|
|
591
|
-
}
|
|
592
|
-
// Two empty blocks mark end-of-archive.
|
|
593
|
-
out.push(Buffer.alloc(1024, 0));
|
|
594
|
-
return Buffer.concat(out);
|
|
595
|
-
}
|
|
596
|
-
function zeroPadTo512(n) {
|
|
597
|
-
const rem = n % 512;
|
|
598
|
-
if (rem === 0)
|
|
599
|
-
return Buffer.alloc(0);
|
|
600
|
-
return Buffer.alloc(512 - rem, 0);
|
|
601
|
-
}
|
|
602
|
-
function tarHeader(opts) {
|
|
603
|
-
const buf = Buffer.alloc(512, 0);
|
|
604
|
-
writeTarString(buf, 0, 100, opts.name);
|
|
605
|
-
writeTarOctal(buf, 100, 8, 0o644); // mode
|
|
606
|
-
writeTarOctal(buf, 108, 8, 0); // uid
|
|
607
|
-
writeTarOctal(buf, 116, 8, 0); // gid
|
|
608
|
-
writeTarOctal(buf, 124, 12, opts.size);
|
|
609
|
-
writeTarOctal(buf, 136, 12, opts.mtime);
|
|
610
|
-
// checksum field must be treated as spaces for calculation
|
|
611
|
-
buf.fill(0x20, 148, 156);
|
|
612
|
-
writeTarString(buf, 156, 1, opts.typeflag);
|
|
613
|
-
writeTarString(buf, 257, 6, "ustar"); // magic
|
|
614
|
-
writeTarString(buf, 263, 2, "00"); // version
|
|
615
|
-
const sum = buf.reduce((acc, b) => acc + b, 0);
|
|
616
|
-
writeTarChecksum(buf, sum);
|
|
617
|
-
return buf;
|
|
618
|
-
}
|
|
619
|
-
function writeTarString(buf, offset, length, value) {
|
|
620
|
-
const b = Buffer.from(value, "utf8");
|
|
621
|
-
b.copy(buf, offset, 0, Math.min(length, b.length));
|
|
622
|
-
}
|
|
623
|
-
function writeTarOctal(buf, offset, length, value) {
|
|
624
|
-
const raw = Math.max(0, value).toString(8);
|
|
625
|
-
const padded = raw.padStart(length - 1, "0") + "\0";
|
|
626
|
-
writeTarString(buf, offset, length, padded);
|
|
627
|
-
}
|
|
628
|
-
function writeTarChecksum(buf, sum) {
|
|
629
|
-
// 6 digits, NUL, space (common convention).
|
|
630
|
-
const raw = Math.max(0, sum).toString(8).padStart(6, "0");
|
|
631
|
-
writeTarString(buf, 148, 8, `${raw}\0 `);
|
|
632
|
-
}
|
|
633
|
-
export async function createUpgradeBundle(files) {
|
|
634
|
-
const manifestUrl = new URL("../../assets/framework.manifest.json", import.meta.url);
|
|
635
|
-
const manifestText = typeof files["framework.manifest.json"] === "string"
|
|
636
|
-
? files["framework.manifest.json"]
|
|
637
|
-
: await readFile(fileURLToPath(manifestUrl), "utf8");
|
|
638
|
-
const manifest = JSON.parse(manifestText);
|
|
639
|
-
const normalizedFiles = {};
|
|
640
|
-
for (const [relPath, content] of Object.entries(files)) {
|
|
641
|
-
// Tests historically authored bundles using workspace-destination paths. Upgrade now reads
|
|
642
|
-
// upstream files via manifest source_path (package assets layout).
|
|
643
|
-
const mapped = relPath.startsWith(".agentplane/agents/")
|
|
644
|
-
? relPath.replace(/^\.agentplane\/agents\//, "agents/")
|
|
645
|
-
: relPath;
|
|
646
|
-
normalizedFiles[mapped] = content;
|
|
647
|
-
}
|
|
648
|
-
// Ensure the bundle always carries its manifest at the root.
|
|
649
|
-
normalizedFiles["framework.manifest.json"] ??= manifestText;
|
|
650
|
-
if (manifest.schema_version === 1 && Array.isArray(manifest.files)) {
|
|
651
|
-
for (const entry of manifest.files) {
|
|
652
|
-
if (!entry?.required)
|
|
653
|
-
continue;
|
|
654
|
-
const sourceRel = (entry.source_path ?? entry.path ?? "").trim();
|
|
655
|
-
if (!sourceRel)
|
|
656
|
-
continue;
|
|
657
|
-
if (normalizedFiles[sourceRel] !== undefined)
|
|
658
|
-
continue;
|
|
659
|
-
if (entry.type === "json")
|
|
660
|
-
normalizedFiles[sourceRel] = "{}\n";
|
|
661
|
-
else if (sourceRel.endsWith(".md"))
|
|
662
|
-
normalizedFiles[sourceRel] = "# AGENTS\n";
|
|
663
|
-
else
|
|
664
|
-
normalizedFiles[sourceRel] = "\n";
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-upgrade-bundle-"));
|
|
668
|
-
const bundleDir = path.join(baseDir, "bundle");
|
|
669
|
-
await mkdir(bundleDir, { recursive: true });
|
|
670
|
-
for (const [relPath, content] of Object.entries(normalizedFiles)) {
|
|
671
|
-
const fullPath = path.join(bundleDir, relPath);
|
|
672
|
-
await mkdir(path.dirname(fullPath), { recursive: true });
|
|
673
|
-
await writeFile(fullPath, content, "utf8");
|
|
674
|
-
}
|
|
675
|
-
const bundlePath = path.join(baseDir, "agentplane-upgrade.tar.gz");
|
|
676
|
-
await execFileAsync("tar", ["-czf", bundlePath, "-C", bundleDir, "."]);
|
|
677
|
-
const checksum = createHash("sha256")
|
|
678
|
-
.update(await readFile(bundlePath))
|
|
679
|
-
.digest("hex");
|
|
680
|
-
const checksumPath = `${bundlePath}.sha256`;
|
|
681
|
-
await writeFile(checksumPath, `${checksum} agentplane-upgrade.tar.gz\n`, "utf8");
|
|
682
|
-
return { bundlePath, checksumPath };
|
|
683
|
-
}
|
|
684
|
-
export async function mkGitRepoRootWithBranch(branch) {
|
|
685
|
-
const root = await mkGitRepoRoot();
|
|
686
|
-
await execFileAsync("git", ["checkout", "-b", branch], { cwd: root, env: cleanGitEnv() });
|
|
687
|
-
return root;
|
|
688
|
-
}
|
|
689
|
-
export async function configureGitUser(root) {
|
|
690
|
-
await execFileAsync("git", ["config", "user.email", "test@example.com"], {
|
|
691
|
-
cwd: root,
|
|
692
|
-
env: cleanGitEnv(),
|
|
693
|
-
});
|
|
694
|
-
await execFileAsync("git", ["config", "user.name", "Test User"], {
|
|
695
|
-
cwd: root,
|
|
696
|
-
env: cleanGitEnv(),
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
export function cleanGitEnv() {
|
|
700
|
-
const env = { ...process.env };
|
|
701
|
-
delete env.GIT_DIR;
|
|
702
|
-
delete env.GIT_WORK_TREE;
|
|
703
|
-
delete env.GIT_COMMON_DIR;
|
|
704
|
-
delete env.GIT_INDEX_FILE;
|
|
705
|
-
delete env.GIT_OBJECT_DIRECTORY;
|
|
706
|
-
delete env.GIT_ALTERNATE_OBJECT_DIRECTORIES;
|
|
707
|
-
env.GIT_CONFIG_GLOBAL = "/dev/null";
|
|
708
|
-
env.GIT_CONFIG_SYSTEM = "/dev/null";
|
|
709
|
-
env.GIT_TERMINAL_PROMPT = "0";
|
|
710
|
-
env.GIT_AUTHOR_NAME = env.GIT_AUTHOR_NAME ?? "Agentplane Test";
|
|
711
|
-
env.GIT_AUTHOR_EMAIL = env.GIT_AUTHOR_EMAIL ?? "agentplane-test@example.com";
|
|
712
|
-
env.GIT_COMMITTER_NAME = env.GIT_COMMITTER_NAME ?? "Agentplane Test";
|
|
713
|
-
env.GIT_COMMITTER_EMAIL = env.GIT_COMMITTER_EMAIL ?? "agentplane-test@example.com";
|
|
714
|
-
return env;
|
|
715
|
-
}
|
|
716
|
-
export async function pathExists(filePath) {
|
|
717
|
-
try {
|
|
718
|
-
await access(filePath);
|
|
719
|
-
return true;
|
|
720
|
-
}
|
|
721
|
-
catch {
|
|
722
|
-
return false;
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
export async function gitBranchExists(root, branch) {
|
|
726
|
-
try {
|
|
727
|
-
await execFileAsync("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], {
|
|
728
|
-
cwd: root,
|
|
729
|
-
env: cleanGitEnv(),
|
|
730
|
-
});
|
|
731
|
-
return true;
|
|
732
|
-
}
|
|
733
|
-
catch (err) {
|
|
734
|
-
const code = err?.code;
|
|
735
|
-
if (code === 1)
|
|
736
|
-
return false;
|
|
737
|
-
throw err;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
export async function commitAll(root, message) {
|
|
741
|
-
await execFileAsync("git", ["add", "."], { cwd: root, env: cleanGitEnv() });
|
|
742
|
-
await execFileAsync("git", ["commit", "--no-verify", "-m", message], {
|
|
743
|
-
cwd: root,
|
|
744
|
-
env: cleanGitEnv(),
|
|
745
|
-
});
|
|
746
|
-
}
|
|
747
|
-
export async function commitPathsIfChanged(root, paths, message) {
|
|
748
|
-
await execFileAsync("git", ["add", "--", ...paths], { cwd: root, env: cleanGitEnv() });
|
|
749
|
-
const { stdout } = await execFileAsync("git", ["diff", "--cached", "--name-only", "--", ...paths], {
|
|
750
|
-
cwd: root,
|
|
751
|
-
env: cleanGitEnv(),
|
|
752
|
-
});
|
|
753
|
-
if (!stdout.trim())
|
|
754
|
-
return false;
|
|
755
|
-
await execFileAsync("git", ["commit", "--no-verify", "-m", message], {
|
|
756
|
-
cwd: root,
|
|
757
|
-
env: cleanGitEnv(),
|
|
758
|
-
});
|
|
759
|
-
return true;
|
|
760
|
-
}
|
|
761
|
-
export async function stageGitignoreIfPresent(root) {
|
|
762
|
-
const gitignorePath = path.join(root, ".gitignore");
|
|
763
|
-
if (!(await pathExists(gitignorePath)))
|
|
764
|
-
return;
|
|
765
|
-
await execFileAsync("git", ["add", ".gitignore"], { cwd: root, env: cleanGitEnv() });
|
|
766
|
-
}
|
|
1
|
+
export * from "../testing/index.js";
|