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,14 +1,14 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { DEFAULT_EVENT_LOG } from "
|
|
5
|
-
import { errors } from "
|
|
6
|
-
import { emitFromTeamEvent } from "
|
|
7
|
-
import { type IncrementalReadState, readJsonlSince, readJsonlTail } from "
|
|
8
|
-
import { logInternalError } from "
|
|
9
|
-
import { redactSecrets } from "
|
|
10
|
-
import { sleep, sleepSync } from "
|
|
11
|
-
import { atomicWriteFile } from "
|
|
4
|
+
import { DEFAULT_EVENT_LOG } from "../../config/defaults.ts";
|
|
5
|
+
import { errors } from "../../errors.ts";
|
|
6
|
+
import { emitFromTeamEvent } from "../../ui/run-event-bus.ts";
|
|
7
|
+
import { type IncrementalReadState, readJsonlSince, readJsonlTail } from "../../utils/incremental-reader.ts";
|
|
8
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
9
|
+
import { redactSecrets } from "../../utils/redaction.ts";
|
|
10
|
+
import { sleep, sleepSync } from "../../utils/sleep.ts";
|
|
11
|
+
import { atomicWriteFile } from "../atomic-write.ts";
|
|
12
12
|
import {
|
|
13
13
|
applyCompactionUnlocked,
|
|
14
14
|
currentGeneration,
|
|
@@ -69,7 +69,25 @@ const MAX_EVENTS_BYTES = 50 * 1024 * 1024;
|
|
|
69
69
|
|
|
70
70
|
const sequenceCache = new Map<string, { size: number; mtimeMs: number; seq: number; lastAccessMs: number }>();
|
|
71
71
|
const MAX_SEQUENCE_CACHE_ENTRIES = 256;
|
|
72
|
-
|
|
72
|
+
// P0-2: per-eventsPath append counter. Previously a single module-global shared
|
|
73
|
+
// across all runs AND never incremented on the async path, so the async rotation
|
|
74
|
+
// gate (`0 % 100 === 0`) was always true → needsRotation ran on EVERY async append
|
|
75
|
+
// (a full read+parse+rewrite once the log crossed 4 MB). FIFO-bounded to avoid
|
|
76
|
+
// unbounded growth with run count.
|
|
77
|
+
const appendCounters = new Map<string, number>();
|
|
78
|
+
const APPEND_COUNTER_MAX_ENTRIES = 256;
|
|
79
|
+
export function tickAppendCounter(eventsPath: string, inc = 1): boolean {
|
|
80
|
+
const prev = appendCounters.get(eventsPath) ?? 0;
|
|
81
|
+
const next = prev + inc;
|
|
82
|
+
appendCounters.set(eventsPath, next);
|
|
83
|
+
if (appendCounters.size > APPEND_COUNTER_MAX_ENTRIES) {
|
|
84
|
+
const oldest = appendCounters.keys().next().value;
|
|
85
|
+
if (oldest !== undefined) appendCounters.delete(oldest);
|
|
86
|
+
}
|
|
87
|
+
// True when a 100-boundary is crossed (matches the old `next % 100 === 0`
|
|
88
|
+
// semantics for inc=1, and generalizes to batch increments).
|
|
89
|
+
return Math.floor(next / 100) > Math.floor(prev / 100);
|
|
90
|
+
}
|
|
73
91
|
let overflowCounter = 0;
|
|
74
92
|
|
|
75
93
|
/** Simple cross-process lock for an eventsPath to prevent JSONL interleave on concurrent append.
|
|
@@ -82,7 +100,7 @@ let overflowCounter = 0;
|
|
|
82
100
|
* blocks the Node.js event loop for up to 5s. During that time, AbortSignal handlers
|
|
83
101
|
* cannot fire, SIGTERM handlers are delayed, and the process appears unresponsive to
|
|
84
102
|
* orchestrator health checks. Known callers include `appendEvent` (sync path),
|
|
85
|
-
* `flushOneEventLogBuffer`, and `state/mailbox.ts`. Prefer the async alternative
|
|
103
|
+
* `flushOneEventLogBuffer`, and `state/coordination/mailbox.ts`. Prefer the async alternative
|
|
86
104
|
* (`appendEventAsync`) for all new code.
|
|
87
105
|
*/
|
|
88
106
|
export function withEventLogLockSync<T>(eventsPath: string, fn: () => T, options?: { timeoutMs?: number; staleMs?: number }): T {
|
|
@@ -288,13 +306,16 @@ function nextSequence(eventsPath: string): number {
|
|
|
288
306
|
const stored = readStoredSequence(eventsPath);
|
|
289
307
|
const fileShrunk = cached && stat.size < cached.size;
|
|
290
308
|
if (stored !== undefined && !fileShrunk) {
|
|
291
|
-
//
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
//
|
|
309
|
+
// Trust the sidecar, but guard against a REGRESSED sidecar (e.g. the
|
|
310
|
+
// async path persisted a lower seq, rolling the sidecar back below the
|
|
311
|
+
// file's true max). Take max with a full scan so a regressed sidecar
|
|
312
|
+
// cannot produce a duplicate sequence number (EL-1 regression guard).
|
|
313
|
+
// NOTE (ST-12): a full scan here is acceptable because all three append
|
|
314
|
+
// paths now allocate seqs via reserveSequence/reserveSequenceUnderLock
|
|
315
|
+
// (ST-5: re-read sidecar under lock + max with in-process counter);
|
|
316
|
+
// nextSequence is only consulted for seeding/test helpers, NOT on the
|
|
317
|
+
// production append path. ST-12's perf goal (avoid 4MB scan on first
|
|
318
|
+
// append) is therefore met by ST-5 at the reserveSequence layer.
|
|
298
319
|
const fileMax = scanSequence(eventsPath);
|
|
299
320
|
const safeSeq = Math.max(stored, fileMax);
|
|
300
321
|
sequenceCache.set(eventsPath, {
|
|
@@ -318,7 +339,9 @@ function nextSequence(eventsPath: string): number {
|
|
|
318
339
|
|
|
319
340
|
function persistSequence(eventsPath: string, seq: number): void {
|
|
320
341
|
try {
|
|
321
|
-
|
|
342
|
+
// P0-4: the .seq sidecar is disposable (event-reconstructor tolerates an
|
|
343
|
+
// inconsistent tail); best-effort avoids 2 fsyncs per event append.
|
|
344
|
+
atomicWriteFile(sequencePath(eventsPath), String(seq), { durability: "best-effort" });
|
|
322
345
|
} catch (error) {
|
|
323
346
|
logInternalError("event-log.persist-sequence-file", error, `eventsPath=${eventsPath}`);
|
|
324
347
|
}
|
|
@@ -335,17 +358,26 @@ function persistSequence(eventsPath: string, seq: number): void {
|
|
|
335
358
|
// sidecar durable for crash recovery across restarts.
|
|
336
359
|
const seqCounters = new Map<string, number>();
|
|
337
360
|
|
|
338
|
-
/** Atomically reserve the next sequence number for `eventsPath`.
|
|
361
|
+
/** Atomically reserve the next sequence number for `eventsPath`.
|
|
362
|
+
*
|
|
363
|
+
* ST-5 (v0.9.56): previously this seeded the in-process `seqCounters` counter
|
|
364
|
+
* ONCE per process (reading the `.seq` sidecar a single time via
|
|
365
|
+
* `nextSequence`) and then served every subsequent call purely from that
|
|
366
|
+
* process-local counter. Two processes that both seeded before either had
|
|
367
|
+
* persisted ended up sharing the same counter base -> duplicate sequence
|
|
368
|
+
* numbers -> `sinceSeq` streaming readers silently dropped the second event.
|
|
369
|
+
* The async path was already fixed via `reserveSequenceUnderLock` (which
|
|
370
|
+
* re-reads the sidecar every call); the sync (`appendEvent`) and buffered
|
|
371
|
+
* (`appendEventBatchInsideLock`) paths were NOT.
|
|
372
|
+
*
|
|
373
|
+
* Now ALL three append paths share one body: re-read the authoritative `.seq`
|
|
374
|
+
* sidecar on EVERY call and take `max(sidecar, inProcess)` so a counter that
|
|
375
|
+
* lags behind a sidecar advanced by another process can never assign a
|
|
376
|
+
* regressed (duplicate) seq. Every call site already holds a cross-process
|
|
377
|
+
* file lock (`withEventLogLockSync` for sync/buffered, `withEventLogLockAsync`
|
|
378
|
+
* for async), so the sidecar re-read is race-free within each lock class. */
|
|
339
379
|
function reserveSequence(eventsPath: string): number {
|
|
340
|
-
|
|
341
|
-
if (last === undefined) {
|
|
342
|
-
// Seed once from the authoritative source (sidecar / cache / file scan).
|
|
343
|
-
// nextSequence() returns the NEXT seq to assign, so the last assigned is one less.
|
|
344
|
-
last = nextSequence(eventsPath) - 1;
|
|
345
|
-
}
|
|
346
|
-
const next = last + 1;
|
|
347
|
-
seqCounters.set(eventsPath, next);
|
|
348
|
-
return next;
|
|
380
|
+
return reserveSequenceUnderLock(eventsPath);
|
|
349
381
|
}
|
|
350
382
|
|
|
351
383
|
/** Keep the in-process counter monotonic w.r.t. an explicitly-provided seq
|
|
@@ -501,7 +533,8 @@ async function withEventLogLockAsync<T>(
|
|
|
501
533
|
try {
|
|
502
534
|
await fs.promises.mkdir(lockDir);
|
|
503
535
|
try {
|
|
504
|
-
|
|
536
|
+
// P0-4: the lock pid file is disposable stale-lock state; best-effort.
|
|
537
|
+
atomicWriteFile(pidFile, String(process.pid), { durability: "best-effort" });
|
|
505
538
|
} catch {
|
|
506
539
|
/* best-effort */
|
|
507
540
|
}
|
|
@@ -724,12 +757,15 @@ export async function appendEventAsync(eventsPath: string, event: AppendTeamEven
|
|
|
724
757
|
// Phase 1.5: when worker atomic writer is enabled, append via worker.
|
|
725
758
|
if (isWorkerAtomicWriterEnabled()) {
|
|
726
759
|
await appendFileViaWorker(eventsPath, line);
|
|
727
|
-
//
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
await
|
|
731
|
-
|
|
732
|
-
|
|
760
|
+
// P0-4 (F3a mirror): fsync terminal events only; non-terminal events are
|
|
761
|
+
// informational and the event-reconstructor tolerates an inconsistent tail.
|
|
762
|
+
if (isTerminal) {
|
|
763
|
+
const fd = await fs.promises.open(eventsPath, "r+");
|
|
764
|
+
try {
|
|
765
|
+
await fd.sync();
|
|
766
|
+
} finally {
|
|
767
|
+
await fd.close();
|
|
768
|
+
}
|
|
733
769
|
}
|
|
734
770
|
} else {
|
|
735
771
|
// FIND-10: single-fd append+fsync. Opens in append mode, writes,
|
|
@@ -740,7 +776,8 @@ export async function appendEventAsync(eventsPath: string, event: AppendTeamEven
|
|
|
740
776
|
const fd = await fs.promises.open(eventsPath, "a");
|
|
741
777
|
try {
|
|
742
778
|
await fd.appendFile(line, "utf-8");
|
|
743
|
-
|
|
779
|
+
// P0-4 (F3a mirror): skip the data fsync for non-terminal events.
|
|
780
|
+
if (isTerminal) await fd.sync();
|
|
744
781
|
// FIND-10 R1 fix: the cache-optimization fd.stat() must NOT sit in the
|
|
745
782
|
// seq-durability critical path. If it threw (rare — fd invalidated),
|
|
746
783
|
// it would skip persistSequence below and reopen the seq-reuse
|
|
@@ -764,7 +801,7 @@ export async function appendEventAsync(eventsPath: string, event: AppendTeamEven
|
|
|
764
801
|
// FIND-10: track whether compaction happened after the append so the
|
|
765
802
|
// cache-update stat can safely reuse postAppendStat (file unchanged).
|
|
766
803
|
let compactedAfterAppend = false;
|
|
767
|
-
if (
|
|
804
|
+
if (tickAppendCounter(eventsPath) && needsRotation(eventsPath)) {
|
|
768
805
|
compactedAfterAppend = true;
|
|
769
806
|
try {
|
|
770
807
|
const prepared = prepareCompaction(eventsPath);
|
|
@@ -865,6 +902,8 @@ export async function appendEventAsync(eventsPath: string, event: AppendTeamEven
|
|
|
865
902
|
*/
|
|
866
903
|
async function appendEventBatchInsideLock(eventsPath: string, queue: BufferedAppend[]): Promise<void> {
|
|
867
904
|
if (queue.length === 0) return;
|
|
905
|
+
// P0-2: keep the per-path counter honest for cross-path rotation sampling.
|
|
906
|
+
tickAppendCounter(eventsPath, queue.length);
|
|
868
907
|
fs.mkdirSync(path.dirname(eventsPath), { recursive: true });
|
|
869
908
|
|
|
870
909
|
// Pre-flight size check (mirrors appendEventInsideLock). We do it once for
|
|
@@ -1100,8 +1139,7 @@ function appendEventInsideLock(eventsPath: string, event: AppendTeamEvent): Team
|
|
|
1100
1139
|
logInternalError("event-log.persist-sequence", error, `eventsPath=${eventsPath}`);
|
|
1101
1140
|
}
|
|
1102
1141
|
}
|
|
1103
|
-
|
|
1104
|
-
if (appendCounter % 100 === 0 && needsRotation(eventsPath)) {
|
|
1142
|
+
if (tickAppendCounter(eventsPath) && needsRotation(eventsPath)) {
|
|
1105
1143
|
// Round 24 (BUG 1): we are INSIDE withEventLogLockSync here (called via
|
|
1106
1144
|
// appendEventInsideLock). The mkdir lock is NOT re-entrant, so calling the
|
|
1107
1145
|
// locked compactEventLog would deadlock → 5s timeout → compaction never
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
-
import { logInternalError } from "
|
|
3
|
-
import { redactJsonLine } from "
|
|
2
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
3
|
+
import { redactJsonLine } from "../../utils/redaction.ts";
|
|
4
4
|
|
|
5
5
|
export interface DrainableSource {
|
|
6
6
|
pause(): void;
|
|
@@ -35,8 +35,12 @@ export interface JsonlWriter {
|
|
|
35
35
|
export function createJsonlWriter(filePath: string | undefined, source: DrainableSource, deps: JsonlWriterDeps = {}): JsonlWriter {
|
|
36
36
|
if (!filePath) {
|
|
37
37
|
return {
|
|
38
|
-
writeLine() {
|
|
39
|
-
|
|
38
|
+
writeLine() {
|
|
39
|
+
/* no-op: null writer */
|
|
40
|
+
},
|
|
41
|
+
async close() {
|
|
42
|
+
/* no-op: null writer */
|
|
43
|
+
},
|
|
40
44
|
};
|
|
41
45
|
}
|
|
42
46
|
|
|
@@ -46,8 +50,12 @@ export function createJsonlWriter(filePath: string | undefined, source: Drainabl
|
|
|
46
50
|
stream = createWriteStream(filePath);
|
|
47
51
|
} catch {
|
|
48
52
|
return {
|
|
49
|
-
writeLine() {
|
|
50
|
-
|
|
53
|
+
writeLine() {
|
|
54
|
+
/* no-op: stream creation failed */
|
|
55
|
+
},
|
|
56
|
+
async close() {
|
|
57
|
+
/* no-op: stream creation failed */
|
|
58
|
+
},
|
|
51
59
|
};
|
|
52
60
|
}
|
|
53
61
|
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
import { crewHooks } from "../runtime/crew-hooks.ts";
|
|
7
7
|
|
|
8
8
|
// Lazy-initialized store and paths
|
|
9
|
-
let storeInstance: import("./instinct-store.js").InstinctStore | null = null;
|
|
9
|
+
let storeInstance: import("./stores/instinct-store.js").InstinctStore | null = null;
|
|
10
10
|
let pathsInstance: typeof import("../utils/paths.js") | null = null;
|
|
11
11
|
|
|
12
12
|
async function getStore() {
|
|
13
13
|
if (!storeInstance) {
|
|
14
14
|
// LAZY: defer dynamic import of ./instinct-store.js to its call site.
|
|
15
|
-
const { InstinctStore } = await import("./instinct-store.js");
|
|
15
|
+
const { InstinctStore } = await import("./stores/instinct-store.js");
|
|
16
16
|
// LAZY: defer dynamic import of ../utils/paths.js to its call site.
|
|
17
17
|
const paths = await import("../utils/paths.js");
|
|
18
18
|
storeInstance = new InstinctStore(paths.projectCrewRoot(process.cwd()));
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { DEFAULT_CACHE, DEFAULT_PATHS } from "
|
|
5
|
-
import { userCrewRoot } from "
|
|
6
|
-
import { isSafePathId } from "
|
|
7
|
-
import { sharedScanCache } from "
|
|
8
|
-
import { sleepSync } from "
|
|
9
|
-
import { atomicWriteJson, isSymlinkSafePath, renameWithRetry } from "
|
|
10
|
-
import type { TeamRunManifest } from "
|
|
4
|
+
import { DEFAULT_CACHE, DEFAULT_PATHS } from "../../config/defaults.ts";
|
|
5
|
+
import { userCrewRoot } from "../../utils/paths.ts";
|
|
6
|
+
import { isSafePathId } from "../../utils/safe-paths.ts";
|
|
7
|
+
import { sharedScanCache } from "../../utils/scan-cache.ts";
|
|
8
|
+
import { sleepSync } from "../../utils/sleep.ts";
|
|
9
|
+
import { atomicWriteJson, isSymlinkSafePath, renameWithRetry } from "../atomic-write.ts";
|
|
10
|
+
import type { TeamRunManifest } from "../types.ts";
|
|
11
11
|
|
|
12
12
|
/** Magic bytes prefix for binary registry to prevent deserialization of hostile files. */
|
|
13
13
|
const BINARY_MAGIC = Buffer.from("PICREW2BIN", "utf-8");
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { redactSecretString, redactSecrets } from "
|
|
5
|
-
import { resolveRealContainedPath } from "
|
|
6
|
-
import { atomicWriteFile } from "
|
|
7
|
-
import type { ArtifactDescriptor } from "
|
|
4
|
+
import { redactSecretString, redactSecrets } from "../../utils/redaction.ts";
|
|
5
|
+
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
6
|
+
import { atomicWriteFile } from "../atomic-write.ts";
|
|
7
|
+
import type { ArtifactDescriptor } from "../types.ts";
|
|
8
8
|
|
|
9
9
|
function hashContent(content: string): string {
|
|
10
10
|
return createHash("sha256").update(content).digest("hex");
|
|
@@ -101,6 +101,64 @@ export function cleanupOldArtifacts(artifactsRoot: string, options: ArtifactClea
|
|
|
101
101
|
if (!didCleanup) writeCleanupMarker(artifactsRoot, markerFile);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* ST-10: Default TTL for "temporary" retention artifacts (1 hour).
|
|
106
|
+
* Temporary artifacts (progress, notepad) are short-lived and should not
|
|
107
|
+
* accumulate. One hour balances cleanup aggressiveness with the possibility
|
|
108
|
+
* that a long-running task writes periodic progress updates.
|
|
109
|
+
*/
|
|
110
|
+
export const TEMPORARY_RETENTION_TTL_MS = 60 * 60 * 1000;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* ST-10: Check whether an artifact descriptor indicates the file should be
|
|
114
|
+
* pruned (expired).
|
|
115
|
+
*
|
|
116
|
+
* Enforces:
|
|
117
|
+
* - `expiresAt`: if set and now ≥ expiresAt → expired.
|
|
118
|
+
* - `retention: "temporary"`: if createdAt age ≥ temporaryTtlMs → expired.
|
|
119
|
+
* ("run" and "project" retentions are handled by run-level prune and the
|
|
120
|
+
* age-based {@link cleanupOldArtifacts}, not by this per-descriptor check.)
|
|
121
|
+
*/
|
|
122
|
+
export function isArtifactExpired(desc: ArtifactDescriptor, nowMs: number, temporaryTtlMs: number = TEMPORARY_RETENTION_TTL_MS): boolean {
|
|
123
|
+
// Explicit expiresAt takes precedence.
|
|
124
|
+
if (desc.expiresAt) {
|
|
125
|
+
const expiryMs = Date.parse(desc.expiresAt);
|
|
126
|
+
if (Number.isFinite(expiryMs) && nowMs >= expiryMs) return true;
|
|
127
|
+
}
|
|
128
|
+
// "temporary" retention has a short TTL.
|
|
129
|
+
if (desc.retention === "temporary" && desc.createdAt) {
|
|
130
|
+
const createdMs = Date.parse(desc.createdAt);
|
|
131
|
+
if (Number.isFinite(createdMs) && nowMs - createdMs >= temporaryTtlMs) return true;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* ST-10: Prune expired artifacts by enforcing ArtifactDescriptor.retention/expiresAt.
|
|
138
|
+
*
|
|
139
|
+
* Deletes artifact files whose descriptor indicates expiry (expiresAt passed
|
|
140
|
+
* or temporary-retention TTL exceeded). Returns the count of files deleted.
|
|
141
|
+
*
|
|
142
|
+
* Unlike {@link cleanupOldArtifacts} (which is filesystem age-based on raw
|
|
143
|
+
* files), this operates on artifact *metadata* from the manifest's `artifacts[]`
|
|
144
|
+
* and deletes specific expired files via their descriptor `path`.
|
|
145
|
+
*/
|
|
146
|
+
export function pruneExpiredArtifacts(descriptors: ArtifactDescriptor[], options?: { now?: number; temporaryTtlMs?: number }): number {
|
|
147
|
+
const nowMs = options?.now ?? Date.now();
|
|
148
|
+
const temporaryTtlMs = options?.temporaryTtlMs ?? TEMPORARY_RETENTION_TTL_MS;
|
|
149
|
+
let deleted = 0;
|
|
150
|
+
for (const desc of descriptors) {
|
|
151
|
+
if (!isArtifactExpired(desc, nowMs, temporaryTtlMs)) continue;
|
|
152
|
+
try {
|
|
153
|
+
fs.unlinkSync(desc.path);
|
|
154
|
+
deleted++;
|
|
155
|
+
} catch {
|
|
156
|
+
// Best-effort: file may already be removed or path may be stale.
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return deleted;
|
|
160
|
+
}
|
|
161
|
+
|
|
104
162
|
function resolveInside(baseDir: string, relativePath: string): string {
|
|
105
163
|
// Check if baseDir is a symlink on every call to prevent symlink attacks
|
|
106
164
|
try {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { resolveRealContainedPath } from "
|
|
5
|
-
import { atomicWriteFile, renameWithRetry } from "
|
|
6
|
-
import { withFileLockSync } from "
|
|
4
|
+
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
5
|
+
import { atomicWriteFile, renameWithRetry } from "../atomic-write.ts";
|
|
6
|
+
import { withFileLockSync } from "../coordination/locks.ts";
|
|
7
7
|
|
|
8
8
|
const SHA256_HEX = /^[a-f0-9]{64}$/i;
|
|
9
9
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { ManifestSummary } from "
|
|
4
|
-
import { computeRunHealth } from "
|
|
5
|
-
import { atomicWriteFile } from "
|
|
3
|
+
import type { ManifestSummary } from "../../runtime/task-health.ts";
|
|
4
|
+
import { computeRunHealth } from "../../runtime/task-health.ts";
|
|
5
|
+
import { atomicWriteFile } from "../atomic-write.ts";
|
|
6
6
|
|
|
7
7
|
// Relative to the crew root (`<cwd>/.crew`). BUG A fix (pts/2 hang
|
|
8
8
|
// investigation 2026-06-16): this was `.crew/state/health`, which double-joined
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { assertSafePathId } from "
|
|
5
|
-
import { atomicWriteFile } from "
|
|
4
|
+
import { assertSafePathId } from "../../utils/safe-paths.ts";
|
|
5
|
+
import { atomicWriteFile } from "../atomic-write.ts";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Represents a learned instinct that guides agent behavior.
|
|
@@ -272,4 +272,4 @@ export class InstinctStore {
|
|
|
272
272
|
export {
|
|
273
273
|
getGlobalStorageDir,
|
|
274
274
|
getProjectStorageDir,
|
|
275
|
-
} from "
|
|
275
|
+
} from "../../utils/project-detector.ts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { logInternalError } from "
|
|
3
|
-
import { atomicWriteJson } from "
|
|
2
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
3
|
+
import { atomicWriteJson } from "../atomic-write.ts";
|
|
4
4
|
|
|
5
5
|
// ── Types ────────────────────────────────────────────────────────────────
|
|
6
6
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { projectCrewRoot } from "
|
|
5
|
-
import { atomicWriteJson } from "
|
|
6
|
-
import { withFileLockSync } from "
|
|
7
|
-
import type { TeamTaskState } from "
|
|
4
|
+
import { projectCrewRoot } from "../../utils/paths.ts";
|
|
5
|
+
import { atomicWriteJson } from "../atomic-write.ts";
|
|
6
|
+
import { withFileLockSync } from "../coordination/locks.ts";
|
|
7
|
+
import type { TeamTaskState } from "../types.ts";
|
|
8
8
|
|
|
9
9
|
const DEFAULT_CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
10
10
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { projectCrewRoot } from "
|
|
4
|
-
import { assertSafePathId } from "
|
|
5
|
-
import { atomicWriteFile } from "
|
|
6
|
-
import type { TeamRunManifest, TeamTaskState } from "
|
|
3
|
+
import { projectCrewRoot } from "../../utils/paths.ts";
|
|
4
|
+
import { assertSafePathId } from "../../utils/safe-paths.ts";
|
|
5
|
+
import { atomicWriteFile } from "../atomic-write.ts";
|
|
6
|
+
import type { TeamRunManifest, TeamTaskState } from "../types.ts";
|
|
7
7
|
|
|
8
8
|
export interface RunGraphNode {
|
|
9
9
|
id: string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { projectCrewRoot } from "
|
|
4
|
-
import { assertSafePathId } from "
|
|
5
|
-
import { atomicWriteJson, readJsonFile } from "
|
|
3
|
+
import { projectCrewRoot } from "../../utils/paths.ts";
|
|
4
|
+
import { assertSafePathId } from "../../utils/safe-paths.ts";
|
|
5
|
+
import { atomicWriteJson, readJsonFile } from "../atomic-write.ts";
|
|
6
6
|
import { loadRunManifestById } from "./state-store.ts";
|
|
7
7
|
|
|
8
8
|
/**
|