@gajae-code/coding-agent 0.11.11 → 0.12.1
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 +131 -4
- package/dist/types/async/job-manager.d.ts +17 -3
- package/dist/types/cli/read-cli.d.ts +1 -0
- package/dist/types/commands/deep-interview.d.ts +9 -0
- package/dist/types/commands/harness.d.ts +22 -0
- package/dist/types/commands/read.d.ts +6 -0
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/provider-auth-health.d.ts +14 -0
- package/dist/types/config/provider-ranking.d.ts +59 -0
- package/dist/types/config/settings-schema.d.ts +83 -1
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/exa/mcp-client.d.ts +10 -1
- package/dist/types/exec/bash-executor.d.ts +45 -12
- package/dist/types/extensibility/extensions/types.d.ts +38 -4
- package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
- package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
- package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
- package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
- package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
- package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
- package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
- package/dist/types/extensibility/shared-events.d.ts +6 -0
- package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
- package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
- package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
- package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +70 -1
- package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
- package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
- package/dist/types/gjc-runtime/team-runtime.d.ts +27 -1
- package/dist/types/gjc-runtime/team-store.d.ts +12 -0
- package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
- package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +17 -0
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +31 -80
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
- package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
- package/dist/types/main.d.ts +1 -1
- package/dist/types/memories/index.d.ts +2 -0
- package/dist/types/modes/acp/acp-agent.d.ts +10 -19
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
- package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
- package/dist/types/modes/components/read-tool-group.d.ts +4 -4
- package/dist/types/modes/components/session-observer-overlay.d.ts +22 -0
- package/dist/types/modes/components/settings-selector.d.ts +11 -0
- package/dist/types/modes/components/status-line/gh.d.ts +5 -0
- package/dist/types/modes/components/tool-execution.d.ts +8 -0
- package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
- package/dist/types/modes/controllers/event-controller.d.ts +3 -0
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
- package/dist/types/reminders/star-reminder.d.ts +3 -13
- package/dist/types/runtime-mcp/manager.d.ts +1 -0
- package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
- package/dist/types/sdk/acp/adapter.d.ts +3 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +5 -0
- package/dist/types/sdk/broker/transport.d.ts +2 -0
- package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -1
- package/dist/types/sdk/bus/config.d.ts +6 -2
- package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
- package/dist/types/sdk/bus/index.d.ts +44 -1
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +44 -0
- package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
- package/dist/types/sdk/bus/reconciliation-store.d.ts +69 -0
- package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
- package/dist/types/sdk/bus/rich-render.d.ts +2 -0
- package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
- package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -4
- package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
- package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
- package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
- package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/host/query/handlers.d.ts +5 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
- package/dist/types/sdk/prompt-status.d.ts +23 -3
- package/dist/types/sdk/session.d.ts +6 -0
- package/dist/types/session/agent-session.d.ts +82 -12
- package/dist/types/session/artifacts.d.ts +8 -0
- package/dist/types/session/blob-store.d.ts +57 -4
- package/dist/types/session/internal/managed-session-storage.d.ts +8 -1
- package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
- package/dist/types/session/session-manager.d.ts +48 -19
- package/dist/types/session/session-storage.d.ts +4 -0
- package/dist/types/session/streaming-output.d.ts +96 -12
- package/dist/types/setup/credential-import.d.ts +12 -0
- package/dist/types/skill-state/active-state.d.ts +12 -4
- package/dist/types/skill-state/workflow-hud.d.ts +9 -0
- package/dist/types/task/executor.d.ts +3 -2
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/provider-retry-status.d.ts +8 -0
- package/dist/types/task/receipt.d.ts +7 -1
- package/dist/types/task/types.d.ts +23 -0
- package/dist/types/tools/ask-answer-registry.d.ts +2 -2
- package/dist/types/tools/bash-interactive.d.ts +4 -1
- package/dist/types/tools/bash.d.ts +3 -1
- package/dist/types/tools/browser/launch.d.ts +7 -0
- package/dist/types/tools/fetch.d.ts +17 -1
- package/dist/types/tools/image-gen.d.ts +4 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/output-meta.d.ts +44 -3
- package/dist/types/tools/path-utils.d.ts +1 -0
- package/dist/types/tools/read-internals.d.ts +12 -0
- package/dist/types/tools/read.d.ts +45 -7
- package/dist/types/tools/resource-gc.d.ts +4 -0
- package/dist/types/tools/review.d.ts +5 -7
- package/dist/types/tools/subagent.d.ts +2 -0
- package/dist/types/tools/tool-result.d.ts +7 -1
- package/dist/types/utils/gh.d.ts +13 -0
- package/dist/types/utils/image-resize.d.ts +1 -0
- package/dist/types/web/search/providers/kimi.d.ts +2 -0
- package/dist/types/web/search/providers/searxng.d.ts +7 -0
- package/dist/types/web/search/providers/xai.d.ts +2 -0
- package/package.json +11 -13
- package/scripts/acp-conformance-agent.ts +218 -0
- package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
- package/scripts/capture-gjc-bundle-settings.ts +306 -0
- package/scripts/capture-sticky-viewport-showcase.ts +292 -0
- package/scripts/generate-sdk-operation-inventory.ts +5 -0
- package/scripts/resident-memory-bench.ts +1341 -0
- package/scripts/run-acp-conformance.ts +285 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
- package/scripts/verify-sticky-viewport-showcase.ts +611 -0
- package/src/async/job-manager.ts +78 -20
- package/src/capability/index.ts +8 -0
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/plugin-cli.ts +176 -18
- package/src/cli/read-cli.ts +2 -1
- package/src/cli.ts +1 -0
- package/src/commands/deep-interview.ts +29 -9
- package/src/commands/harness.ts +35 -12
- package/src/commands/read.ts +11 -2
- package/src/commands/team.ts +20 -2
- package/src/config/file-lock.ts +11 -2
- package/src/config/model-registry.ts +21 -2
- package/src/config/provider-auth-health.ts +42 -0
- package/src/config/provider-ranking.ts +119 -0
- package/src/config/settings-schema.ts +74 -1
- package/src/config/settings.ts +246 -108
- package/src/coordinator-mcp/question-gate-codec.ts +1 -1
- package/src/coordinator-mcp/server.ts +5 -12
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +230 -82
- package/src/defaults/gjc/skills/ralplan/SKILL.md +77 -41
- package/src/defaults/gjc/skills/team/SKILL.md +3 -1
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +62 -39
- package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
- package/src/defaults/gjc-defaults.ts +4 -4
- package/src/eval/py/executor.ts +7 -2
- package/src/exa/mcp-client.ts +12 -3
- package/src/exec/bash-executor.ts +144 -27
- package/src/extensibility/extensions/runner.ts +15 -0
- package/src/extensibility/extensions/types.ts +46 -5
- package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
- package/src/extensibility/gjc-plugins/index.ts +19 -2
- package/src/extensibility/gjc-plugins/installer.ts +189 -50
- package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
- package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
- package/src/extensibility/gjc-plugins/observability.ts +3 -3
- package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
- package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
- package/src/extensibility/gjc-plugins/schema.ts +84 -12
- package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
- package/src/extensibility/gjc-plugins/types.ts +141 -0
- package/src/extensibility/gjc-plugins/validation.ts +9 -0
- package/src/extensibility/shared-events.ts +5 -0
- package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -82
- package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
- package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
- package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
- package/src/gjc-runtime/deep-interview-state.ts +12 -943
- package/src/gjc-runtime/gc-render.ts +1 -0
- package/src/gjc-runtime/gc-runtime.ts +11 -1
- package/src/gjc-runtime/launch-tmux.ts +25 -6
- package/src/gjc-runtime/managed-owner-admission.ts +1 -1
- package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
- package/src/gjc-runtime/ralplan-runtime.ts +1149 -98
- package/src/gjc-runtime/state-runtime.ts +2 -1
- package/src/gjc-runtime/state-writer.ts +70 -222
- package/src/gjc-runtime/team-launch.ts +42 -5
- package/src/gjc-runtime/team-runtime.ts +1085 -40
- package/src/gjc-runtime/team-store.ts +32 -0
- package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
- package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
- package/src/gjc-runtime/team-workers.ts +1 -0
- package/src/gjc-runtime/tmux-owner-isolation.ts +28 -0
- package/src/gjc-runtime/tmux-sessions.ts +58 -13
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +414 -618
- package/src/gjc-runtime/workflow-manifest.generated.json +105 -449
- package/src/gjc-runtime/workflow-manifest.ts +38 -247
- package/src/hooks/native-skill-hook.ts +17 -4
- package/src/hooks/skill-state.ts +1 -23
- package/src/internal-urls/docs-index.generated.ts +21 -22
- package/src/internal-urls/local-root-gc.ts +127 -0
- package/src/main.ts +9 -5
- package/src/memories/index.ts +10 -0
- package/src/modes/DESIGN.md +98 -0
- package/src/modes/acp/acp-agent.ts +339 -191
- package/src/modes/acp/acp-event-mapper.ts +14 -7
- package/src/modes/acp/acp-mode.ts +39 -3
- package/src/modes/components/assistant-message.ts +123 -22
- package/src/modes/components/gjc-bundle-settings.ts +508 -0
- package/src/modes/components/irc-sidebar.ts +176 -62
- package/src/modes/components/model-selector.ts +61 -4
- package/src/modes/components/notifications-settings-editor.ts +12 -1
- package/src/modes/components/oauth-selector.ts +96 -28
- package/src/modes/components/read-tool-group.ts +82 -14
- package/src/modes/components/session-observer-overlay.ts +457 -83
- package/src/modes/components/settings-selector.ts +116 -23
- package/src/modes/components/status-line/gh.ts +16 -0
- package/src/modes/components/tool-execution.ts +138 -27
- package/src/modes/components/tool-status-header.ts +3 -14
- package/src/modes/components/transcript-viewer-overlay.ts +99 -24
- package/src/modes/controllers/command-controller.ts +4 -0
- package/src/modes/controllers/event-controller.ts +109 -27
- package/src/modes/controllers/extension-ui-controller.ts +26 -2
- package/src/modes/controllers/input-controller.ts +18 -3
- package/src/modes/controllers/selector-controller.ts +127 -36
- package/src/modes/interactive-mode.ts +62 -3
- package/src/modes/irc-observation-ledger.ts +71 -15
- package/src/modes/runtime-init.ts +22 -2
- package/src/modes/types.ts +2 -0
- package/src/modes/utils/ui-helpers.ts +94 -1
- package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
- package/src/prompts/agents/architect.md +9 -1
- package/src/prompts/agents/critic.md +9 -0
- package/src/prompts/system/eager-todo.md +8 -4
- package/src/prompts/system/system-prompt.md +11 -5
- package/src/prompts/tools/bash.md +5 -5
- package/src/prompts/tools/read.md +4 -2
- package/src/prompts/tools/search-tool-bm25.md +5 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/reminders/star-reminder.ts +4 -42
- package/src/runtime-mcp/manager.ts +19 -4
- package/src/runtime-mcp/smithery-auth.ts +17 -2
- package/src/runtime-mcp/smithery-connect.ts +11 -1
- package/src/sdk/acp/adapter.ts +22 -6
- package/src/sdk/broker/lifecycle.ts +25 -6
- package/src/sdk/broker/transport.ts +35 -3
- package/src/sdk/bus/attachment-registry.ts +5 -1
- package/src/sdk/bus/chat-daemon-cli.ts +4 -39
- package/src/sdk/bus/chat-daemon-control.ts +6 -3
- package/src/sdk/bus/config.ts +18 -2
- package/src/sdk/bus/control-drain-lease.ts +104 -0
- package/src/sdk/bus/index.ts +984 -146
- package/src/sdk/bus/kind-aware-reconciliation.ts +317 -0
- package/src/sdk/bus/lifecycle-commands.ts +4 -1
- package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
- package/src/sdk/bus/prompt-reconciliation.ts +2 -1
- package/src/sdk/bus/reconciliation-store.ts +303 -0
- package/src/sdk/bus/rich-draft.ts +1 -1
- package/src/sdk/bus/rich-render.ts +2 -2
- package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
- package/src/sdk/bus/telegram-cli.ts +33 -8
- package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +11 -4
- package/src/sdk/bus/telegram-daemon.ts +916 -23
- package/src/sdk/bus/telegram-reference.ts +40 -3
- package/src/sdk/bus/threaded-render.ts +48 -3
- package/src/sdk/bus/topic-registry.ts +20 -0
- package/src/sdk/host/control/dispatch.ts +5 -1
- package/src/sdk/host/control/operations.ts +1 -1
- package/src/sdk/host/host.ts +23 -1
- package/src/sdk/host/query/handlers.ts +55 -0
- package/src/sdk/host/query/revision-store.ts +36 -2
- package/src/sdk/host/reverse-leases.ts +44 -7
- package/src/sdk/mcp/server.ts +46 -18
- package/src/sdk/prompt-status.ts +16 -3
- package/src/sdk/protocol/operation-inventory.generated.json +51 -0
- package/src/sdk/protocol/operation-registry.ts +7 -2
- package/src/sdk/session.ts +101 -10
- package/src/session/agent-session.ts +1286 -220
- package/src/session/artifacts.ts +22 -0
- package/src/session/auth-broker-config.ts +10 -3
- package/src/session/blob-store.ts +915 -24
- package/src/session/internal/managed-session-scope.ts +44 -6
- package/src/session/internal/managed-session-storage.ts +48 -6
- package/src/session/memory-guard-checkpoint-participant.ts +131 -0
- package/src/session/session-manager.ts +2364 -438
- package/src/session/session-storage.ts +9 -1
- package/src/session/streaming-output.ts +500 -111
- package/src/setup/credential-import.ts +75 -13
- package/src/setup/provider-onboarding.ts +19 -4
- package/src/skill-state/active-state.ts +32 -10
- package/src/skill-state/workflow-hud.ts +42 -2
- package/src/skill-state/workflow-mutation-guard.ts +560 -8
- package/src/task/executor.ts +122 -39
- package/src/task/index.ts +23 -14
- package/src/task/provider-retry-status.ts +16 -0
- package/src/task/receipt.ts +23 -7
- package/src/task/render.ts +6 -2
- package/src/task/types.ts +108 -0
- package/src/tools/ask-answer-registry.ts +12 -6
- package/src/tools/ask.ts +169 -118
- package/src/tools/ast-edit.ts +1 -0
- package/src/tools/ast-grep.ts +1 -0
- package/src/tools/bash-interactive.ts +8 -3
- package/src/tools/bash.ts +503 -60
- package/src/tools/browser/launch.ts +41 -6
- package/src/tools/fetch.ts +114 -23
- package/src/tools/find.ts +1 -0
- package/src/tools/image-gen.ts +29 -5
- package/src/tools/index.ts +4 -0
- package/src/tools/output-meta.ts +281 -20
- package/src/tools/path-utils.ts +8 -3
- package/src/tools/read-internals.ts +44 -0
- package/src/tools/read.ts +1560 -310
- package/src/tools/resource-gc.ts +182 -18
- package/src/tools/review.ts +5 -7
- package/src/tools/search.ts +1 -0
- package/src/tools/subagent-render.ts +6 -2
- package/src/tools/subagent.ts +6 -0
- package/src/tools/telegram-send.ts +6 -3
- package/src/tools/tool-result.ts +14 -1
- package/src/utils/gh.ts +39 -0
- package/src/utils/image-resize.ts +3 -0
- package/src/web/search/providers/anthropic.ts +4 -4
- package/src/web/search/providers/codex.ts +1 -1
- package/src/web/search/providers/kimi.ts +15 -5
- package/src/web/search/providers/searxng.ts +47 -4
- package/src/web/search/providers/xai.ts +7 -2
- package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
- package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
- package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
- package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
- package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
- package/src/gjc-runtime/deep-interview-draft.ts +0 -843
- package/src/gjc-runtime/deep-interview-payload.ts +0 -262
- package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
- package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
|
@@ -857,7 +857,8 @@ function buildHudForMode(
|
|
|
857
857
|
: typeof payload.mode === "string"
|
|
858
858
|
? (payload.mode as string)
|
|
859
859
|
: undefined;
|
|
860
|
-
const
|
|
860
|
+
const rawVerdict = payload.last_review_verdict ?? payload.verdict;
|
|
861
|
+
const verdict = typeof rawVerdict === "string" ? rawVerdict : undefined;
|
|
861
862
|
const iteration = typeof payload.iteration === "number" ? (payload.iteration as number) : undefined;
|
|
862
863
|
const pendingApproval = payload.pending_approval === true || stage === "final";
|
|
863
864
|
return buildRalplanHudSummary({
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
type WorkflowStateMutationOwner,
|
|
12
12
|
type WorkflowStateReceipt,
|
|
13
13
|
} from "../skill-state/workflow-state-contract";
|
|
14
|
-
import { validateDeepInterviewV1Envelope } from "./deep-interview-state";
|
|
15
14
|
import {
|
|
16
15
|
activeEntryPath as layoutActiveEntryPath,
|
|
17
16
|
activeSnapshotPath as layoutActiveSnapshotPath,
|
|
@@ -78,47 +77,6 @@ export interface WorkflowEnvelopeIntegrityMismatch {
|
|
|
78
77
|
expected: string;
|
|
79
78
|
actual: string;
|
|
80
79
|
}
|
|
81
|
-
export type WorkflowReceiptVerification =
|
|
82
|
-
| "legacy"
|
|
83
|
-
| "native-valid"
|
|
84
|
-
| "receipt-malformed"
|
|
85
|
-
| "receipt-missing"
|
|
86
|
-
| "checksum-mismatch";
|
|
87
|
-
|
|
88
|
-
export interface GuardedWorkflowEnvelopeTransformOptions extends StateWriterOptions {
|
|
89
|
-
expectedRevision: number;
|
|
90
|
-
/** Additional native schema validation applied to both current and candidate envelopes. */
|
|
91
|
-
validate?: (value: Record<string, unknown>, legacy: boolean) => void;
|
|
92
|
-
transform: (
|
|
93
|
-
current: Record<string, unknown>,
|
|
94
|
-
context: { revision: number; legacy: boolean },
|
|
95
|
-
) =>
|
|
96
|
-
| { kind: "noop" }
|
|
97
|
-
| { kind: "write"; value: Record<string, unknown> }
|
|
98
|
-
| Promise<{ kind: "noop" } | { kind: "write"; value: Record<string, unknown> }>;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export interface GuardedWorkflowEnvelopeWarning {
|
|
102
|
-
code: "DI_POST_COMMIT_AUDIT_FAILED";
|
|
103
|
-
message: string;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export type GuardedWorkflowEnvelopeTransformResult =
|
|
107
|
-
| { path: string; written: false; reason: "noop"; revision: number; warnings: [] }
|
|
108
|
-
| {
|
|
109
|
-
path: string;
|
|
110
|
-
written: true;
|
|
111
|
-
revision: number;
|
|
112
|
-
stamped: Record<string, unknown>;
|
|
113
|
-
warnings: GuardedWorkflowEnvelopeWarning[];
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
export class GuardedWorkflowEnvelopeError extends Error {
|
|
117
|
-
constructor(public readonly code: string) {
|
|
118
|
-
super(code);
|
|
119
|
-
this.name = "GuardedWorkflowEnvelopeError";
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
80
|
|
|
123
81
|
export interface WorkflowTransactionJournal {
|
|
124
82
|
version: 1;
|
|
@@ -138,7 +96,6 @@ export interface GuardedStateWriterOptions extends StateWriterOptions {
|
|
|
138
96
|
policy: StateWritePolicy;
|
|
139
97
|
expectedRevision?: number;
|
|
140
98
|
sourceRevision?: number;
|
|
141
|
-
lockHeld?: boolean;
|
|
142
99
|
}
|
|
143
100
|
|
|
144
101
|
export type GuardedWriteResult =
|
|
@@ -150,13 +107,17 @@ export interface StateWriterOptions {
|
|
|
150
107
|
receipt?: StateWriterReceiptContext;
|
|
151
108
|
audit?: StateWriterAuditContext;
|
|
152
109
|
sourceRevision?: number;
|
|
153
|
-
orderingRevision?: number;
|
|
154
110
|
/**
|
|
155
111
|
* Cross-process lock tuning for read-modify-write paths that route through
|
|
156
112
|
* `withWorkflowStateLock` / `updateJsonAtomic`. Omit for the hardened
|
|
157
113
|
* `withFileLock` defaults.
|
|
158
114
|
*/
|
|
159
115
|
lock?: FileLockOptions;
|
|
116
|
+
/**
|
|
117
|
+
* Caller already holds the workflow state lock for this target path (via
|
|
118
|
+
* `withWorkflowStateLock`). Skip re-acquisition to avoid self-deadlock.
|
|
119
|
+
*/
|
|
120
|
+
lockHeld?: boolean;
|
|
160
121
|
}
|
|
161
122
|
|
|
162
123
|
export class StateWriteConflictError extends Error {
|
|
@@ -298,49 +259,6 @@ export function workflowEnvelopeContentSha256(value: unknown): string {
|
|
|
298
259
|
.update(JSON.stringify(canonicalizeJson(withoutReceiptChecksum(value))))
|
|
299
260
|
.digest("hex");
|
|
300
261
|
}
|
|
301
|
-
export function isNativeDeepInterviewV1(value: Record<string, unknown>): boolean {
|
|
302
|
-
if (value.skill !== "deep-interview") return false;
|
|
303
|
-
return value.schema_version === 1 || (isPlainObject(value.state) && value.state.schema_version === 1);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
export function verifyWorkflowEnvelopeReceiptValue(value: unknown, filePath: string): WorkflowReceiptVerification {
|
|
307
|
-
if (!isPlainObject(value)) return "receipt-malformed";
|
|
308
|
-
const native = isNativeDeepInterviewV1(value);
|
|
309
|
-
if (!Object.hasOwn(value, "receipt")) return native ? "receipt-missing" : "legacy";
|
|
310
|
-
if (!isPlainObject(value.receipt) || !isPlainObject(value.receipt.content_sha256)) return "receipt-malformed";
|
|
311
|
-
|
|
312
|
-
const receipt = value.receipt as Record<string, unknown>;
|
|
313
|
-
const checksum = receipt.content_sha256 as Record<string, unknown>;
|
|
314
|
-
if (
|
|
315
|
-
typeof value.skill !== "string" ||
|
|
316
|
-
receipt.version !== 1 ||
|
|
317
|
-
receipt.skill !== value.skill ||
|
|
318
|
-
(receipt.skill !== "deep-interview" &&
|
|
319
|
-
receipt.skill !== "ralplan" &&
|
|
320
|
-
receipt.skill !== "ultragoal" &&
|
|
321
|
-
receipt.skill !== "team") ||
|
|
322
|
-
(receipt.owner !== "gjc-state-cli" && receipt.owner !== "gjc-runtime" && receipt.owner !== "gjc-hook") ||
|
|
323
|
-
typeof receipt.command !== "string" ||
|
|
324
|
-
typeof receipt.state_path !== "string" ||
|
|
325
|
-
typeof receipt.storage_path !== "string" ||
|
|
326
|
-
typeof receipt.mutated_at !== "string" ||
|
|
327
|
-
!Number.isFinite(Date.parse(receipt.mutated_at)) ||
|
|
328
|
-
typeof receipt.fresh_until !== "string" ||
|
|
329
|
-
!Number.isFinite(Date.parse(receipt.fresh_until)) ||
|
|
330
|
-
(receipt.status !== "fresh" && receipt.status !== "stale") ||
|
|
331
|
-
typeof receipt.mutation_id !== "string" ||
|
|
332
|
-
checksum.algorithm !== "sha256" ||
|
|
333
|
-
typeof checksum.value !== "string" ||
|
|
334
|
-
!/^[0-9a-f]{64}$/.test(checksum.value) ||
|
|
335
|
-
typeof checksum.covered_path !== "string" ||
|
|
336
|
-
path.resolve(checksum.covered_path) !== path.resolve(filePath) ||
|
|
337
|
-
typeof checksum.computed_at !== "string" ||
|
|
338
|
-
!Number.isFinite(Date.parse(checksum.computed_at))
|
|
339
|
-
) {
|
|
340
|
-
return "receipt-malformed";
|
|
341
|
-
}
|
|
342
|
-
return workflowEnvelopeContentSha256(value) === checksum.value ? "native-valid" : "checksum-mismatch";
|
|
343
|
-
}
|
|
344
262
|
|
|
345
263
|
export function stampWorkflowEnvelopeChecksum<T>(value: T, filePath: string, computedAt = new Date().toISOString()): T {
|
|
346
264
|
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
@@ -507,11 +425,6 @@ function persistedSourceRevision(value: unknown): number {
|
|
|
507
425
|
const revision = value.source_state_revision;
|
|
508
426
|
return typeof revision === "number" && Number.isFinite(revision) ? revision : persistedStateRevision(value);
|
|
509
427
|
}
|
|
510
|
-
function persistedCommittedModeRevision(value: unknown): number {
|
|
511
|
-
if (!isPlainObject(value)) return 0;
|
|
512
|
-
const revision = value.committed_mode_state_revision;
|
|
513
|
-
return typeof revision === "number" && Number.isFinite(revision) ? revision : 0;
|
|
514
|
-
}
|
|
515
428
|
|
|
516
429
|
function withoutCandidateRevision(value: unknown): unknown {
|
|
517
430
|
if (!isPlainObject(value)) return value;
|
|
@@ -620,12 +533,7 @@ async function writeGuardedResolvedJsonAtomic(
|
|
|
620
533
|
|
|
621
534
|
const incomingSourceRevision =
|
|
622
535
|
options.sourceRevision ?? (isPlainObject(value) ? persistedStateRevision(value) : 0);
|
|
623
|
-
if (
|
|
624
|
-
current !== undefined &&
|
|
625
|
-
(options.orderingRevision !== undefined
|
|
626
|
-
? options.orderingRevision <= persistedCommittedModeRevision(current)
|
|
627
|
-
: incomingSourceRevision <= persistedSourceRevision(current))
|
|
628
|
-
) {
|
|
536
|
+
if (current !== undefined && incomingSourceRevision <= persistedSourceRevision(current)) {
|
|
629
537
|
return { path: filePath, written: false, reason: "stale-skip", revision: currentRevision };
|
|
630
538
|
}
|
|
631
539
|
const next = stampStateRevision(
|
|
@@ -659,7 +567,6 @@ export async function writeGuardedWorkflowEnvelopeAtomic(
|
|
|
659
567
|
const write = async (): Promise<GuardedWriteResult> => {
|
|
660
568
|
const current = await readJsonIfPresentTolerant(filePath);
|
|
661
569
|
const currentRevision = persistedStateRevision(current);
|
|
662
|
-
|
|
663
570
|
if (options.policy === "source") {
|
|
664
571
|
if (options.expectedRevision !== undefined && options.expectedRevision !== currentRevision) {
|
|
665
572
|
throw new StateWriteConflictError(filePath, options.expectedRevision, currentRevision);
|
|
@@ -683,15 +590,9 @@ export async function writeGuardedWorkflowEnvelopeAtomic(
|
|
|
683
590
|
await maybeAudit(filePath, options);
|
|
684
591
|
return { path: filePath, written: true, revision: currentRevision + 1, stamped: next };
|
|
685
592
|
}
|
|
686
|
-
|
|
687
593
|
const incomingSourceRevision =
|
|
688
594
|
options.sourceRevision ?? (isPlainObject(value) ? persistedStateRevision(value) : 0);
|
|
689
|
-
if (
|
|
690
|
-
current !== undefined &&
|
|
691
|
-
(options.orderingRevision !== undefined
|
|
692
|
-
? options.orderingRevision <= persistedCommittedModeRevision(current)
|
|
693
|
-
: incomingSourceRevision <= persistedSourceRevision(current))
|
|
694
|
-
) {
|
|
595
|
+
if (current !== undefined && incomingSourceRevision <= persistedSourceRevision(current)) {
|
|
695
596
|
return { path: filePath, written: false, reason: "stale-skip", revision: currentRevision };
|
|
696
597
|
}
|
|
697
598
|
const next = stampWorkflowEnvelopeRevisionAndChecksum(
|
|
@@ -715,67 +616,6 @@ export async function writeGuardedWorkflowEnvelopeAtomic(
|
|
|
715
616
|
};
|
|
716
617
|
return options.lockHeld ? write() : lockResolvedWorkflowTarget(filePath, write, options.lock);
|
|
717
618
|
}
|
|
718
|
-
export async function transformGuardedWorkflowEnvelopeAtomic(
|
|
719
|
-
targetPath: string,
|
|
720
|
-
options: GuardedWorkflowEnvelopeTransformOptions,
|
|
721
|
-
): Promise<GuardedWorkflowEnvelopeTransformResult> {
|
|
722
|
-
const filePath = resolveGjcTarget(targetPath, cwdForOptions(options));
|
|
723
|
-
return lockResolvedWorkflowTarget(
|
|
724
|
-
filePath,
|
|
725
|
-
async () => {
|
|
726
|
-
const read = await readExistingStateForMutation(filePath);
|
|
727
|
-
if (read.kind === "absent") throw new GuardedWorkflowEnvelopeError("DI_STATE_ABSENT");
|
|
728
|
-
if (read.kind === "corrupt") throw new GuardedWorkflowEnvelopeError("DI_STATE_CORRUPT");
|
|
729
|
-
const receipt = verifyWorkflowEnvelopeReceiptValue(read.value, filePath);
|
|
730
|
-
if (receipt === "receipt-malformed") throw new GuardedWorkflowEnvelopeError("DI_RECEIPT_MALFORMED");
|
|
731
|
-
if (receipt === "receipt-missing") throw new GuardedWorkflowEnvelopeError("DI_RECEIPT_MISSING");
|
|
732
|
-
if (receipt === "checksum-mismatch") throw new GuardedWorkflowEnvelopeError("DI_RECEIPT_CHECKSUM_MISMATCH");
|
|
733
|
-
const legacy = receipt === "legacy";
|
|
734
|
-
try {
|
|
735
|
-
if (isNativeDeepInterviewV1(read.value)) validateDeepInterviewV1Envelope(read.value);
|
|
736
|
-
options.validate?.(read.value, legacy);
|
|
737
|
-
} catch {
|
|
738
|
-
throw new GuardedWorkflowEnvelopeError("DI_STATE_SCHEMA_INVALID");
|
|
739
|
-
}
|
|
740
|
-
const phase = read.value.current_phase;
|
|
741
|
-
if (phase === "complete" || phase === "handoff" || read.value.active === false) {
|
|
742
|
-
throw new GuardedWorkflowEnvelopeError("DI_PHASE_NOT_REPAIRABLE");
|
|
743
|
-
}
|
|
744
|
-
const revision = persistedStateRevision(read.value);
|
|
745
|
-
if (revision !== options.expectedRevision) throw new GuardedWorkflowEnvelopeError("DI_REVISION_CONFLICT");
|
|
746
|
-
const transformed = await options.transform(read.value, { revision, legacy });
|
|
747
|
-
if (transformed.kind === "noop")
|
|
748
|
-
return { path: filePath, written: false, reason: "noop", revision, warnings: [] };
|
|
749
|
-
try {
|
|
750
|
-
if (isNativeDeepInterviewV1(transformed.value)) validateDeepInterviewV1Envelope(transformed.value);
|
|
751
|
-
options.validate?.(transformed.value, false);
|
|
752
|
-
} catch {
|
|
753
|
-
throw new GuardedWorkflowEnvelopeError("DI_STATE_SCHEMA_INVALID");
|
|
754
|
-
}
|
|
755
|
-
const stamped = stampWorkflowEnvelopeRevisionAndChecksum(
|
|
756
|
-
transformed.value,
|
|
757
|
-
filePath,
|
|
758
|
-
revision + 1,
|
|
759
|
-
undefined,
|
|
760
|
-
options,
|
|
761
|
-
) as Record<string, unknown>;
|
|
762
|
-
const parsed = RequiredOnWriteEnvelopeSchema.safeParse(stamped);
|
|
763
|
-
if (!parsed.success) throw new GuardedWorkflowEnvelopeError("DI_STATE_SCHEMA_INVALID");
|
|
764
|
-
await atomicWrite(filePath, jsonText(stamped));
|
|
765
|
-
const warnings: GuardedWorkflowEnvelopeWarning[] = [];
|
|
766
|
-
try {
|
|
767
|
-
await maybeAudit(filePath, options);
|
|
768
|
-
} catch (error) {
|
|
769
|
-
warnings.push({
|
|
770
|
-
code: "DI_POST_COMMIT_AUDIT_FAILED",
|
|
771
|
-
message: error instanceof Error ? error.message : String(error),
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
return { path: filePath, written: true, revision: revision + 1, stamped, warnings };
|
|
775
|
-
},
|
|
776
|
-
options.lock,
|
|
777
|
-
);
|
|
778
|
-
}
|
|
779
619
|
|
|
780
620
|
export async function writeJsonAtomic(
|
|
781
621
|
targetPath: string,
|
|
@@ -845,63 +685,71 @@ export async function writeWorkflowEnvelopeAtomic(
|
|
|
845
685
|
options?: StateWriterOptions,
|
|
846
686
|
): Promise<string> {
|
|
847
687
|
const filePath = resolveGjcTarget(targetPath, cwdForOptions(options));
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
688
|
+
const write = async (): Promise<string> => {
|
|
689
|
+
const withReceipt = withWorkflowReceipt(value, buildReceipt(options));
|
|
690
|
+
const stamped = stampWorkflowEnvelopeChecksum(withReceipt, filePath);
|
|
691
|
+
const parsed = RequiredOnWriteEnvelopeSchema.safeParse(stamped);
|
|
692
|
+
if (!parsed.success) {
|
|
693
|
+
throw new Error(
|
|
694
|
+
`Refusing to write invalid workflow state envelope to ${filePath}: ${parsed.error.issues
|
|
695
|
+
.map(issue => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
|
|
696
|
+
.join("; ")}`,
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
// #658: internal runtime writers (ralplan/ultragoal/deep-interview/team) persist
|
|
700
|
+
// envelopes directly, bypassing the `gjc state` CLI transition gate (`isValidTransition`,
|
|
701
|
+
// historically the sole call site in state-runtime.ts). Re-assert that gate on every
|
|
702
|
+
// sanctioned envelope write so internal writes cannot persist invalid state-machine phase
|
|
703
|
+
// transitions silently. Forced writes (`gjc state ... --force`, reconcile repairs) carry
|
|
704
|
+
// `audit.forced` and bypass, mirroring the CLI's `use --force to bypass`.
|
|
705
|
+
//
|
|
706
|
+
// The gate governs ACTIVE workflow progression only. Deactivation/teardown writes
|
|
707
|
+
// (`active: false`, e.g. `gjc state clear`, which persists the universal `complete`
|
|
708
|
+
// sentinel that is not a per-skill manifest state) leave the transition graph and are
|
|
709
|
+
// intentionally exempt.
|
|
710
|
+
if (options?.audit?.forced !== true && parsed.data.active === true) {
|
|
711
|
+
const toPhase = parsed.data.current_phase.trim();
|
|
712
|
+
if (toPhase) {
|
|
713
|
+
// Lazy import: workflow-manifest dereferences CANONICAL_GJC_WORKFLOW_SKILLS at
|
|
714
|
+
// module load, and active-state -> state-writer -> workflow-manifest -> active-state
|
|
715
|
+
// is a load-time cycle. Importing at call time (after init) avoids the TDZ.
|
|
716
|
+
const { isKnownWorkflowState, isValidTransition } = await import("./workflow-manifest");
|
|
717
|
+
const skill = parsed.data.skill;
|
|
718
|
+
// Structural invariant (hard): a `current_phase` absent from the skill's manifest is
|
|
719
|
+
// never a legitimate internal write, matching the CLI/reconcile unknown-phase gate.
|
|
720
|
+
if (!isKnownWorkflowState(skill, toPhase)) {
|
|
721
|
+
throw new Error(
|
|
722
|
+
`Refusing to write unknown ${skill} phase "${toPhase}" to ${filePath}: not a known ${skill} manifest state (forced writes bypass via audit.forced)`,
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
// Transition invariant (#658, diagnostic-only safety net): resolve the prior phase
|
|
726
|
+
// (caller-supplied `audit.fromPhase`, else the active persisted envelope on disk) and
|
|
727
|
+
// flag edges the manifest does not define. Intentionally NON-blocking and audit-only
|
|
728
|
+
// — the CLI path already hard-fails invalid edges before reaching here, and legitimate
|
|
729
|
+
// internal repairs / ralplan short-mode stage skips move between valid states without a
|
|
730
|
+
// direct manifest edge. It records an `invalid_transition_detected` audit entry (no
|
|
731
|
+
// stderr) so such transitions are non-silent without breaking those flows.
|
|
732
|
+
const fromPhase = (options?.audit?.fromPhase ?? (await readPersistedPhase(filePath)))?.trim();
|
|
733
|
+
if (
|
|
734
|
+
fromPhase &&
|
|
735
|
+
fromPhase !== toPhase &&
|
|
736
|
+
isKnownWorkflowState(skill, fromPhase) &&
|
|
737
|
+
!isValidTransition(skill, fromPhase, toPhase)
|
|
738
|
+
) {
|
|
739
|
+
await recordInvalidWorkflowTransition({ filePath, skill, fromPhase, toPhase, options });
|
|
740
|
+
}
|
|
899
741
|
}
|
|
900
742
|
}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
743
|
+
await atomicWrite(filePath, jsonText(stamped));
|
|
744
|
+
await maybeAudit(filePath, options);
|
|
745
|
+
return filePath;
|
|
746
|
+
};
|
|
747
|
+
// Serialize with every other writer of the same state path. Without this, a
|
|
748
|
+
// revision-preserving envelope write (seed/spec persistence) can interleave
|
|
749
|
+
// inside a staged apply's check-then-write window and be silently overwritten
|
|
750
|
+
// (#3387 architect finding 1). Callers already inside `withWorkflowStateLock`
|
|
751
|
+
// for this path pass `lockHeld: true`.
|
|
752
|
+
return options?.lockHeld ? write() : lockResolvedWorkflowTarget(filePath, write, options?.lock);
|
|
905
753
|
}
|
|
906
754
|
|
|
907
755
|
export async function writeTextAtomic(targetPath: string, text: string, options?: StateWriterOptions): Promise<string> {
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
GjcTeamWorkerLifecycle,
|
|
13
13
|
GjcTeamWorktreeMode,
|
|
14
14
|
} from "./team-runtime";
|
|
15
|
+
import { createInitialGjcTeamWorkerMemoryGuardLedger, workerMemoryGuardLedgerPath } from "./team-worker-memory-guard";
|
|
15
16
|
|
|
16
17
|
/** Launch-specific option wiring kept separate from runtime dispatch. */
|
|
17
18
|
export function withTeamLaunchTransport(
|
|
@@ -34,6 +35,8 @@ export function buildWorkerCommand(
|
|
|
34
35
|
config: GjcTeamConfig,
|
|
35
36
|
worker: GjcTeamWorker,
|
|
36
37
|
platform: NodeJS.Platform = process.platform,
|
|
38
|
+
promptOverride?: string,
|
|
39
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
37
40
|
): string {
|
|
38
41
|
const quote = platform === "win32" ? powershellQuote : shellQuote;
|
|
39
42
|
const envAssignment = (key: string, value: string): string =>
|
|
@@ -41,7 +44,8 @@ export function buildWorkerCommand(
|
|
|
41
44
|
const workspace = worker.worktree_path
|
|
42
45
|
? `Worker worktree: ${worker.worktree_path}.`
|
|
43
46
|
: `Worker cwd: ${config.leader.cwd}.`;
|
|
44
|
-
const
|
|
47
|
+
const initialPrompt =
|
|
48
|
+
promptOverride ??
|
|
45
49
|
[
|
|
46
50
|
`You are ${worker.id} in gjc team ${config.team_name}.`,
|
|
47
51
|
`Team state root: ${config.state_root}.`,
|
|
@@ -50,8 +54,9 @@ export function buildWorkerCommand(
|
|
|
50
54
|
"Before implementation, claim your worker-owned task and treat the claimed task record as the source of truth. Do not implement directly from the broad team brief.",
|
|
51
55
|
`Before claiming work, send startup ACK: gjc team api worker-startup-ack --input '{"team_name":"${config.team_name}","worker_id":"${worker.id}","protocol_version":"1"}' --json.`,
|
|
52
56
|
"Use gjc team api update-worker-status to report task-local activity, then claim-task/transition-task-status with this worker id; keep heartbeat current during long work, record completion_evidence (summary plus a passed command or verified inspection/artifact item) before completed, and do not mutate leader-owned goal state.",
|
|
53
|
-
]
|
|
54
|
-
|
|
57
|
+
].join("\n");
|
|
58
|
+
const prompt =
|
|
59
|
+
initialPrompt
|
|
55
60
|
.replace(/[\uFEFF\u200B]/g, "")
|
|
56
61
|
.replace(/\r?\n+/g, " ")
|
|
57
62
|
.trim() || `Worker ${worker.id} ready.`;
|
|
@@ -66,6 +71,17 @@ export function buildWorkerCommand(
|
|
|
66
71
|
envAssignment("GJC_TEAM_DISPLAY_NAME", config.display_name),
|
|
67
72
|
envAssignment(SPAWN_PROVENANCE_ENV, config.leader.session_id.trim() || config.team_name),
|
|
68
73
|
...(worker.worktree_path ? [envAssignment("GJC_TEAM_WORKTREE_PATH", worker.worktree_path)] : []),
|
|
74
|
+
envAssignment(
|
|
75
|
+
"GJC_TEAM_WORKER_MEMORY_GUARD_PATH",
|
|
76
|
+
workerMemoryGuardLedgerPath(path.join(config.state_root, config.team_name), worker.id),
|
|
77
|
+
),
|
|
78
|
+
// The worker derives its heartbeat cadence from the same window the leader
|
|
79
|
+
// enforces. tmux panes do not inherit the launching shell's environment, so
|
|
80
|
+
// without this a tightened window would leave workers publishing on the
|
|
81
|
+
// default cadence and reported stale while they are working.
|
|
82
|
+
...(env.GJC_TEAM_HEARTBEAT_STALE_MS?.trim()
|
|
83
|
+
? [envAssignment("GJC_TEAM_HEARTBEAT_STALE_MS", env.GJC_TEAM_HEARTBEAT_STALE_MS.trim())]
|
|
84
|
+
: []),
|
|
69
85
|
];
|
|
70
86
|
const joined = envLines.join(" ");
|
|
71
87
|
const clearInheritedSession = config.gjc_session_id
|
|
@@ -146,6 +162,7 @@ async function initializeStateDirs(
|
|
|
146
162
|
runtime: GjcTeamLaunchRuntime,
|
|
147
163
|
dir: string,
|
|
148
164
|
workers: GjcTeamWorker[],
|
|
165
|
+
platform: NodeJS.Platform,
|
|
149
166
|
): Promise<void> {
|
|
150
167
|
await fs.mkdir(path.join(dir, "mailbox"), { recursive: true });
|
|
151
168
|
for (const worker of workers) {
|
|
@@ -167,6 +184,14 @@ async function initializeStateDirs(
|
|
|
167
184
|
turn_count: 0,
|
|
168
185
|
alive: true,
|
|
169
186
|
});
|
|
187
|
+
await runtime.writeJson(
|
|
188
|
+
workerMemoryGuardLedgerPath(dir, worker.id),
|
|
189
|
+
createInitialGjcTeamWorkerMemoryGuardLedger({
|
|
190
|
+
workerId: worker.id,
|
|
191
|
+
platform,
|
|
192
|
+
now: runtime.now(),
|
|
193
|
+
}),
|
|
194
|
+
);
|
|
170
195
|
}
|
|
171
196
|
await fs.mkdir(runtime.mailboxDirPath(dir, "leader-fixed"), { recursive: true });
|
|
172
197
|
await runtime.writeJson(runtime.mailboxPath(dir, "leader-fixed"), { messages: [] });
|
|
@@ -217,6 +242,18 @@ export async function startGjcTeamLaunch(
|
|
|
217
242
|
await runtime.rollbackCreatedWorktrees(workers);
|
|
218
243
|
throw error;
|
|
219
244
|
}
|
|
245
|
+
const tasksByOwner = new Map<string, string[]>();
|
|
246
|
+
for (const task of initialTasks) {
|
|
247
|
+
const owner = task.owner?.trim();
|
|
248
|
+
if (!owner) continue;
|
|
249
|
+
const assigned = tasksByOwner.get(owner) ?? [];
|
|
250
|
+
assigned.push(task.id);
|
|
251
|
+
tasksByOwner.set(owner, assigned);
|
|
252
|
+
}
|
|
253
|
+
const workersWithAssignments = workers.map(worker => ({
|
|
254
|
+
...worker,
|
|
255
|
+
assigned_tasks: tasksByOwner.get(worker.id) ?? worker.assigned_tasks,
|
|
256
|
+
}));
|
|
220
257
|
const config: GjcTeamConfig = {
|
|
221
258
|
team_name: teamName,
|
|
222
259
|
display_name: displayName,
|
|
@@ -242,11 +279,11 @@ export async function startGjcTeamLaunch(
|
|
|
242
279
|
},
|
|
243
280
|
leader_cwd: cwd,
|
|
244
281
|
team_state_root: stateRoot,
|
|
245
|
-
workers,
|
|
282
|
+
workers: workersWithAssignments,
|
|
246
283
|
created_at: createdAt,
|
|
247
284
|
updated_at: createdAt,
|
|
248
285
|
};
|
|
249
|
-
await initializeStateDirs(runtime, dir, config.workers);
|
|
286
|
+
await initializeStateDirs(runtime, dir, config.workers, platform);
|
|
250
287
|
await runtime.writeJson(path.join(dir, "config.json"), config);
|
|
251
288
|
await runtime.writeJson(path.join(dir, "manifest.v2.json"), {
|
|
252
289
|
version: 2,
|