@selesai/code 0.13.0 → 0.13.2
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/CHANGELOG.md +22 -0
- package/dist/core/agent-session.d.ts +1 -1
- package/dist/core/agent-session.js +1 -1
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.js +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/extensions/package.json +1 -2
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
- package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
- package/dist/extensions/pi-hermes-memory/README.md +643 -0
- package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
- package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
- package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
- package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
- package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
- package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
- package/dist/extensions/pi-hermes-memory/package.json +66 -0
- package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
- package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
- package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
- package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
- package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
- package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
- package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
- package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
- package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
- package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
- package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
- package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
- package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
- package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
- package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
- package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
- package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
- package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
- package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
- package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
- package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
- package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
- package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
- package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
- package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
- package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
- package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
- package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
- package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
- package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
- package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
- package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
- package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
- package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
- package/dist/extensions/pi-rewind-hook/README.md +4 -1
- package/dist/extensions/pi-rewind-hook/index.ts +151 -21
- package/dist/extensions/pi-rewind-hook/package.json +5 -3
- package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
- package/dist/extensions/pi-subagents/AGENTS.md +5 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
- package/dist/extensions/pi-subagents/README.md +12 -6
- package/dist/extensions/pi-subagents/VISION.md +81 -0
- package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
- package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
- package/dist/extensions/pi-subagents/docs/agents.md +488 -0
- package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
- package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
- package/dist/extensions/pi-subagents/docs/models.md +27 -4
- package/dist/extensions/pi-subagents/docs/observability.md +10 -9
- package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
- package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
- package/dist/extensions/pi-subagents/package-lock.json +389 -2
- package/dist/extensions/pi-subagents/package.json +3 -1
- package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
- package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
- package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
- package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
- package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
- package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
- package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
- package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
- package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
- package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
- package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
- package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
- package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -7
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
- package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
- package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
- package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
- package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
- package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
- package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
- package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
- package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
- package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
- package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
- package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
- package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
- package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
- package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
- package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
- package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
- package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
- package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
- package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
- package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
- package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
- package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
- package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
- package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
- package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
- package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
- package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
- package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
- package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
- package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
- package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
- package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
- package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
- package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
- package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
- package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
- package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
- package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
- package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
- package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +136 -6
- package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
- package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
- package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
- package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
- package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
- package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
- package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
- package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
- package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -7
- package/dist/skills/workflow/SKILL.md +65 -50
- package/package.json +112 -110
- package/dist/extensions/enable-readonly-tools.test.ts +0 -63
- package/dist/extensions/enable-readonly-tools.ts +0 -24
- package/dist/extensions/model-prompt-injector/config.json +0 -16
- package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
- package/dist/extensions/model-prompt-injector/index.ts +0 -148
- package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
- package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AsyncStatus,
|
|
3
|
+
HostStepNodeV1,
|
|
4
|
+
HostStepState,
|
|
5
|
+
HostStepVerdict,
|
|
6
|
+
WorkflowGraphNode,
|
|
7
|
+
WorkflowGraphSnapshot,
|
|
8
|
+
WorkflowNodeStatus,
|
|
9
|
+
} from "../../shared/types.ts";
|
|
10
|
+
|
|
11
|
+
export const HOST_STEP_MAX_ID_CHARS = 128;
|
|
12
|
+
export const HOST_STEP_MAX_LABEL_CHARS = 80;
|
|
13
|
+
export const HOST_STEP_MAX_ROLE_CHARS = 32;
|
|
14
|
+
export const HOST_STEP_MAX_PROVIDER_CHARS = 64;
|
|
15
|
+
export const HOST_STEP_MAX_REASON_CHARS = 64;
|
|
16
|
+
export const HOST_STEP_MAX_DETAIL_CHARS = 200;
|
|
17
|
+
export const HOST_STEP_MAX_TARGET_CHARS = 128;
|
|
18
|
+
export const HOST_STEP_MAX_REF_CHARS = 128;
|
|
19
|
+
export const HOST_STEP_MAX_REPORT_PATH_CHARS = 240;
|
|
20
|
+
export const HOST_STEP_MAX_COUNT = 32;
|
|
21
|
+
|
|
22
|
+
const HOST_STEP_FIELDS = new Set([
|
|
23
|
+
"version",
|
|
24
|
+
"kind",
|
|
25
|
+
"monitorKind",
|
|
26
|
+
"id",
|
|
27
|
+
"label",
|
|
28
|
+
"role",
|
|
29
|
+
"provider",
|
|
30
|
+
"state",
|
|
31
|
+
"verdict",
|
|
32
|
+
"reasonCode",
|
|
33
|
+
"detail",
|
|
34
|
+
"target",
|
|
35
|
+
"freshness",
|
|
36
|
+
"reportPath",
|
|
37
|
+
"exitCode",
|
|
38
|
+
"updatedAt",
|
|
39
|
+
"deadlineAt",
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
const FRESHNESS_FIELDS = new Set(["expectedRef", "observedRef", "stale"]);
|
|
43
|
+
|
|
44
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
45
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function assertBoundedString(value: unknown, field: string, maxChars: number, source: string, required = false): asserts value is string {
|
|
49
|
+
if (value === undefined && !required) return;
|
|
50
|
+
if (typeof value !== "string" || !value.trim()) throw new Error(`Invalid host step '${source}': ${field} must be a non-empty string.`);
|
|
51
|
+
if (value.length > maxChars) throw new Error(`Invalid host step '${source}': ${field} exceeds ${maxChars} characters.`);
|
|
52
|
+
if (/\r|\n/.test(value)) throw new Error(`Invalid host step '${source}': ${field} must be single-line.`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function assertTimestamp(value: unknown, field: string, source: string, required = false): asserts value is number {
|
|
56
|
+
if (value === undefined && !required) return;
|
|
57
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new Error(`Invalid host step '${source}': ${field} must be a non-negative safe integer.`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function assertFreshness(value: unknown, source: string): asserts value is HostStepNodeV1["freshness"] {
|
|
61
|
+
if (!isRecord(value)) throw new Error(`Invalid host step '${source}': freshness must be an object.`);
|
|
62
|
+
const unknownFields = Object.keys(value).filter((field) => !FRESHNESS_FIELDS.has(field));
|
|
63
|
+
if (unknownFields.length > 0) throw new Error(`Invalid host step '${source}': freshness has unsupported fields: ${unknownFields.join(", ")}.`);
|
|
64
|
+
assertBoundedString(value.expectedRef, "freshness.expectedRef", HOST_STEP_MAX_REF_CHARS, source, true);
|
|
65
|
+
assertBoundedString(value.observedRef, "freshness.observedRef", HOST_STEP_MAX_REF_CHARS, source);
|
|
66
|
+
if (value.stale !== undefined && typeof value.stale !== "boolean") throw new Error(`Invalid host step '${source}': freshness.stale must be a boolean.`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Validate the persisted host-step contract. This deliberately rejects unknown
|
|
71
|
+
* fields and unbounded values so status and receipt loaders fail closed.
|
|
72
|
+
*/
|
|
73
|
+
export function assertHostStepNode(value: unknown, source = "status"): asserts value is HostStepNodeV1 {
|
|
74
|
+
if (!isRecord(value)) throw new Error(`Invalid host step '${source}': expected an object.`);
|
|
75
|
+
const unknownFields = Object.keys(value).filter((field) => !HOST_STEP_FIELDS.has(field));
|
|
76
|
+
if (unknownFields.length > 0) throw new Error(`Invalid host step '${source}': unsupported fields: ${unknownFields.join(", ")}.`);
|
|
77
|
+
if (value.version !== 1) throw new Error(`Invalid host step '${source}': version must be 1.`);
|
|
78
|
+
if (value.kind !== "host-step") throw new Error(`Invalid host step '${source}': kind must be 'host-step'.`);
|
|
79
|
+
if (value.monitorKind !== "command" && value.monitorKind !== "ci" && value.monitorKind !== "gate") throw new Error(`Invalid host step '${source}': monitorKind must be 'command', 'ci', or 'gate'.`);
|
|
80
|
+
assertBoundedString(value.id, "id", HOST_STEP_MAX_ID_CHARS, source, true);
|
|
81
|
+
assertBoundedString(value.label, "label", HOST_STEP_MAX_LABEL_CHARS, source, true);
|
|
82
|
+
assertBoundedString(value.role, "role", HOST_STEP_MAX_ROLE_CHARS, source);
|
|
83
|
+
assertBoundedString(value.provider, "provider", HOST_STEP_MAX_PROVIDER_CHARS, source);
|
|
84
|
+
if (value.state !== "pending" && value.state !== "running" && value.state !== "done" && value.state !== "cancelled" && value.state !== "error") {
|
|
85
|
+
throw new Error(`Invalid host step '${source}': state is invalid.`);
|
|
86
|
+
}
|
|
87
|
+
if (value.verdict !== undefined && value.verdict !== "pass" && value.verdict !== "fail" && value.verdict !== "inconclusive") {
|
|
88
|
+
throw new Error(`Invalid host step '${source}': verdict is invalid.`);
|
|
89
|
+
}
|
|
90
|
+
if (value.state !== "done" && value.verdict !== undefined) throw new Error(`Invalid host step '${source}': verdict is only valid for done state.`);
|
|
91
|
+
assertBoundedString(value.reasonCode, "reasonCode", HOST_STEP_MAX_REASON_CHARS, source);
|
|
92
|
+
assertBoundedString(value.detail, "detail", HOST_STEP_MAX_DETAIL_CHARS, source);
|
|
93
|
+
assertBoundedString(value.target, "target", HOST_STEP_MAX_TARGET_CHARS, source);
|
|
94
|
+
if (value.freshness !== undefined) assertFreshness(value.freshness, source);
|
|
95
|
+
if (value.freshness && value.freshness.stale === true && (value.state !== "done" || value.verdict !== "inconclusive")) {
|
|
96
|
+
throw new Error(`Invalid host step '${source}': stale freshness requires done/inconclusive state.`);
|
|
97
|
+
}
|
|
98
|
+
assertBoundedString(value.reportPath, "reportPath", HOST_STEP_MAX_REPORT_PATH_CHARS, source);
|
|
99
|
+
const reportName = hostStepReportName(value.reportPath);
|
|
100
|
+
if (value.reportPath !== undefined && (!reportName || reportName === "." || reportName === "..")) throw new Error(`Invalid host step '${source}': reportPath must name a report.`);
|
|
101
|
+
if (value.exitCode !== undefined && value.exitCode !== null && (typeof value.exitCode !== "number" || !Number.isSafeInteger(value.exitCode) || value.exitCode < 0)) throw new Error(`Invalid host step '${source}': exitCode must be a non-negative safe integer or null.`);
|
|
102
|
+
if (value.monitorKind !== "command" && value.exitCode !== undefined) throw new Error(`Invalid host step '${source}': exitCode is only valid for command steps.`);
|
|
103
|
+
if ((value.state === "pending" || value.state === "running") && value.exitCode !== undefined) throw new Error(`Invalid host step '${source}': exitCode is only valid after command settlement.`);
|
|
104
|
+
assertTimestamp(value.updatedAt, "updatedAt", source, true);
|
|
105
|
+
assertTimestamp(value.deadlineAt, "deadlineAt", source);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function parseHostStepNode(value: unknown, source = "status"): HostStepNodeV1 {
|
|
109
|
+
assertHostStepNode(value, source);
|
|
110
|
+
return {
|
|
111
|
+
...value,
|
|
112
|
+
...(value.freshness ? { freshness: { ...value.freshness } } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function assertUniqueHostStepIds(hostSteps: readonly HostStepNodeV1[], source = "status"): void {
|
|
117
|
+
const ids = new Set<string>();
|
|
118
|
+
for (const hostStep of hostSteps) {
|
|
119
|
+
if (ids.has(hostStep.id)) throw new Error(`Invalid host step '${source}': duplicate host step id '${hostStep.id}'.`);
|
|
120
|
+
ids.add(hostStep.id);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Return only valid host nodes so an untrusted in-memory projection fails closed. */
|
|
125
|
+
export function validHostStepNodes(graph: WorkflowGraphSnapshot | undefined): HostStepNodeV1[] {
|
|
126
|
+
const nodes = graph?.nodes ?? [];
|
|
127
|
+
const nodeIdCounts = new Map<string, number>();
|
|
128
|
+
for (const node of nodes) nodeIdCounts.set(node.id, (nodeIdCounts.get(node.id) ?? 0) + 1);
|
|
129
|
+
const hostSteps: HostStepNodeV1[] = [];
|
|
130
|
+
for (const [index, node] of nodes.entries()) {
|
|
131
|
+
if (node.kind !== "host-step") continue;
|
|
132
|
+
try {
|
|
133
|
+
const hostStep = parseHostStepNode(node.hostStep, `workflowGraph.nodes[${index}].hostStep`);
|
|
134
|
+
if (node.id !== hostStep.id || node.label !== hostStep.label) continue;
|
|
135
|
+
if (nodeIdCounts.get(hostStep.id) !== 1) continue;
|
|
136
|
+
hostSteps.push(hostStep);
|
|
137
|
+
} catch {
|
|
138
|
+
// Renderers must not turn malformed host data into a fake child row.
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return hostSteps.slice(0, HOST_STEP_MAX_COUNT);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function assertWorkflowGraphHostSteps(graph: WorkflowGraphSnapshot | undefined, source = "status", expectedRunId?: string): void {
|
|
145
|
+
if (!graph) return;
|
|
146
|
+
if (expectedRunId !== undefined && graph.runId !== expectedRunId) throw new Error(`Invalid host step '${source}': workflowGraph.runId does not match the status run id.`);
|
|
147
|
+
const hostStepCount = graph.nodes.filter((node) => node.kind === "host-step").length;
|
|
148
|
+
if (hostStepCount > HOST_STEP_MAX_COUNT) throw new Error(`Invalid host step '${source}': workflowGraph contains more than ${HOST_STEP_MAX_COUNT} host steps.`);
|
|
149
|
+
const hostSteps: HostStepNodeV1[] = [];
|
|
150
|
+
for (const [index, node] of graph.nodes.entries()) {
|
|
151
|
+
if (node.kind !== "host-step") continue;
|
|
152
|
+
const hostStep = parseHostStepNode(node.hostStep, `${source}.workflowGraph.nodes[${index}].hostStep`);
|
|
153
|
+
if (node.id !== hostStep.id) throw new Error(`Invalid host step '${source}': workflowGraph.nodes[${index}].id does not match hostStep.id.`);
|
|
154
|
+
if (node.label !== hostStep.label) throw new Error(`Invalid host step '${source}': workflowGraph.nodes[${index}].label does not match hostStep.label.`);
|
|
155
|
+
hostSteps.push(hostStep);
|
|
156
|
+
}
|
|
157
|
+
assertUniqueHostStepIds(hostSteps, source);
|
|
158
|
+
for (const hostStep of hostSteps) {
|
|
159
|
+
if (graph.nodes.filter((node) => node.id === hostStep.id).length !== 1) throw new Error(`Invalid host step '${source}': workflowGraph id '${hostStep.id}' is not unique.`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function hostStepWorkflowNode(hostStep: HostStepNodeV1): WorkflowGraphNode {
|
|
164
|
+
assertHostStepNode(hostStep, hostStep.id);
|
|
165
|
+
return {
|
|
166
|
+
id: hostStep.id,
|
|
167
|
+
kind: "host-step",
|
|
168
|
+
label: hostStep.label,
|
|
169
|
+
status: workflowNodeStatus(hostStep),
|
|
170
|
+
hostStep: { ...hostStep, ...(hostStep.freshness ? { freshness: { ...hostStep.freshness } } : {}) },
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function workflowNodeStatus(hostStep: HostStepNodeV1): WorkflowNodeStatus {
|
|
175
|
+
if (hostStep.state === "pending") return "pending";
|
|
176
|
+
if (hostStep.state === "running") return "running";
|
|
177
|
+
if (hostStep.state === "cancelled") return "stopped";
|
|
178
|
+
if (hostStep.state === "error") return "failed";
|
|
179
|
+
if (hostStep.verdict === undefined || hostStep.verdict === "inconclusive") return "partial";
|
|
180
|
+
return hostStep.verdict === "fail" ? "failed" : "completed";
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Host-only registration/update boundary. The caller supplies the existing
|
|
185
|
+
* status writer; monitor providers never receive a path or write status.json.
|
|
186
|
+
*/
|
|
187
|
+
export function upsertHostStep(input: {
|
|
188
|
+
status: AsyncStatus;
|
|
189
|
+
hostStep: HostStepNodeV1;
|
|
190
|
+
persist: (status: AsyncStatus) => void;
|
|
191
|
+
}): AsyncStatus {
|
|
192
|
+
const hostStep = parseHostStepNode(input.hostStep, input.hostStep.id);
|
|
193
|
+
assertWorkflowGraphHostSteps(input.status.workflowGraph, "host-step", input.status.runId);
|
|
194
|
+
const graph: WorkflowGraphSnapshot = input.status.workflowGraph
|
|
195
|
+
? {
|
|
196
|
+
...input.status.workflowGraph,
|
|
197
|
+
nodes: [...input.status.workflowGraph.nodes],
|
|
198
|
+
}
|
|
199
|
+
: {
|
|
200
|
+
runId: input.status.runId,
|
|
201
|
+
mode: input.status.mode,
|
|
202
|
+
phases: [],
|
|
203
|
+
nodes: [],
|
|
204
|
+
};
|
|
205
|
+
const existingIndex = graph.nodes.findIndex((node) => node.id === hostStep.id);
|
|
206
|
+
const existing = existingIndex >= 0 ? graph.nodes[existingIndex] : undefined;
|
|
207
|
+
if (existing && existing.kind !== "host-step") throw new Error(`Host step '${hostStep.id}' conflicts with an existing workflow node.`);
|
|
208
|
+
if (existingIndex < 0 && graph.nodes.filter((candidate) => candidate.kind === "host-step").length >= HOST_STEP_MAX_COUNT) {
|
|
209
|
+
throw new Error(`Host step limit of ${HOST_STEP_MAX_COUNT} has been reached.`);
|
|
210
|
+
}
|
|
211
|
+
const node = hostStepWorkflowNode(hostStep);
|
|
212
|
+
if (existingIndex >= 0) graph.nodes[existingIndex] = node;
|
|
213
|
+
else graph.nodes.push(node);
|
|
214
|
+
const nextStatus: AsyncStatus = {
|
|
215
|
+
...input.status,
|
|
216
|
+
workflowGraph: graph,
|
|
217
|
+
lastUpdate: Math.max(input.status.lastUpdate ?? 0, hostStep.updatedAt),
|
|
218
|
+
};
|
|
219
|
+
input.persist(nextStatus);
|
|
220
|
+
return nextStatus;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function hostStepVerdictLabel(state: HostStepState, verdict: HostStepVerdict | undefined): string {
|
|
224
|
+
return state === "done" ? verdict ?? "inconclusive" : state;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function hostStepReportName(reportPath: string | undefined): string | undefined {
|
|
228
|
+
if (!reportPath) return undefined;
|
|
229
|
+
return reportPath.split(/[\\/]/).filter(Boolean).at(-1);
|
|
230
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { AsyncStatus, WorkflowLaneMetadata, WorkflowLaneMode } from "../../shared/types.ts";
|
|
2
|
+
|
|
3
|
+
export const WORKFLOW_LANE_KEY_MAX_BYTES = 128;
|
|
4
|
+
export const WORKFLOW_LANE_SOURCE_REF_MAX_BYTES = 128;
|
|
5
|
+
export const WORKFLOW_LANE_CLAIM_MAX_BYTES = 160;
|
|
6
|
+
export const WORKFLOW_LANE_CLAIMS_MAX = 20;
|
|
7
|
+
export const WORKFLOW_LANE_OUTPUT_PATH_MAX_BYTES = 256;
|
|
8
|
+
export const WORKFLOW_LANE_OUTPUT_PATHS_MAX = 10;
|
|
9
|
+
export const WORKTREE_STATUS_PATH_MAX_BYTES = 4096;
|
|
10
|
+
export const WORKTREE_STATUS_BRANCH_MAX_BYTES = 256;
|
|
11
|
+
|
|
12
|
+
const WORKFLOW_LANE_KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
13
|
+
const WORKFLOW_LANE_MODES = new Set<WorkflowLaneMode>(["mutation", "review", "scout", "gate"]);
|
|
14
|
+
|
|
15
|
+
function byteLength(value: string): number {
|
|
16
|
+
return Buffer.byteLength(value, "utf8");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function boundedNonEmptyString(value: unknown, label: string, maxBytes: number): string {
|
|
20
|
+
if (typeof value !== "string" || !value.trim()) throw new Error(`${label} must be a non-empty string.`);
|
|
21
|
+
const normalized = value.trim();
|
|
22
|
+
if (byteLength(normalized) > maxBytes) throw new Error(`${label} exceeds ${maxBytes} UTF-8 bytes.`);
|
|
23
|
+
if ([...normalized].some((character) => character === "\n" || character === "\r" || character === "\u0000")) throw new Error(`${label} must not contain newlines or NUL bytes.`);
|
|
24
|
+
return normalized;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function assertPlainObject(value: unknown, label: string): asserts value is Record<string, unknown> {
|
|
28
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)) {
|
|
29
|
+
throw new Error(`${label} must be a plain JSON object.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function assertKnownFields(value: Record<string, unknown>, fields: readonly string[], label: string): void {
|
|
34
|
+
const unknown = Object.keys(value).filter((field) => !fields.includes(field));
|
|
35
|
+
if (unknown.length > 0) throw new Error(`${label} has unsupported fields: ${unknown.join(", ")}.`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function boundedStringArray(value: unknown, label: string, maxItems: number, maxBytes: number): string[] {
|
|
39
|
+
if (!Array.isArray(value)) throw new Error(`${label} must be an array.`);
|
|
40
|
+
if (value.length > maxItems) throw new Error(`${label} supports at most ${maxItems} entries.`);
|
|
41
|
+
return value.map((entry, index) => {
|
|
42
|
+
if (!Object.hasOwn(value, index)) throw new Error(`${label} must not contain sparse entries.`);
|
|
43
|
+
return boundedNonEmptyString(entry, `${label}[${index}]`, maxBytes);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Normalize and validate launch-declared lane metadata. */
|
|
48
|
+
export function normalizeWorkflowLaneMetadata(value: unknown, label = "lane"): WorkflowLaneMetadata | undefined {
|
|
49
|
+
if (value === undefined) return undefined;
|
|
50
|
+
assertPlainObject(value, label);
|
|
51
|
+
assertKnownFields(value, ["version", "key", "mode", "sourceRef", "claims", "outputPaths"], label);
|
|
52
|
+
if (value.version !== 1) throw new Error(`${label}.version must be 1.`);
|
|
53
|
+
const key = boundedNonEmptyString(value.key, `${label}.key`, WORKFLOW_LANE_KEY_MAX_BYTES);
|
|
54
|
+
if (!WORKFLOW_LANE_KEY_PATTERN.test(key)) throw new Error(`${label}.key is invalid.`);
|
|
55
|
+
const mode = value.mode;
|
|
56
|
+
if (mode !== undefined && (typeof mode !== "string" || !WORKFLOW_LANE_MODES.has(mode as WorkflowLaneMode))) throw new Error(`${label}.mode is invalid.`);
|
|
57
|
+
const sourceRef = value.sourceRef === undefined ? undefined : boundedNonEmptyString(value.sourceRef, `${label}.sourceRef`, WORKFLOW_LANE_SOURCE_REF_MAX_BYTES);
|
|
58
|
+
const claims = value.claims === undefined ? undefined : boundedStringArray(value.claims, `${label}.claims`, WORKFLOW_LANE_CLAIMS_MAX, WORKFLOW_LANE_CLAIM_MAX_BYTES);
|
|
59
|
+
const outputPaths = value.outputPaths === undefined ? undefined : boundedStringArray(value.outputPaths, `${label}.outputPaths`, WORKFLOW_LANE_OUTPUT_PATHS_MAX, WORKFLOW_LANE_OUTPUT_PATH_MAX_BYTES);
|
|
60
|
+
return {
|
|
61
|
+
version: 1,
|
|
62
|
+
key,
|
|
63
|
+
...(mode !== undefined ? { mode: mode as WorkflowLaneMode } : {}),
|
|
64
|
+
...(sourceRef !== undefined ? { sourceRef } : {}),
|
|
65
|
+
...(claims !== undefined ? { claims } : {}),
|
|
66
|
+
...(outputPaths !== undefined ? { outputPaths } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function assertWorkflowLaneKey(lane: WorkflowLaneMetadata | undefined, workflowKey: string | undefined, label = "lane"): void {
|
|
71
|
+
if (!lane || workflowKey === undefined) return;
|
|
72
|
+
if (lane.key !== workflowKey) throw new Error(`${label}.key '${lane.key}' does not match workflow key '${workflowKey}'.`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface WorktreeStatusReference {
|
|
76
|
+
worktreePath: string;
|
|
77
|
+
branch: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Validate the display-only worktree fields copied into status.json. */
|
|
81
|
+
export function normalizeWorktreeStatusReference(value: unknown, label = "worktree status reference"): WorktreeStatusReference | undefined {
|
|
82
|
+
if (value === undefined) return undefined;
|
|
83
|
+
assertPlainObject(value, label);
|
|
84
|
+
assertKnownFields(value, ["worktreePath", "branch"], label);
|
|
85
|
+
return {
|
|
86
|
+
worktreePath: boundedNonEmptyString(value.worktreePath, `${label}.worktreePath`, WORKTREE_STATUS_PATH_MAX_BYTES),
|
|
87
|
+
branch: boundedNonEmptyString(value.branch, `${label}.branch`, WORKTREE_STATUS_BRANCH_MAX_BYTES),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Validate only the additive lane/worktree fields of a persisted async status. */
|
|
92
|
+
export function validateAsyncStatusLaneMetadata(status: Pick<AsyncStatus, "runId" | "workflowKey" | "lane" | "steps">, label = "async status"): void {
|
|
93
|
+
const lane = normalizeWorkflowLaneMetadata(status.lane, `${label}.lane`);
|
|
94
|
+
assertWorkflowLaneKey(lane, status.workflowKey, `${label}.lane`);
|
|
95
|
+
if (lane) status.lane = lane;
|
|
96
|
+
for (const [index, step] of (status.steps ?? []).entries()) {
|
|
97
|
+
const stepLane = normalizeWorkflowLaneMetadata(step.lane, `${label}.steps[${index}].lane`);
|
|
98
|
+
assertWorkflowLaneKey(stepLane, step.workflowKey, `${label}.steps[${index}].lane`);
|
|
99
|
+
if (stepLane) step.lane = stepLane;
|
|
100
|
+
const hasPath = step.worktreePath !== undefined;
|
|
101
|
+
const hasBranch = step.branch !== undefined;
|
|
102
|
+
if (hasPath !== hasBranch) throw new Error(`${label}.steps[${index}] must include both worktreePath and branch.`);
|
|
103
|
+
if (hasPath) normalizeWorktreeStatusReference({ worktreePath: step.worktreePath, branch: step.branch }, `${label}.steps[${index}]`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
|
|
3
|
+
export function preflightLaunchCwd(requestedCwd: string, effectiveCwd: string): string | undefined {
|
|
4
|
+
const resolution = requestedCwd === effectiveCwd ? "" : `\n(resolved from ${JSON.stringify(requestedCwd)})`;
|
|
5
|
+
try {
|
|
6
|
+
if (!fs.statSync(effectiveCwd).isDirectory()) {
|
|
7
|
+
return `Subagent launch aborted: cwd is not a directory: ${effectiveCwd}${resolution}`;
|
|
8
|
+
}
|
|
9
|
+
} catch (error) {
|
|
10
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
11
|
+
return `Subagent launch aborted: cwd does not exist: ${effectiveCwd}${resolution}`;
|
|
12
|
+
}
|
|
13
|
+
return `Subagent launch aborted: cwd could not be accessed: ${effectiveCwd}${resolution}\n${error instanceof Error ? error.message : String(error)}`;
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
@@ -141,8 +141,9 @@ export function isMutatingBashCommand(command: string): boolean {
|
|
|
141
141
|
|| MUTATING_BASH_PATTERNS.some((pattern) => pattern.test(command));
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
export function isMutatingTool(toolName: string | undefined, args: Record<string, unknown> | undefined): boolean {
|
|
144
|
+
export function isMutatingTool(toolName: string | undefined, args: Record<string, unknown> | undefined, mutationTools?: readonly string[]): boolean {
|
|
145
145
|
if (!toolName) return false;
|
|
146
|
+
if (mutationTools?.includes(toolName)) return true;
|
|
146
147
|
if (toolName === "edit" || toolName === "write") return true;
|
|
147
148
|
if (toolName === "cursor") {
|
|
148
149
|
const activityTitle = typeof args?.activityTitle === "string" ? args.activityTitle : "";
|