pi-crew 0.9.55 → 0.9.57
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/AGENTS.md +1 -1
- package/CHANGELOG.md +58 -0
- package/README.md +53 -5
- package/dist/index.mjs +5666 -4370
- package/docs/README.md +54 -0
- package/package.json +12 -13
- package/skills/real-test-pi-crew/SKILL.md +93 -3
- package/src/agents/discover-agents.ts +68 -10
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +2 -1
- package/src/config/types.ts +12 -0
- package/src/extension/action-suggestions.ts +16 -63
- package/src/extension/async-notifier.ts +3 -3
- package/src/extension/command-completions.ts +2 -2
- package/src/extension/crew-cleanup.ts +3 -3
- package/src/extension/crew-vibes/footer.ts +4 -2
- package/src/extension/cross-extension-rpc.ts +10 -5
- package/src/extension/knowledge-injection.ts +57 -10
- package/src/extension/register.ts +2 -2
- package/src/extension/registration/artifact-cleanup.ts +41 -3
- package/src/extension/registration/commands.ts +4 -4
- package/src/extension/registration/context-builder.ts +10 -10
- package/src/extension/registration/crash-recovery-cache.ts +3 -3
- package/src/extension/registration/foreground-run-controller.ts +1 -1
- package/src/extension/registration/lazy-configurers.ts +2 -2
- package/src/extension/registration/lifecycle-handlers.ts +12 -12
- package/src/extension/registration/lifecycle.ts +2 -2
- package/src/extension/registration/observability.ts +2 -2
- package/src/extension/registration/registration-types.ts +3 -3
- package/src/extension/registration/runtime-cleanup.ts +1 -1
- package/src/extension/registration/subagent-helpers.ts +2 -2
- package/src/extension/registration/subagent-manager-setup.ts +2 -2
- package/src/extension/registration/subagent-tools.ts +21 -16
- package/src/extension/registration/team-tool.ts +109 -17
- package/src/extension/registration/viewers.ts +3 -4
- package/src/extension/registration/wire-cross-extension.ts +7 -7
- package/src/extension/rpc-hmac.ts +3 -2
- package/src/extension/run-bundle-schema.ts +13 -4
- package/src/extension/run-export.ts +2 -2
- package/src/extension/run-index.ts +2 -3
- package/src/extension/run-maintenance.ts +57 -1
- package/src/extension/team-manager-command.ts +3 -1
- package/src/extension/team-tool/anchor.ts +8 -2
- package/src/extension/team-tool/api.ts +117 -39
- package/src/extension/team-tool/cancel.ts +23 -8
- package/src/extension/team-tool/chain-executor.ts +1 -1
- package/src/extension/team-tool/dispatch/automate.ts +17 -2
- package/src/extension/team-tool/dispatch/control.ts +17 -2
- package/src/extension/team-tool/dispatch/manage.ts +34 -2
- package/src/extension/team-tool/dispatch/run.ts +17 -2
- package/src/extension/team-tool/dispatch/status.ts +37 -5
- package/src/extension/team-tool/doctor.ts +2 -2
- package/src/extension/team-tool/explain.ts +1 -1
- package/src/extension/team-tool/goal-wrap.ts +5 -5
- package/src/extension/team-tool/goal.ts +30 -9
- package/src/extension/team-tool/handle-schedule.ts +37 -19
- package/src/extension/team-tool/inspect.ts +21 -5
- package/src/extension/team-tool/lifecycle-actions.ts +53 -10
- package/src/extension/team-tool/parallel-dispatch.ts +14 -5
- package/src/extension/team-tool/param-error.ts +138 -0
- package/src/extension/team-tool/respond.ts +20 -6
- package/src/extension/team-tool/run.ts +27 -17
- package/src/extension/team-tool/status.ts +17 -6
- package/src/extension/team-tool.ts +26 -19
- package/src/hooks/registry.ts +1 -1
- package/src/i18n.ts +22 -0
- package/src/observability/event-bus.ts +1 -1
- package/src/prompt/prompt-runtime.ts +2 -2
- package/src/runtime/README.md +35 -0
- package/src/runtime/agent-control.ts +1 -1
- package/src/runtime/anchor-manager.ts +0 -2
- package/src/runtime/async-runner.ts +1 -1
- package/src/runtime/attention-events.ts +3 -2
- package/src/runtime/auto-summarize.ts +0 -2
- package/src/runtime/background-runner.ts +103 -30
- package/src/runtime/{crew-broker-child.ts → broker/crew-broker-child.ts} +2 -2
- package/src/runtime/{crew-broker-client.ts → broker/crew-broker-client.ts} +4 -7
- package/src/runtime/{crew-broker.ts → broker/crew-broker.ts} +13 -21
- package/src/runtime/chain-runner.ts +50 -5
- package/src/runtime/{child-pi-constants.ts → child-pi/child-pi-constants.ts} +1 -1
- package/src/runtime/{child-pi-kill.ts → child-pi/child-pi-kill.ts} +3 -3
- package/src/runtime/{child-pi-spawn.ts → child-pi/child-pi-spawn.ts} +28 -12
- package/src/runtime/{child-pi-steering.ts → child-pi/child-pi-steering.ts} +1 -1
- package/src/runtime/{child-pi-streams.ts → child-pi/child-pi-streams.ts} +23 -4
- package/src/runtime/{child-pi-transcript.ts → child-pi/child-pi-transcript.ts} +6 -6
- package/src/runtime/{child-pi.ts → child-pi/child-pi.ts} +47 -78
- package/src/runtime/compaction/compact-stages/bounded-tail.ts +84 -0
- package/src/runtime/{compact-stages → compaction/compact-stages}/index.ts +2 -2
- package/src/runtime/{compaction-summary.ts → compaction/compaction-summary.ts} +3 -3
- package/src/runtime/{tool-output-pruner.ts → compaction/tool-output-pruner.ts} +1 -1
- package/src/runtime/crew-agent-records.ts +48 -2
- package/src/runtime/custom-tools/irc-tool.ts +2 -2
- package/src/runtime/delivery-coordinator.ts +0 -3
- package/src/runtime/diagnostic-export.ts +5 -4
- package/src/runtime/foreground-control.ts +1 -1
- package/src/runtime/foreground-watchdog.ts +1 -1
- package/src/runtime/{adaptive-plan.ts → goal-workflow/adaptive-plan.ts} +8 -8
- package/src/runtime/{dynamic-workflow-context.ts → goal-workflow/dynamic-workflow-context.ts} +16 -16
- package/src/runtime/{dynamic-workflow-runner.ts → goal-workflow/dynamic-workflow-runner.ts} +10 -10
- package/src/runtime/{goal-achievement.ts → goal-workflow/goal-achievement.ts} +3 -3
- package/src/runtime/{goal-evaluator.ts → goal-workflow/goal-evaluator.ts} +8 -8
- package/src/runtime/{goal-loop-runner.ts → goal-workflow/goal-loop-runner.ts} +27 -25
- package/src/runtime/{goal-state-store.ts → goal-workflow/goal-state-store.ts} +8 -8
- package/src/runtime/{plan-templates.ts → goal-workflow/plan-templates.ts} +1 -1
- package/src/runtime/group-join.ts +3 -3
- package/src/runtime/handoff-manager.ts +0 -2
- package/src/runtime/{heartbeat-watcher.ts → heartbeat/heartbeat-watcher.ts} +7 -7
- package/src/runtime/iteration-hooks.ts +1 -1
- package/src/runtime/{live-agent-control.ts → live-session/live-agent-control.ts} +2 -2
- package/src/runtime/{live-agent-manager.ts → live-session/live-agent-manager.ts} +4 -4
- package/src/runtime/{live-session-runtime.ts → live-session/live-session-runtime.ts} +39 -41
- package/src/runtime/manifest-cache.ts +6 -2
- package/src/runtime/{model-fallback.ts → model/model-fallback.ts} +1 -1
- package/src/runtime/{pi-args.ts → model/pi-args.ts} +20 -5
- package/src/runtime/model/provider-extensions.ts +116 -0
- package/src/runtime/{runtime-policy.ts → model/runtime-policy.ts} +2 -2
- package/src/runtime/{runtime-resolver.ts → model/runtime-resolver.ts} +3 -3
- package/src/runtime/{runtime-warmup.ts → model/runtime-warmup.ts} +8 -8
- package/src/runtime/orphan-worker-registry.ts +1 -1
- package/src/runtime/{progress-tracker.ts → output/progress-tracker.ts} +1 -1
- package/src/runtime/{result-extractor.ts → output/result-extractor.ts} +4 -4
- package/src/runtime/{sidechain-output.ts → output/sidechain-output.ts} +2 -2
- package/src/runtime/{stream-preview.ts → output/stream-preview.ts} +1 -1
- package/src/runtime/{streaming-output.ts → output/streaming-output.ts} +2 -2
- package/src/runtime/{tool-progress.ts → output/tool-progress.ts} +1 -1
- package/src/runtime/parent-guard.ts +30 -10
- package/src/runtime/pipeline-runner.ts +2 -2
- package/src/runtime/policy-engine.ts +2 -2
- package/src/runtime/{cancellation.ts → process/cancellation.ts} +1 -1
- package/src/runtime/{post-exit-stdio-guard.ts → process/post-exit-stdio-guard.ts} +1 -1
- package/src/runtime/{process-lifecycle.ts → process/process-lifecycle.ts} +3 -3
- package/src/runtime/{checkpoint.ts → recovery/checkpoint.ts} +4 -4
- package/src/runtime/{crash-recovery.ts → recovery/crash-recovery.ts} +93 -21
- package/src/runtime/{overflow-recovery.ts → recovery/overflow-recovery.ts} +1 -1
- package/src/runtime/{recovery-recipes.ts → recovery/recovery-recipes.ts} +1 -1
- package/src/runtime/{retry-executor.ts → recovery/retry-executor.ts} +2 -2
- package/src/runtime/{retry-runner.ts → recovery/retry-runner.ts} +2 -8
- package/src/runtime/run-tracker.ts +1 -1
- package/src/runtime/run-worker.ts +3 -3
- package/src/runtime/{coalesce-tasks.ts → scheduling/coalesce-tasks.ts} +3 -3
- package/src/runtime/{concurrency.ts → scheduling/concurrency.ts} +9 -3
- package/src/runtime/{parallel-research.ts → scheduling/parallel-research.ts} +4 -2
- package/src/runtime/{run-coalesced-task-group.ts → scheduling/run-coalesced-task-group.ts} +95 -36
- package/src/runtime/{semaphore.ts → scheduling/semaphore.ts} +4 -1
- package/src/runtime/{task-graph-scheduler.ts → scheduling/task-graph-scheduler.ts} +1 -1
- package/src/runtime/session-resources.ts +1 -1
- package/src/runtime/settings-store.ts +1 -1
- package/src/runtime/single-agent-compose.ts +1 -0
- package/src/runtime/stale-reconciler.ts +1 -1
- package/src/runtime/subagent-manager.ts +1 -1
- package/src/runtime/supervisor-contact.ts +28 -13
- package/src/runtime/task-output-context.ts +7 -5
- package/src/runtime/task-runner/child-executor.ts +67 -31
- package/src/runtime/task-runner/live-executor.ts +8 -8
- package/src/runtime/task-runner/post-execution.ts +12 -12
- package/src/runtime/task-runner/pre-execution.ts +6 -6
- package/src/runtime/task-runner/progress.ts +1 -1
- package/src/runtime/task-runner/run-projection.ts +1 -1
- package/src/runtime/task-runner/scaffold-executor.ts +1 -1
- package/src/runtime/task-runner/state-helpers.ts +2 -2
- package/src/runtime/task-runner.ts +4 -4
- package/src/runtime/team-runner.ts +441 -175
- package/src/runtime/{completion-guard.ts → verification/completion-guard.ts} +1 -1
- package/src/runtime/{green-contract.ts → verification/green-contract.ts} +1 -1
- package/src/runtime/{post-checks.ts → verification/post-checks.ts} +4 -4
- package/src/runtime/{verification-gates.ts → verification/verification-gates.ts} +5 -5
- package/src/runtime/{verification-integrity.ts → verification/verification-integrity.ts} +1 -1
- package/src/schema/config-schema.ts +1 -0
- package/src/schema/team-tool-schema.ts +149 -185
- package/src/state/README.md +44 -0
- package/src/state/atomic-write.ts +24 -3
- package/src/state/{locks.ts → coordination/locks.ts} +118 -38
- package/src/state/{mailbox.ts → coordination/mailbox.ts} +14 -8
- package/src/state/{schedule.ts → coordination/schedule.ts} +3 -3
- package/src/state/{task-claims.ts → coordination/task-claims.ts} +1 -1
- package/src/state/decision-ledger.ts +1 -1
- package/src/state/{event-log-rotation.ts → event-log/event-log-rotation.ts} +189 -31
- package/src/state/{event-log.ts → event-log/event-log.ts} +77 -39
- package/src/state/{jsonl-writer.ts → event-log/jsonl-writer.ts} +14 -6
- package/src/state/hook-instinct-bridge.ts +2 -2
- package/src/state/{active-run-registry.ts → stores/active-run-registry.ts} +7 -7
- package/src/state/{artifact-store.ts → stores/artifact-store.ts} +62 -4
- package/src/state/{blob-store.ts → stores/blob-store.ts} +3 -3
- package/src/state/{health-store.ts → stores/health-store.ts} +3 -3
- package/src/state/{instinct-store.ts → stores/instinct-store.ts} +3 -3
- package/src/state/{observation-store.ts → stores/observation-store.ts} +2 -2
- package/src/state/{run-cache.ts → stores/run-cache.ts} +4 -4
- package/src/state/{run-graph.ts → stores/run-graph.ts} +4 -4
- package/src/state/{run-metrics.ts → stores/run-metrics.ts} +3 -3
- package/src/state/{state-store.ts → stores/state-store.ts} +254 -21
- package/src/state/types.ts +27 -3
- package/src/ui/component.ts +55 -0
- package/src/ui/crew-select-list.ts +3 -1
- package/src/ui/dashboard-panes/agents-pane.ts +1 -1
- package/src/ui/dwf-phase-display.ts +1 -1
- package/src/ui/heartbeat-aggregator.ts +1 -1
- package/src/ui/keybinding-map.ts +179 -6
- package/src/ui/layout-primitives.ts +9 -5
- package/src/ui/live-conversation-overlay.ts +1 -1
- package/src/ui/live-run-sidebar.ts +1 -1
- package/src/ui/overlay-stack.ts +148 -0
- package/src/ui/overlays/agent-picker-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-compose-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-detail-overlay.ts +2 -2
- package/src/ui/powerbar-publisher.ts +1 -1
- package/src/ui/render-scheduler.ts +1 -1
- package/src/ui/run-action-dispatcher.ts +3 -3
- package/src/ui/run-dashboard.ts +5 -33
- package/src/ui/run-event-bus.ts +3 -3
- package/src/ui/run-snapshot-cache.ts +37 -18
- package/src/ui/settings-overlay.ts +13 -21
- package/src/ui/snapshot-types.ts +1 -1
- package/src/ui/status-colors.ts +0 -2
- package/src/ui/terminal-status.ts +1 -1
- package/src/ui/theme-adapter.ts +33 -13
- package/src/ui/tool-renderers/index.ts +8 -0
- package/src/ui/transcript-viewer.ts +37 -13
- package/src/ui/widget/index.ts +32 -9
- package/src/ui/widget/widget-formatters.ts +62 -4
- package/src/ui/widget/widget-model.ts +2 -2
- package/src/ui/widget/widget-renderer.ts +1 -1
- package/src/utils/conflict-detect.ts +58 -5
- package/src/utils/ndjson.ts +2 -2
- package/src/utils/redaction.ts +39 -0
- package/src/utils/socket-path.ts +1 -1
- package/src/workflows/workflow-config.ts +1 -1
- package/src/worktree/cleanup.ts +1 -1
- package/src/worktree/worktree-manager.ts +111 -47
- package/workflows/chain.workflow.md +2 -2
- package/dist/build-meta.json +0 -16807
- package/index.bundle.ts +0 -25
- package/scripts/bench-check.mjs +0 -96
- package/scripts/bench-cold-start.mjs +0 -216
- package/scripts/build-bundle.mjs +0 -92
- package/scripts/check-all-skills.ts +0 -294
- package/scripts/check-bundle-size.mjs +0 -38
- package/scripts/check-bundle-staleness.mjs +0 -97
- package/scripts/check-conflict-markers.mjs +0 -91
- package/scripts/check-lazy-imports.mjs +0 -28
- package/scripts/dev-runner.mjs +0 -106
- package/scripts/profile-startup.mjs +0 -125
- package/scripts/release-smoke.mjs +0 -74
- package/scripts/run-bench.mjs +0 -47
- package/scripts/run-real-chain.ts +0 -41
- package/scripts/test-issue-29-crash.ts +0 -111
- package/scripts/test-issue-29-e2e.ts +0 -183
- package/scripts/test-issue-29-real-runtime.ts +0 -330
- package/scripts/test-issue-29-real-tasks.ts +0 -387
- package/scripts/test-issue-29-team-tool.ts +0 -105
- package/scripts/test-runner.mjs +0 -84
- package/scripts/verify-flicker-fix.ts +0 -109
- package/scripts/verify-skill.ts +0 -550
- package/scripts/watch-bundle.mjs +0 -259
- package/scripts/watchdog-harness.ts +0 -119
- package/src/adapters/claude-adapter.ts +0 -23
- package/src/adapters/codex-adapter.ts +0 -21
- package/src/adapters/cursor-adapter.ts +0 -17
- package/src/adapters/export-util.ts +0 -143
- package/src/adapters/index.ts +0 -15
- package/src/adapters/registry.ts +0 -18
- package/src/adapters/types.ts +0 -23
- package/src/runtime/code-summary.ts +0 -292
- package/src/runtime/cross-extension-rpc.ts +0 -143
- package/src/runtime/hidden-handoff.ts +0 -407
- package/src/runtime/prose-compressor.ts +0 -162
- package/src/subagents/async-entry.ts +0 -1
- package/src/subagents/index.ts +0 -3
- package/src/subagents/live/control.ts +0 -1
- package/src/subagents/live/manager.ts +0 -1
- package/src/subagents/live/realtime.ts +0 -1
- package/src/subagents/live/session-runtime.ts +0 -1
- package/src/subagents/manager.ts +0 -1
- package/src/subagents/spawn.ts +0 -1
- package/test-integration-check.ts +0 -118
- /package/src/runtime/{broker-issuer.ts → broker/broker-issuer.ts} +0 -0
- /package/src/runtime/{crew-broker-tokens.ts → broker/crew-broker-tokens.ts} +0 -0
- /package/src/runtime/{child-pi-pool.ts → child-pi/child-pi-pool.ts} +0 -0
- /package/src/runtime/{compact-pipeline.ts → compaction/compact-pipeline.ts} +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/ansi-strip-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/blank-collapse-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/deduplicate-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/head-snap-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/tail-capture-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/truncation-stage.ts +0 -0
- /package/src/runtime/{important-line-classifier.ts → compaction/important-line-classifier.ts} +0 -0
- /package/src/runtime/{heartbeat-gradient.ts → heartbeat/heartbeat-gradient.ts} +0 -0
- /package/src/runtime/{worker-heartbeat.ts → heartbeat/worker-heartbeat.ts} +0 -0
- /package/src/runtime/{worker-startup.ts → heartbeat/worker-startup.ts} +0 -0
- /package/src/runtime/{intercom-bridge.ts → live-session/intercom-bridge.ts} +0 -0
- /package/src/runtime/{live-control-realtime.ts → live-session/live-control-realtime.ts} +0 -0
- /package/src/runtime/{live-extension-bridge.ts → live-session/live-extension-bridge.ts} +0 -0
- /package/src/runtime/{live-irc.ts → live-session/live-irc.ts} +0 -0
- /package/src/runtime/{live-session-health.ts → live-session/live-session-health.ts} +0 -0
- /package/src/runtime/{model-resolver.ts → model/model-resolver.ts} +0 -0
- /package/src/runtime/{model-scope.ts → model/model-scope.ts} +0 -0
- /package/src/runtime/{output-validator.ts → output/output-validator.ts} +0 -0
- /package/src/runtime/{pi-json-output.ts → output/pi-json-output.ts} +0 -0
- /package/src/runtime/{progress-event-coalescer.ts → output/progress-event-coalescer.ts} +0 -0
- /package/src/runtime/{cancellation-token.ts → process/cancellation-token.ts} +0 -0
- /package/src/runtime/{zombie-scanner.ts → process/zombie-scanner.ts} +0 -0
- /package/src/runtime/{crash-classification.ts → recovery/crash-classification.ts} +0 -0
- /package/src/runtime/{batch-barrier.ts → scheduling/batch-barrier.ts} +0 -0
- /package/src/runtime/{global-worker-cap.ts → scheduling/global-worker-cap.ts} +0 -0
- /package/src/runtime/{parallel-utils.ts → scheduling/parallel-utils.ts} +0 -0
- /package/src/runtime/{scheduler.ts → scheduling/scheduler.ts} +0 -0
- /package/src/runtime/{task-graph.ts → scheduling/task-graph.ts} +0 -0
- /package/src/runtime/{verification-worktree.ts → verification/verification-worktree.ts} +0 -0
- /package/src/state/{event-reconstructor.ts → event-log/event-reconstructor.ts} +0 -0
- /package/src/state/{worker-atomic-writer.ts → event-log/worker-atomic-writer.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
-
import type { TeamRunManifest, TeamTaskState } from "
|
|
2
|
+
import type { TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
3
3
|
|
|
4
4
|
// ============================================================================
|
|
5
5
|
// Phase 1.2: Completion Mutation Guard — detects tasks that claim success but
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* Distilled from pi-autoresearch's post-check / backpressure pattern.
|
|
6
6
|
*/
|
|
7
7
|
import { execFileSync } from "node:child_process";
|
|
8
|
-
import { WINDOWS_ESSENTIAL_ENV_VARS } from "
|
|
9
|
-
import { sanitizeEnvSecrets } from "
|
|
10
|
-
import { resolveShellForScript } from "
|
|
11
|
-
import { resolveRealContainedPath } from "
|
|
8
|
+
import { WINDOWS_ESSENTIAL_ENV_VARS } from "../../utils/env-allowlist.ts";
|
|
9
|
+
import { sanitizeEnvSecrets } from "../../utils/env-filter.ts";
|
|
10
|
+
import { resolveShellForScript } from "../../utils/resolve-shell.ts";
|
|
11
|
+
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
12
12
|
|
|
13
13
|
/** Default timeout for post-check scripts (5 minutes). */
|
|
14
14
|
const DEFAULT_TIMEOUT_MS = 300_000;
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
import { spawn } from "node:child_process";
|
|
13
13
|
import * as fs from "node:fs";
|
|
14
14
|
import * as path from "node:path";
|
|
15
|
-
import { writeArtifact } from "
|
|
16
|
-
import type { GreenLevel, VerificationCommandResult, VerificationContract } from "
|
|
17
|
-
import { WINDOWS_ESSENTIAL_ENV_VARS } from "
|
|
18
|
-
import { sanitizeEnvSecrets } from "
|
|
19
|
-
import { redactSecretString } from "
|
|
15
|
+
import { writeArtifact } from "../../state/stores/artifact-store.ts";
|
|
16
|
+
import type { GreenLevel, VerificationCommandResult, VerificationContract } from "../../state/types.ts";
|
|
17
|
+
import { WINDOWS_ESSENTIAL_ENV_VARS } from "../../utils/env-allowlist.ts";
|
|
18
|
+
import { sanitizeEnvSecrets } from "../../utils/env-filter.ts";
|
|
19
|
+
import { redactSecretString } from "../../utils/redaction.ts";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Phase 1.5 #1 (RFC 13 §6 info-disclosure mitigation): sanitize the env passed
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
import { createHash } from "node:crypto";
|
|
29
29
|
import * as fs from "node:fs";
|
|
30
30
|
import * as path from "node:path";
|
|
31
|
-
import { logInternalError } from "
|
|
31
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Fixed set of project-manifest files considered by {@link snapshotManifests}.
|
|
@@ -1,4 +1,25 @@
|
|
|
1
|
-
import { Type } from "@sinclair/typebox";
|
|
1
|
+
import { type TSchema, Type, TypeRegistry } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
4
|
+
// EXT-7: Compact enum action schema. TypeBox has no built-in type that
|
|
5
|
+
// produces JSON Schema `{ enum: [...] }` AND validates via Value.Check.
|
|
6
|
+
// Type.Unsafe defaults to Kind 'Unsafe' which Value.Check throws on.
|
|
7
|
+
// We register a custom 'StringEnum' kind once: JSON Schema consumers (the
|
|
8
|
+
// LLM tool definition) see the compact `{ type: "string", enum: [...] }`
|
|
9
|
+
// (~600 chars vs ~1890 for anyOf+const), and Value.Check validates via
|
|
10
|
+
// the registered predicate.
|
|
11
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
12
|
+
TypeRegistry.Set("StringEnum", (schema, value) => {
|
|
13
|
+
const s = schema as { enum?: unknown[] };
|
|
14
|
+
return typeof value === "string" && Array.isArray(s.enum) && s.enum.includes(value);
|
|
15
|
+
});
|
|
16
|
+
const KIND = Symbol.for("TypeBox.Kind");
|
|
17
|
+
function stringEnum(values: readonly string[], description: string): TSchema {
|
|
18
|
+
// Empty string accepted: calling models emit "" for unset action; the handler
|
|
19
|
+
// treats it as omitted (defaults to "list"). Must be a plain enum member so
|
|
20
|
+
// JSON-Schema consumers (pi-ai validation) accept it without coercion.
|
|
21
|
+
return Type.Unsafe({ [KIND]: "StringEnum", type: "string", enum: ["", ...values], description });
|
|
22
|
+
}
|
|
2
23
|
|
|
3
24
|
// ───────────────────────────────────────────────────────────────────────────
|
|
4
25
|
// API-5 facade split: the 54-action mega-tool schema is split into 5 domain
|
|
@@ -8,24 +29,18 @@ import { Type } from "@sinclair/typebox";
|
|
|
8
29
|
// `TeamToolParams` is re-exported as a TypeBox Union for backward compat.
|
|
9
30
|
// ───────────────────────────────────────────────────────────────────────────
|
|
10
31
|
|
|
11
|
-
const SkillOverride = Type.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
maxItems: 32,
|
|
19
|
-
items: { type: "string", maxLength: 80 },
|
|
20
|
-
},
|
|
21
|
-
{ type: "boolean" },
|
|
22
|
-
],
|
|
23
|
-
});
|
|
32
|
+
const SkillOverride = Type.Union(
|
|
33
|
+
[Type.String({ maxLength: 2048 }), Type.Array(Type.String({ maxLength: 80 }), { maxItems: 32 }), Type.Boolean()],
|
|
34
|
+
{
|
|
35
|
+
description:
|
|
36
|
+
"Skill name(s) to add to role/default skills, an array of skill names, or false to disable all injected skills for this run.",
|
|
37
|
+
},
|
|
38
|
+
);
|
|
24
39
|
|
|
25
|
-
|
|
40
|
+
// Freeform object: Type.Record + Any is TypeBox-native (no custom Unsafe kind),
|
|
41
|
+
// so Value.Check/Compile can walk it without throwing "Unknown type".
|
|
42
|
+
const FreeformConfig = Type.Record(Type.String(), Type.Any(), {
|
|
26
43
|
description: "Resource config for management actions.",
|
|
27
|
-
type: "object",
|
|
28
|
-
additionalProperties: true,
|
|
29
44
|
});
|
|
30
45
|
|
|
31
46
|
/**
|
|
@@ -38,7 +53,7 @@ const FreeformConfig = Type.Unsafe({
|
|
|
38
53
|
*/
|
|
39
54
|
const sharedFields = {
|
|
40
55
|
resource: Type.Optional(
|
|
41
|
-
Type.Union([Type.Literal("agent"), Type.Literal("team"), Type.Literal("workflow")], {
|
|
56
|
+
Type.Union([Type.Literal(""), Type.Literal("agent"), Type.Literal("team"), Type.Literal("workflow")], {
|
|
42
57
|
description: "Resource kind for get/create/update/delete/list. Defaults to all for list.",
|
|
43
58
|
}),
|
|
44
59
|
),
|
|
@@ -75,7 +90,9 @@ const sharedFields = {
|
|
|
75
90
|
runId: Type.Optional(
|
|
76
91
|
Type.String({
|
|
77
92
|
description: "Run ID for status, cancel, or resume.",
|
|
78
|
-
|
|
93
|
+
// Empty string allowed: calling models emit "" for unset keys; the handler
|
|
94
|
+
// treats it as omitted (see normalizeTeamParams in team-tool.ts).
|
|
95
|
+
pattern: "^$|^[A-Za-z0-9_-]+$",
|
|
79
96
|
}),
|
|
80
97
|
),
|
|
81
98
|
taskId: Type.Optional(Type.String({ description: "Task ID for respond action." })),
|
|
@@ -93,12 +110,12 @@ const sharedFields = {
|
|
|
93
110
|
}),
|
|
94
111
|
),
|
|
95
112
|
workspaceMode: Type.Optional(
|
|
96
|
-
Type.Union([Type.Literal("single"), Type.Literal("worktree")], {
|
|
113
|
+
Type.Union([Type.Literal(""), Type.Literal("single"), Type.Literal("worktree")], {
|
|
97
114
|
description: "Workspace isolation mode. Worktree mode is planned after MVP.",
|
|
98
115
|
}),
|
|
99
116
|
),
|
|
100
117
|
context: Type.Optional(
|
|
101
|
-
Type.Union([Type.Literal("fresh"), Type.Literal("fork")], {
|
|
118
|
+
Type.Union([Type.Literal(""), Type.Literal("fresh"), Type.Literal("fork")], {
|
|
102
119
|
description: "Child context mode for workers.",
|
|
103
120
|
}),
|
|
104
121
|
),
|
|
@@ -106,7 +123,7 @@ const sharedFields = {
|
|
|
106
123
|
model: Type.Optional(Type.String({ description: "Model override for direct runs." })),
|
|
107
124
|
skill: Type.Optional(SkillOverride),
|
|
108
125
|
scope: Type.Optional(
|
|
109
|
-
Type.Union([Type.Literal("user"), Type.Literal("project"), Type.Literal("both")], {
|
|
126
|
+
Type.Union([Type.Literal(""), Type.Literal("user"), Type.Literal("project"), Type.Literal("both")], {
|
|
110
127
|
description: "Resource scope for discovery or management.",
|
|
111
128
|
}),
|
|
112
129
|
),
|
|
@@ -127,8 +144,8 @@ const sharedFields = {
|
|
|
127
144
|
}),
|
|
128
145
|
),
|
|
129
146
|
keep: Type.Optional(
|
|
130
|
-
|
|
131
|
-
|
|
147
|
+
// Boolean false accepted: calling models emit false for unset; treated as omitted.
|
|
148
|
+
Type.Union([Type.Boolean(), Type.Integer({ minimum: 0 })], {
|
|
132
149
|
description: "Number of finished runs to keep for prune.",
|
|
133
150
|
}),
|
|
134
151
|
),
|
|
@@ -162,7 +179,8 @@ const sharedFields = {
|
|
|
162
179
|
}),
|
|
163
180
|
),
|
|
164
181
|
once: Type.Optional(
|
|
165
|
-
|
|
182
|
+
// Boolean false accepted: calling models emit false for unset; treated as omitted.
|
|
183
|
+
Type.Union([Type.Boolean(), Type.String(), Type.Number()], {
|
|
166
184
|
description: "ISO timestamp or epoch ms for a one-time scheduled run.",
|
|
167
185
|
}),
|
|
168
186
|
),
|
|
@@ -172,11 +190,20 @@ const sharedFields = {
|
|
|
172
190
|
}),
|
|
173
191
|
),
|
|
174
192
|
budgetTotal: Type.Optional(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
193
|
+
// 0 accepted as "unset/disabled" (models emit 0 for off); still rejects 1-999
|
|
194
|
+
// as the MISCONFIGURATION GUARD against typo'd silent-abort configs.
|
|
195
|
+
Type.Union(
|
|
196
|
+
[
|
|
197
|
+
Type.Literal(0),
|
|
198
|
+
Type.Number({
|
|
199
|
+
minimum: 1000,
|
|
200
|
+
}),
|
|
201
|
+
],
|
|
202
|
+
{
|
|
203
|
+
description:
|
|
204
|
+
"Total token budget for the run. When set, enables budget tracking with default 80% warning and 95% abort thresholds. Minimum 1000 — this is a MISCONFIGURATION GUARD (catches typos / silent-abort configs like budgetTotal:1, which would abort on turn 1), NOT a usefulness guarantee; a productive multi-turn goal needs far more than 1000 tokens. 0 = unset.",
|
|
205
|
+
},
|
|
206
|
+
),
|
|
180
207
|
),
|
|
181
208
|
budgetUnlimited: Type.Optional(
|
|
182
209
|
Type.Boolean({
|
|
@@ -201,7 +228,7 @@ const sharedFields = {
|
|
|
201
228
|
}),
|
|
202
229
|
),
|
|
203
230
|
runKind: Type.Optional(
|
|
204
|
-
Type.Union([Type.Literal("team-run"), Type.Literal("goal-loop"), Type.Literal("dynamic-workflow")], {
|
|
231
|
+
Type.Union([Type.Literal(""), Type.Literal("team-run"), Type.Literal("goal-loop"), Type.Literal("dynamic-workflow")], {
|
|
205
232
|
description:
|
|
206
233
|
'Background dispatch discriminator. Default "team-run" runs the normal executeTeamRun workflow; "goal-loop" (P0/P1) and "dynamic-workflow" (P2/P3) dispatch to their respective background runners. Absent = "team-run" for backward compatibility.',
|
|
207
234
|
}),
|
|
@@ -239,99 +266,54 @@ const sharedFields = {
|
|
|
239
266
|
|
|
240
267
|
const ACTION_DESCRIPTION = "Team action. Defaults to 'list' when omitted.";
|
|
241
268
|
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
[
|
|
245
|
-
Type.Literal("run"),
|
|
246
|
-
Type.Literal("parallel"),
|
|
247
|
-
Type.Literal("plan"),
|
|
248
|
-
Type.Literal("orchestrate"),
|
|
249
|
-
Type.Literal("resume"),
|
|
250
|
-
Type.Literal("retry"),
|
|
251
|
-
Type.Literal("wait"),
|
|
252
|
-
Type.Literal("steer"),
|
|
253
|
-
Type.Literal("goal"),
|
|
254
|
-
],
|
|
255
|
-
{ description: ACTION_DESCRIPTION },
|
|
256
|
-
),
|
|
257
|
-
);
|
|
269
|
+
const RUN_ACTIONS = ["run", "parallel", "plan", "orchestrate", "resume", "retry", "wait", "steer", "goal"] as const;
|
|
270
|
+
const runActions = Type.Optional(stringEnum(RUN_ACTIONS, ACTION_DESCRIPTION));
|
|
258
271
|
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
],
|
|
279
|
-
{ description: ACTION_DESCRIPTION },
|
|
280
|
-
),
|
|
281
|
-
);
|
|
272
|
+
const STATUS_ACTIONS = [
|
|
273
|
+
"status",
|
|
274
|
+
"list",
|
|
275
|
+
"get",
|
|
276
|
+
"events",
|
|
277
|
+
"artifacts",
|
|
278
|
+
"summary",
|
|
279
|
+
"graph",
|
|
280
|
+
"search",
|
|
281
|
+
"health",
|
|
282
|
+
"worktrees",
|
|
283
|
+
"checkpoint",
|
|
284
|
+
"cache",
|
|
285
|
+
"explain",
|
|
286
|
+
"onboard",
|
|
287
|
+
"recommend",
|
|
288
|
+
"help",
|
|
289
|
+
] as const;
|
|
290
|
+
const statusActions = Type.Optional(stringEnum(STATUS_ACTIONS, ACTION_DESCRIPTION));
|
|
282
291
|
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
[
|
|
286
|
-
Type.Literal("cancel"),
|
|
287
|
-
Type.Literal("invalidate"),
|
|
288
|
-
Type.Literal("respond"),
|
|
289
|
-
Type.Literal("cleanup"),
|
|
290
|
-
Type.Literal("prune"),
|
|
291
|
-
Type.Literal("forget"),
|
|
292
|
-
Type.Literal("doctor"),
|
|
293
|
-
],
|
|
294
|
-
{ description: ACTION_DESCRIPTION },
|
|
295
|
-
),
|
|
296
|
-
);
|
|
292
|
+
const CONTROL_ACTIONS = ["cancel", "invalidate", "respond", "cleanup", "prune", "forget", "doctor"] as const;
|
|
293
|
+
const controlActions = Type.Optional(stringEnum(CONTROL_ACTIONS, ACTION_DESCRIPTION));
|
|
297
294
|
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
],
|
|
318
|
-
{ description: ACTION_DESCRIPTION },
|
|
319
|
-
),
|
|
320
|
-
);
|
|
295
|
+
const MANAGE_ACTIONS = [
|
|
296
|
+
"create",
|
|
297
|
+
"update",
|
|
298
|
+
"delete",
|
|
299
|
+
"init",
|
|
300
|
+
"config",
|
|
301
|
+
"validate",
|
|
302
|
+
"autonomy",
|
|
303
|
+
"settings",
|
|
304
|
+
"workflow-create",
|
|
305
|
+
"workflow-get",
|
|
306
|
+
"workflow-list",
|
|
307
|
+
"workflow-save",
|
|
308
|
+
"workflow-delete",
|
|
309
|
+
"import",
|
|
310
|
+
"imports",
|
|
311
|
+
"export",
|
|
312
|
+
] as const;
|
|
313
|
+
const manageActions = Type.Optional(stringEnum(MANAGE_ACTIONS, ACTION_DESCRIPTION));
|
|
321
314
|
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
[
|
|
325
|
-
Type.Literal("schedule"),
|
|
326
|
-
Type.Literal("scheduled"),
|
|
327
|
-
Type.Literal("anchor"),
|
|
328
|
-
Type.Literal("auto-summarize"),
|
|
329
|
-
Type.Literal("auto_boomerang"),
|
|
330
|
-
Type.Literal("api"),
|
|
331
|
-
],
|
|
332
|
-
{ description: ACTION_DESCRIPTION },
|
|
333
|
-
),
|
|
334
|
-
);
|
|
315
|
+
const AUTOMATE_ACTIONS = ["schedule", "scheduled", "anchor", "auto-summarize", "auto_boomerang", "api"] as const;
|
|
316
|
+
const automateActions = Type.Optional(stringEnum(AUTOMATE_ACTIONS, ACTION_DESCRIPTION));
|
|
335
317
|
|
|
336
318
|
// ─── Domain schemas (additionalProperties: true — Phase 1, not tightened) ────
|
|
337
319
|
|
|
@@ -346,77 +328,59 @@ export const ManageDomainParams = Type.Object({ action: manageActions, ...shared
|
|
|
346
328
|
export const AutomateDomainParams = Type.Object({ action: automateActions, ...sharedFields }, { additionalProperties: true });
|
|
347
329
|
|
|
348
330
|
/**
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
* (
|
|
331
|
+
* LLM-facing team-tool schema. FLAT single Object (all actions + all shared
|
|
332
|
+
* fields optional) — NOT the former 5-variant Type.Union. The union emitted a
|
|
333
|
+
* giant `anyOf` (each variant repeated all ~30 shared fields) that LLM
|
|
334
|
+
* tool-callers could not reliably satisfy → empty/malformed calls → params
|
|
335
|
+
* dropped → the tool defaulted to `list`. The handler validates per-action
|
|
336
|
+
* fields at runtime (defense-in-depth, team-tool.ts execute()), so the schema
|
|
337
|
+
* only needs to enumerate valid actions + field types. Domain objects above
|
|
338
|
+
* (RunDomainParams etc.) are kept for the facade dispatch + backward compat.
|
|
352
339
|
*/
|
|
353
|
-
export const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
340
|
+
export const allActionLiterals = ([runActions, statusActions, controlActions, manageActions, automateActions] as TSchema[]).flatMap(
|
|
341
|
+
(set) => {
|
|
342
|
+
const literals =
|
|
343
|
+
(set.anyOf as { const: string }[] | undefined) ??
|
|
344
|
+
(Array.isArray(set.enum) ? set.enum.map((v: unknown) => ({ const: v })) : []) ??
|
|
345
|
+
[];
|
|
346
|
+
// stringEnum accepts "" as an unset marker for model callers; it is NOT an
|
|
347
|
+
// action, so exclude it from the literal/type/suggestion derivations.
|
|
348
|
+
return literals.filter((l) => l.const !== "");
|
|
349
|
+
},
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* EXT-8: Single source of truth for the valid `action` type. Derived from the
|
|
354
|
+
* domain action arrays (the same arrays `allActionLiterals` reads), so the
|
|
355
|
+
* `TeamToolParamsValue.action` interface field, schema enum, and suggestions
|
|
356
|
+
* can never drift apart. Adding/removing an action in any `*_ACTIONS` array
|
|
357
|
+
* propagates to every consumer automatically.
|
|
358
|
+
*/
|
|
359
|
+
export type TeamAction =
|
|
360
|
+
| (typeof RUN_ACTIONS)[number]
|
|
361
|
+
| (typeof STATUS_ACTIONS)[number]
|
|
362
|
+
| (typeof CONTROL_ACTIONS)[number]
|
|
363
|
+
| (typeof MANAGE_ACTIONS)[number]
|
|
364
|
+
| (typeof AUTOMATE_ACTIONS)[number];
|
|
365
|
+
|
|
366
|
+
export const TeamToolParams = Type.Object(
|
|
367
|
+
{
|
|
368
|
+
action: Type.Optional(
|
|
369
|
+
stringEnum(
|
|
370
|
+
allActionLiterals.map((l) => (l as { const: string }).const),
|
|
371
|
+
ACTION_DESCRIPTION,
|
|
372
|
+
),
|
|
373
|
+
),
|
|
374
|
+
...sharedFields,
|
|
375
|
+
},
|
|
376
|
+
{ additionalProperties: true },
|
|
377
|
+
);
|
|
360
378
|
|
|
361
379
|
/** Domain discriminator for the facade dispatch. */
|
|
362
380
|
export type TeamDomain = "run" | "status" | "control" | "manage" | "automate";
|
|
363
381
|
|
|
364
382
|
export interface TeamToolParamsValue {
|
|
365
|
-
action?:
|
|
366
|
-
| "run"
|
|
367
|
-
| "parallel"
|
|
368
|
-
| "plan"
|
|
369
|
-
| "status"
|
|
370
|
-
| "wait"
|
|
371
|
-
| "list"
|
|
372
|
-
| "get"
|
|
373
|
-
| "cancel"
|
|
374
|
-
| "retry"
|
|
375
|
-
| "resume"
|
|
376
|
-
| "respond"
|
|
377
|
-
| "create"
|
|
378
|
-
| "update"
|
|
379
|
-
| "delete"
|
|
380
|
-
| "doctor"
|
|
381
|
-
| "cleanup"
|
|
382
|
-
| "events"
|
|
383
|
-
| "artifacts"
|
|
384
|
-
| "worktrees"
|
|
385
|
-
| "forget"
|
|
386
|
-
| "summary"
|
|
387
|
-
| "prune"
|
|
388
|
-
| "export"
|
|
389
|
-
| "import"
|
|
390
|
-
| "imports"
|
|
391
|
-
| "help"
|
|
392
|
-
| "validate"
|
|
393
|
-
| "config"
|
|
394
|
-
| "init"
|
|
395
|
-
| "recommend"
|
|
396
|
-
| "autonomy"
|
|
397
|
-
| "api"
|
|
398
|
-
| "settings"
|
|
399
|
-
| "steer"
|
|
400
|
-
| "invalidate"
|
|
401
|
-
| "health"
|
|
402
|
-
| "graph"
|
|
403
|
-
| "onboard"
|
|
404
|
-
| "explain"
|
|
405
|
-
| "cache"
|
|
406
|
-
| "checkpoint"
|
|
407
|
-
| "search"
|
|
408
|
-
| "orchestrate"
|
|
409
|
-
| "schedule"
|
|
410
|
-
| "scheduled"
|
|
411
|
-
| "anchor"
|
|
412
|
-
| "auto-summarize"
|
|
413
|
-
| "auto_boomerang"
|
|
414
|
-
| "goal"
|
|
415
|
-
| "workflow-create"
|
|
416
|
-
| "workflow-get"
|
|
417
|
-
| "workflow-list"
|
|
418
|
-
| "workflow-save"
|
|
419
|
-
| "workflow-delete";
|
|
383
|
+
action?: TeamAction;
|
|
420
384
|
resource?: "agent" | "team" | "workflow";
|
|
421
385
|
team?: string;
|
|
422
386
|
workflow?: string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# src/state/ — Cluster Map
|
|
2
|
+
|
|
3
|
+
Persistent state layer for pi-crew runs. Organized into subdirectories by
|
|
4
|
+
responsibility (Phase 7 reorg).
|
|
5
|
+
|
|
6
|
+
## Root (shared infrastructure)
|
|
7
|
+
|
|
8
|
+
| File | Responsibility |
|
|
9
|
+
|------|---------------|
|
|
10
|
+
| `types.ts` | Core state types (`TeamRunManifest`, `TeamTaskState`, schema versions) |
|
|
11
|
+
| `types-eval.ts` | Evaluation-related types |
|
|
12
|
+
| `contracts.ts` | Status transitions, task-status enums |
|
|
13
|
+
| `tiered-eval.ts` | Tiered evaluation logic |
|
|
14
|
+
| `crew-init.ts` | Crew initialization / bootstrap |
|
|
15
|
+
| `decision-ledger.ts` | Decision recording |
|
|
16
|
+
| `gitignore-manager.ts` | `.gitignore` management for crew dirs |
|
|
17
|
+
| `hook-instinct-bridge.ts` | Bridge between hooks and instinct store |
|
|
18
|
+
| `hook-integrations.ts` | Hook integration points |
|
|
19
|
+
| `session-state-map.ts` | Session → state mapping |
|
|
20
|
+
| `usage.ts` | Token/cost usage tracking |
|
|
21
|
+
| `atomic-write.ts` | Atomic file writes (widely used — kept at root) |
|
|
22
|
+
|
|
23
|
+
## `event-log/` — Event journaling
|
|
24
|
+
|
|
25
|
+
Event append/read, rotation/compaction, JSONL writing, and worker-thread
|
|
26
|
+
atomic writes.
|
|
27
|
+
|
|
28
|
+
- `event-log.ts`, `event-log-rotation.ts`, `event-reconstructor.ts`,
|
|
29
|
+
`jsonl-writer.ts`, `worker-atomic-writer.ts`
|
|
30
|
+
|
|
31
|
+
## `stores/` — Persisted data stores
|
|
32
|
+
|
|
33
|
+
Manifest, artifact, blob, observation, health, instinct, run-graph/metrics
|
|
34
|
+
stores, and the active-run registry.
|
|
35
|
+
|
|
36
|
+
- `state-store.ts`, `run-cache.ts`, `artifact-store.ts`, `blob-store.ts`,
|
|
37
|
+
`observation-store.ts`, `health-store.ts`, `instinct-store.ts`,
|
|
38
|
+
`active-run-registry.ts`, `run-graph.ts`, `run-metrics.ts`
|
|
39
|
+
|
|
40
|
+
## `coordination/` — Concurrency & IPC
|
|
41
|
+
|
|
42
|
+
File locks, mailbox messaging, task scheduling, and task claims.
|
|
43
|
+
|
|
44
|
+
- `locks.ts`, `mailbox.ts`, `schedule.ts`, `task-claims.ts`
|
|
@@ -4,7 +4,7 @@ import * as os from "node:os";
|
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
6
6
|
import { sleepSync } from "../utils/sleep.ts";
|
|
7
|
-
import { atomicWriteFileViaWorker, isWorkerAtomicWriterEnabled } from "./worker-atomic-writer.ts";
|
|
7
|
+
import { atomicWriteFileViaWorker, isWorkerAtomicWriterEnabled } from "./event-log/worker-atomic-writer.ts";
|
|
8
8
|
|
|
9
9
|
function hashContent(content: string): string {
|
|
10
10
|
return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
@@ -596,8 +596,16 @@ export function atomicWriteFile(filePath: string, content: string, options?: Ato
|
|
|
596
596
|
// Write temp with restrictive permissions
|
|
597
597
|
const O_NOFOLLOW = typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0;
|
|
598
598
|
let fd: number | undefined;
|
|
599
|
+
// ST-7: track the temp-file lifecycle independently of `fd`. `fd` is cleared
|
|
600
|
+
// (set to undefined) right after the successful close — BEFORE the rename
|
|
601
|
+
// attempt (line ~621) — so gating temp cleanup on `fd !== undefined` leaks
|
|
602
|
+
// the temp file when the rename fails. `tempNeedsCleanup` stays true from
|
|
603
|
+
// open until the rename consumes the temp, so the finally block always
|
|
604
|
+
// removes a leftover instead of being skipped by the stale `fd` guard.
|
|
605
|
+
let tempNeedsCleanup = false;
|
|
599
606
|
try {
|
|
600
607
|
fd = fs.openSync(tempPath, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | O_NOFOLLOW, mode ?? 0o600);
|
|
608
|
+
tempNeedsCleanup = true; // ST-7: temp file now exists on disk
|
|
601
609
|
// Post-open verification: on Windows O_NOFOLLOW is 0, so verify FD is a regular file
|
|
602
610
|
const openedStat = fs.fstatSync(fd);
|
|
603
611
|
if (!openedStat.isFile()) {
|
|
@@ -636,6 +644,10 @@ export function atomicWriteFile(filePath: string, content: string, options?: Ato
|
|
|
636
644
|
}
|
|
637
645
|
// Issue 1 fix: use link+unlink instead of rename to avoid following symlinks
|
|
638
646
|
renameWithLinkSync(tempPath, filePath);
|
|
647
|
+
// ST-7: rename consumed the temp file — it no longer exists at tempPath, so
|
|
648
|
+
// the finally block must NOT try to remove it (and must not be gated on
|
|
649
|
+
// `fd`, which is already undefined here from the close at line ~621).
|
|
650
|
+
tempNeedsCleanup = false;
|
|
639
651
|
// FIX (2026-07-01 mailbox-replay CI flake): fsync the parent directory
|
|
640
652
|
// after rename so the directory entry update is durable. On most Linux
|
|
641
653
|
// filesystems, rename is journaled but the journal flush isn't always
|
|
@@ -679,8 +691,12 @@ export function atomicWriteFile(filePath: string, content: string, options?: Ato
|
|
|
679
691
|
throw renameError;
|
|
680
692
|
}
|
|
681
693
|
} finally {
|
|
682
|
-
//
|
|
683
|
-
//
|
|
694
|
+
// ST-7: temp cleanup must be gated on `tempNeedsCleanup` (whether a leftover
|
|
695
|
+
// temp file still exists), NOT on `fd !== undefined`. `fd` is set to undefined
|
|
696
|
+
// right after the successful close — BEFORE the rename attempt — so the old
|
|
697
|
+
// `fd !== undefined` guard skipped `rmSync(tempPath)` whenever the rename
|
|
698
|
+
// failed, leaking the temp file. `tempNeedsCleanup` is true from open until
|
|
699
|
+
// the rename consumes the temp, so this branch fires exactly when needed.
|
|
684
700
|
if (fd !== undefined) {
|
|
685
701
|
// A-02: close fd if still open before cleanup. If an error occurred
|
|
686
702
|
// between openSync and the normal closeSync (e.g. fstat/write/fsync
|
|
@@ -691,6 +707,8 @@ export function atomicWriteFile(filePath: string, content: string, options?: Ato
|
|
|
691
707
|
} catch {
|
|
692
708
|
/* fd may already be closed */
|
|
693
709
|
}
|
|
710
|
+
}
|
|
711
|
+
if (tempNeedsCleanup) {
|
|
694
712
|
try {
|
|
695
713
|
fs.rmSync(tempPath, { force: true });
|
|
696
714
|
} catch {
|
|
@@ -764,6 +782,9 @@ export async function atomicWriteFileAsync(filePath: string, content: string, op
|
|
|
764
782
|
// A-02: close fd if still open before cleanup. If an error occurred
|
|
765
783
|
// between open and the normal close (e.g. stat/writeFile/sync threw),
|
|
766
784
|
// the FileHandle would leak.
|
|
785
|
+
// ST-7: unlike the sync path, the async `rm(tempPath)` below is
|
|
786
|
+
// UNCONDITIONAL (not gated on `fd`), so a rename failure here does NOT
|
|
787
|
+
// leak the temp file. Verified during the ST-7 audit — no fix needed.
|
|
767
788
|
if (fd) {
|
|
768
789
|
try {
|
|
769
790
|
await fd.close();
|