@telora/factory 0.4.5
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/dist/audit.d.ts +69 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +376 -0
- package/dist/audit.js.map +1 -0
- package/dist/builder-completion.d.ts +35 -0
- package/dist/builder-completion.d.ts.map +1 -0
- package/dist/builder-completion.js +375 -0
- package/dist/builder-completion.js.map +1 -0
- package/dist/builder-spawner.d.ts +40 -0
- package/dist/builder-spawner.d.ts.map +1 -0
- package/dist/builder-spawner.js +493 -0
- package/dist/builder-spawner.js.map +1 -0
- package/dist/completion-gate.d.ts +52 -0
- package/dist/completion-gate.d.ts.map +1 -0
- package/dist/completion-gate.js +336 -0
- package/dist/completion-gate.js.map +1 -0
- package/dist/completion-report.d.ts +36 -0
- package/dist/completion-report.d.ts.map +1 -0
- package/dist/completion-report.js +348 -0
- package/dist/completion-report.js.map +1 -0
- package/dist/completion.d.ts +58 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +287 -0
- package/dist/completion.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +57 -0
- package/dist/config.js.map +1 -0
- package/dist/context-manager.d.ts +152 -0
- package/dist/context-manager.d.ts.map +1 -0
- package/dist/context-manager.js +421 -0
- package/dist/context-manager.js.map +1 -0
- package/dist/crash-detection.d.ts +70 -0
- package/dist/crash-detection.d.ts.map +1 -0
- package/dist/crash-detection.js +123 -0
- package/dist/crash-detection.js.map +1 -0
- package/dist/crash-recovery.d.ts +83 -0
- package/dist/crash-recovery.d.ts.map +1 -0
- package/dist/crash-recovery.js +522 -0
- package/dist/crash-recovery.js.map +1 -0
- package/dist/crash-resolution.d.ts +34 -0
- package/dist/crash-resolution.d.ts.map +1 -0
- package/dist/crash-resolution.js +382 -0
- package/dist/crash-resolution.js.map +1 -0
- package/dist/escalation.d.ts +150 -0
- package/dist/escalation.d.ts.map +1 -0
- package/dist/escalation.js +352 -0
- package/dist/escalation.js.map +1 -0
- package/dist/execution-target.d.ts +31 -0
- package/dist/execution-target.d.ts.map +1 -0
- package/dist/execution-target.js +71 -0
- package/dist/execution-target.js.map +1 -0
- package/dist/execution-unit-init.d.ts +28 -0
- package/dist/execution-unit-init.d.ts.map +1 -0
- package/dist/execution-unit-init.js +115 -0
- package/dist/execution-unit-init.js.map +1 -0
- package/dist/execution.d.ts +17 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +20 -0
- package/dist/execution.js.map +1 -0
- package/dist/factory-engine.d.ts +100 -0
- package/dist/factory-engine.d.ts.map +1 -0
- package/dist/factory-engine.js +243 -0
- package/dist/factory-engine.js.map +1 -0
- package/dist/gap-detection.d.ts +43 -0
- package/dist/gap-detection.d.ts.map +1 -0
- package/dist/gap-detection.js +149 -0
- package/dist/gap-detection.js.map +1 -0
- package/dist/gate-context.d.ts +23 -0
- package/dist/gate-context.d.ts.map +1 -0
- package/dist/gate-context.js +63 -0
- package/dist/gate-context.js.map +1 -0
- package/dist/gate-engine.d.ts +55 -0
- package/dist/gate-engine.d.ts.map +1 -0
- package/dist/gate-engine.js +191 -0
- package/dist/gate-engine.js.map +1 -0
- package/dist/gates/adversarial.d.ts +59 -0
- package/dist/gates/adversarial.d.ts.map +1 -0
- package/dist/gates/adversarial.js +426 -0
- package/dist/gates/adversarial.js.map +1 -0
- package/dist/gates/adversary-spawner.d.ts +35 -0
- package/dist/gates/adversary-spawner.d.ts.map +1 -0
- package/dist/gates/adversary-spawner.js +286 -0
- package/dist/gates/adversary-spawner.js.map +1 -0
- package/dist/gates/adversary-test-dir.d.ts +41 -0
- package/dist/gates/adversary-test-dir.d.ts.map +1 -0
- package/dist/gates/adversary-test-dir.js +150 -0
- package/dist/gates/adversary-test-dir.js.map +1 -0
- package/dist/gates/behavioral-parser.d.ts +32 -0
- package/dist/gates/behavioral-parser.d.ts.map +1 -0
- package/dist/gates/behavioral-parser.js +190 -0
- package/dist/gates/behavioral-parser.js.map +1 -0
- package/dist/gates/behavioral-runner.d.ts +36 -0
- package/dist/gates/behavioral-runner.d.ts.map +1 -0
- package/dist/gates/behavioral-runner.js +306 -0
- package/dist/gates/behavioral-runner.js.map +1 -0
- package/dist/gates/behavioral.d.ts +37 -0
- package/dist/gates/behavioral.d.ts.map +1 -0
- package/dist/gates/behavioral.js +485 -0
- package/dist/gates/behavioral.js.map +1 -0
- package/dist/gates/deterministic.d.ts +24 -0
- package/dist/gates/deterministic.d.ts.map +1 -0
- package/dist/gates/deterministic.js +186 -0
- package/dist/gates/deterministic.js.map +1 -0
- package/dist/git-factory.d.ts +59 -0
- package/dist/git-factory.d.ts.map +1 -0
- package/dist/git-factory.js +102 -0
- package/dist/git-factory.js.map +1 -0
- package/dist/guard-evaluation.d.ts +48 -0
- package/dist/guard-evaluation.d.ts.map +1 -0
- package/dist/guard-evaluation.js +416 -0
- package/dist/guard-evaluation.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/instance-completion.d.ts +34 -0
- package/dist/instance-completion.d.ts.map +1 -0
- package/dist/instance-completion.js +366 -0
- package/dist/instance-completion.js.map +1 -0
- package/dist/instance-lifecycle.d.ts +15 -0
- package/dist/instance-lifecycle.d.ts.map +1 -0
- package/dist/instance-lifecycle.js +18 -0
- package/dist/instance-lifecycle.js.map +1 -0
- package/dist/instance-phase-dispatch.d.ts +75 -0
- package/dist/instance-phase-dispatch.d.ts.map +1 -0
- package/dist/instance-phase-dispatch.js +674 -0
- package/dist/instance-phase-dispatch.js.map +1 -0
- package/dist/instance-poll-loop.d.ts +43 -0
- package/dist/instance-poll-loop.d.ts.map +1 -0
- package/dist/instance-poll-loop.js +360 -0
- package/dist/instance-poll-loop.js.map +1 -0
- package/dist/instance-state-machine.d.ts +52 -0
- package/dist/instance-state-machine.d.ts.map +1 -0
- package/dist/instance-state-machine.js +235 -0
- package/dist/instance-state-machine.js.map +1 -0
- package/dist/log-manager.d.ts +28 -0
- package/dist/log-manager.d.ts.map +1 -0
- package/dist/log-manager.js +71 -0
- package/dist/log-manager.js.map +1 -0
- package/dist/pipeline-evaluator.d.ts +61 -0
- package/dist/pipeline-evaluator.d.ts.map +1 -0
- package/dist/pipeline-evaluator.js +107 -0
- package/dist/pipeline-evaluator.js.map +1 -0
- package/dist/pipeline-metrics.d.ts +52 -0
- package/dist/pipeline-metrics.d.ts.map +1 -0
- package/dist/pipeline-metrics.js +40 -0
- package/dist/pipeline-metrics.js.map +1 -0
- package/dist/pipeline-traversal.d.ts +43 -0
- package/dist/pipeline-traversal.d.ts.map +1 -0
- package/dist/pipeline-traversal.js +68 -0
- package/dist/pipeline-traversal.js.map +1 -0
- package/dist/plan-parser.d.ts +76 -0
- package/dist/plan-parser.d.ts.map +1 -0
- package/dist/plan-parser.js +223 -0
- package/dist/plan-parser.js.map +1 -0
- package/dist/planning-phase.d.ts +52 -0
- package/dist/planning-phase.d.ts.map +1 -0
- package/dist/planning-phase.js +444 -0
- package/dist/planning-phase.js.map +1 -0
- package/dist/planning-prompt.d.ts +64 -0
- package/dist/planning-prompt.d.ts.map +1 -0
- package/dist/planning-prompt.js +251 -0
- package/dist/planning-prompt.js.map +1 -0
- package/dist/planning.d.ts +16 -0
- package/dist/planning.d.ts.map +1 -0
- package/dist/planning.js +17 -0
- package/dist/planning.js.map +1 -0
- package/dist/process-runner.d.ts +41 -0
- package/dist/process-runner.d.ts.map +1 -0
- package/dist/process-runner.js +81 -0
- package/dist/process-runner.js.map +1 -0
- package/dist/product-config.d.ts +34 -0
- package/dist/product-config.d.ts.map +1 -0
- package/dist/product-config.js +43 -0
- package/dist/product-config.js.map +1 -0
- package/dist/queries/cycle-evaluations.d.ts +23 -0
- package/dist/queries/cycle-evaluations.d.ts.map +1 -0
- package/dist/queries/cycle-evaluations.js +37 -0
- package/dist/queries/cycle-evaluations.js.map +1 -0
- package/dist/queries/escalations.d.ts +30 -0
- package/dist/queries/escalations.d.ts.map +1 -0
- package/dist/queries/escalations.js +42 -0
- package/dist/queries/escalations.js.map +1 -0
- package/dist/queries/execution-units.d.ts +76 -0
- package/dist/queries/execution-units.d.ts.map +1 -0
- package/dist/queries/execution-units.js +109 -0
- package/dist/queries/execution-units.js.map +1 -0
- package/dist/queries/gate-results.d.ts +32 -0
- package/dist/queries/gate-results.d.ts.map +1 -0
- package/dist/queries/gate-results.js +44 -0
- package/dist/queries/gate-results.js.map +1 -0
- package/dist/queries/instances.d.ts +51 -0
- package/dist/queries/instances.d.ts.map +1 -0
- package/dist/queries/instances.js +77 -0
- package/dist/queries/instances.js.map +1 -0
- package/dist/queries/sessions.d.ts +50 -0
- package/dist/queries/sessions.d.ts.map +1 -0
- package/dist/queries/sessions.js +81 -0
- package/dist/queries/sessions.js.map +1 -0
- package/dist/queries/shared.d.ts +38 -0
- package/dist/queries/shared.d.ts.map +1 -0
- package/dist/queries/shared.js +119 -0
- package/dist/queries/shared.js.map +1 -0
- package/dist/queries/specs.d.ts +12 -0
- package/dist/queries/specs.d.ts.map +1 -0
- package/dist/queries/specs.js +21 -0
- package/dist/queries/specs.js.map +1 -0
- package/dist/queries/strategies.d.ts +14 -0
- package/dist/queries/strategies.d.ts.map +1 -0
- package/dist/queries/strategies.js +18 -0
- package/dist/queries/strategies.js.map +1 -0
- package/dist/queries/work-units.d.ts +42 -0
- package/dist/queries/work-units.d.ts.map +1 -0
- package/dist/queries/work-units.js +57 -0
- package/dist/queries/work-units.js.map +1 -0
- package/dist/queries/workflows.d.ts +29 -0
- package/dist/queries/workflows.d.ts.map +1 -0
- package/dist/queries/workflows.js +103 -0
- package/dist/queries/workflows.js.map +1 -0
- package/dist/remediation-units.d.ts +40 -0
- package/dist/remediation-units.d.ts.map +1 -0
- package/dist/remediation-units.js +263 -0
- package/dist/remediation-units.js.map +1 -0
- package/dist/replanning.d.ts +72 -0
- package/dist/replanning.d.ts.map +1 -0
- package/dist/replanning.js +403 -0
- package/dist/replanning.js.map +1 -0
- package/dist/resource-limits.d.ts +62 -0
- package/dist/resource-limits.d.ts.map +1 -0
- package/dist/resource-limits.js +322 -0
- package/dist/resource-limits.js.map +1 -0
- package/dist/scheduler.d.ts +98 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +203 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/session-adapter.d.ts +89 -0
- package/dist/session-adapter.d.ts.map +1 -0
- package/dist/session-adapter.js +108 -0
- package/dist/session-adapter.js.map +1 -0
- package/dist/sop-generator.d.ts +29 -0
- package/dist/sop-generator.d.ts.map +1 -0
- package/dist/sop-generator.js +235 -0
- package/dist/sop-generator.js.map +1 -0
- package/dist/spec-profiles.d.ts +41 -0
- package/dist/spec-profiles.d.ts.map +1 -0
- package/dist/spec-profiles.js +131 -0
- package/dist/spec-profiles.js.map +1 -0
- package/dist/strategy-design-graph.d.ts +23 -0
- package/dist/strategy-design-graph.d.ts.map +1 -0
- package/dist/strategy-design-graph.js +205 -0
- package/dist/strategy-design-graph.js.map +1 -0
- package/dist/strategy-design-prompt.d.ts +28 -0
- package/dist/strategy-design-prompt.d.ts.map +1 -0
- package/dist/strategy-design-prompt.js +108 -0
- package/dist/strategy-design-prompt.js.map +1 -0
- package/dist/strategy-design-schema.d.ts +767 -0
- package/dist/strategy-design-schema.d.ts.map +1 -0
- package/dist/strategy-design-schema.js +126 -0
- package/dist/strategy-design-schema.js.map +1 -0
- package/dist/strategy-design.d.ts +69 -0
- package/dist/strategy-design.d.ts.map +1 -0
- package/dist/strategy-design.js +411 -0
- package/dist/strategy-design.js.map +1 -0
- package/dist/strategy-gating.d.ts +31 -0
- package/dist/strategy-gating.d.ts.map +1 -0
- package/dist/strategy-gating.js +276 -0
- package/dist/strategy-gating.js.map +1 -0
- package/dist/team-prompt-builder.d.ts +47 -0
- package/dist/team-prompt-builder.d.ts.map +1 -0
- package/dist/team-prompt-builder.js +362 -0
- package/dist/team-prompt-builder.js.map +1 -0
- package/dist/trace-engine.d.ts +40 -0
- package/dist/trace-engine.d.ts.map +1 -0
- package/dist/trace-engine.js +344 -0
- package/dist/trace-engine.js.map +1 -0
- package/dist/types.d.ts +612 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/unit-session-lifecycle.d.ts +78 -0
- package/dist/unit-session-lifecycle.d.ts.map +1 -0
- package/dist/unit-session-lifecycle.js +141 -0
- package/dist/unit-session-lifecycle.js.map +1 -0
- package/dist/unit-session.d.ts +30 -0
- package/dist/unit-session.d.ts.map +1 -0
- package/dist/unit-session.js +370 -0
- package/dist/unit-session.js.map +1 -0
- package/dist/watchdogs.d.ts +33 -0
- package/dist/watchdogs.d.ts.map +1 -0
- package/dist/watchdogs.js +170 -0
- package/dist/watchdogs.js.map +1 -0
- package/dist/work-unit-scheduler.d.ts +34 -0
- package/dist/work-unit-scheduler.d.ts.map +1 -0
- package/dist/work-unit-scheduler.js +91 -0
- package/dist/work-unit-scheduler.js.map +1 -0
- package/dist/workflow-transition.d.ts +90 -0
- package/dist/workflow-transition.d.ts.map +1 -0
- package/dist/workflow-transition.js +340 -0
- package/dist/workflow-transition.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory context management module.
|
|
3
|
+
*
|
|
4
|
+
* Builds message payloads for managing AI builder context during the
|
|
5
|
+
* build-gate execution cycle. Supports three operations:
|
|
6
|
+
*
|
|
7
|
+
* - compact: Instruct a running builder to summarize and compact its context
|
|
8
|
+
* - load_files: Instruct a running builder to read specific files into context
|
|
9
|
+
* - reset: Build a fresh prompt for re-spawning a builder with clean context
|
|
10
|
+
*
|
|
11
|
+
* Key design principle: this module produces PAYLOADS only. It never touches
|
|
12
|
+
* ChildProcess, streams, or any process management. The execution module
|
|
13
|
+
* (execution.ts) is responsible for sending payloads to builder processes.
|
|
14
|
+
*/
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Constants
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/** Log prefix for all context management messages. */
|
|
19
|
+
const LOG_PREFIX = '[context-mgr]';
|
|
20
|
+
/**
|
|
21
|
+
* Default number of iterations before triggering a context reset.
|
|
22
|
+
* Can be overridden by blueprint configuration.
|
|
23
|
+
*/
|
|
24
|
+
export const DEFAULT_CONTEXT_RESET_AFTER_ITERATIONS = 3;
|
|
25
|
+
/** Maximum number of recent gate results to include in a reset payload. */
|
|
26
|
+
const MAX_RECENT_GATE_RESULTS = 10;
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Operation payload builders
|
|
29
|
+
// ============================================================================
|
|
30
|
+
/**
|
|
31
|
+
* Build a compact operation payload.
|
|
32
|
+
*
|
|
33
|
+
* Instructs a running builder to summarize its current context and continue
|
|
34
|
+
* working from the summary, dropping conversation history before the summary.
|
|
35
|
+
*
|
|
36
|
+
* @returns The message string to send to the builder's stdin via stream-json.
|
|
37
|
+
*/
|
|
38
|
+
export function buildCompactPayload() {
|
|
39
|
+
return ('[context-management] Compact your context. Summarize the key state of your ' +
|
|
40
|
+
'current work (what you\'ve done, what\'s left, recent gate feedback) into a ' +
|
|
41
|
+
'concise summary, then continue working from that summary. Drop conversation ' +
|
|
42
|
+
'history before this point.');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Build a load_files operation payload.
|
|
46
|
+
*
|
|
47
|
+
* Instructs a running builder to read specific files into its context.
|
|
48
|
+
* The file list is formatted one-per-line for readability.
|
|
49
|
+
*
|
|
50
|
+
* @param files Array of file paths to load.
|
|
51
|
+
* @returns The message string to send to the builder's stdin via stream-json.
|
|
52
|
+
*/
|
|
53
|
+
export function buildLoadFilesPayload(files) {
|
|
54
|
+
if (files.length === 0) {
|
|
55
|
+
console.warn(`${LOG_PREFIX} load_files called with empty file list`);
|
|
56
|
+
return '[context-management] No files specified to load.';
|
|
57
|
+
}
|
|
58
|
+
const fileList = files.map((f) => ` - ${f}`).join('\n');
|
|
59
|
+
return ('[context-management] Load the following files into your context by reading them:\n' +
|
|
60
|
+
fileList);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build a reset payload containing the full context for re-spawning a builder.
|
|
64
|
+
*
|
|
65
|
+
* Used when a work unit has iterated multiple times and needs a fresh context
|
|
66
|
+
* instead of accumulating stale conversation history. Includes:
|
|
67
|
+
* - The work unit spec and description
|
|
68
|
+
* - Instance specification
|
|
69
|
+
* - Operational notes from the blueprint
|
|
70
|
+
* - Summary of previous iteration results (gate feedback)
|
|
71
|
+
*
|
|
72
|
+
* @param workUnit The work unit being reset.
|
|
73
|
+
* @param state The parent factory instance state.
|
|
74
|
+
* @param gateOutput The gate failure output from the most recent iteration (if any).
|
|
75
|
+
* @returns A structured payload object with the fresh prompt.
|
|
76
|
+
*/
|
|
77
|
+
export function buildResetPayload(workUnit, state, gateOutput) {
|
|
78
|
+
return {
|
|
79
|
+
freshPrompt: buildFreshContextPrompt(workUnit, state, gateOutput),
|
|
80
|
+
reason: `Context reset after ${workUnit.iterationCount} iteration(s)`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build a context payload for a given work unit from the current factory
|
|
85
|
+
* instance state.
|
|
86
|
+
*
|
|
87
|
+
* Extracts the work unit's title, description, strategy scope, interface
|
|
88
|
+
* contracts, recent gate results, relevant files, and operational notes
|
|
89
|
+
* into a self-contained payload that can be used to build a fresh prompt
|
|
90
|
+
* via the ContextManager interface.
|
|
91
|
+
*/
|
|
92
|
+
export function buildContextPayload(state, workUnitId) {
|
|
93
|
+
// Find the active builder for this work unit to get iteration context
|
|
94
|
+
const builder = state.activeBuilderSessions.get(workUnitId);
|
|
95
|
+
// Default work unit metadata
|
|
96
|
+
let workUnitTitle = `Work Unit ${workUnitId.slice(0, 8)}`;
|
|
97
|
+
const workUnitDescription = '';
|
|
98
|
+
if (builder) {
|
|
99
|
+
workUnitTitle = `Work Unit (session: ${builder.sessionId.slice(0, 8)}, iteration: ${builder.iterationCount})`;
|
|
100
|
+
}
|
|
101
|
+
// Extract strategy scope from specification
|
|
102
|
+
const strategyScope = state.specification ?? 'No specification available';
|
|
103
|
+
// Build simplified interface contracts from blueprint context
|
|
104
|
+
const produces = [];
|
|
105
|
+
const consumes = [];
|
|
106
|
+
// Extract relevant files from the worktree path
|
|
107
|
+
const relevantFiles = [];
|
|
108
|
+
if (state.worktreePath) {
|
|
109
|
+
relevantFiles.push(state.worktreePath);
|
|
110
|
+
}
|
|
111
|
+
// Include operational notes from the blueprint
|
|
112
|
+
const operationalNotes = state.blueprint.operationalNotes;
|
|
113
|
+
// Build recent gate results (empty array -- actual results are fetched
|
|
114
|
+
// asynchronously by the caller via getGateResults query)
|
|
115
|
+
const recentGateResults = [];
|
|
116
|
+
return {
|
|
117
|
+
workUnitTitle,
|
|
118
|
+
workUnitDescription,
|
|
119
|
+
strategyScope,
|
|
120
|
+
interfaceContracts: { produces, consumes },
|
|
121
|
+
recentGateResults,
|
|
122
|
+
relevantFiles,
|
|
123
|
+
operationalNotes,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Build a context payload with full work unit data.
|
|
128
|
+
*
|
|
129
|
+
* This is the preferred overload when the caller has the work unit metadata
|
|
130
|
+
* and gate results available (which avoids async DB lookups in the pure
|
|
131
|
+
* payload builder).
|
|
132
|
+
*/
|
|
133
|
+
export function buildContextPayloadWithData(state, workUnitTitle, workUnitDescription, strategyScope, interfaceContracts, recentGateResults, relevantFiles) {
|
|
134
|
+
return {
|
|
135
|
+
workUnitTitle,
|
|
136
|
+
workUnitDescription,
|
|
137
|
+
strategyScope,
|
|
138
|
+
interfaceContracts,
|
|
139
|
+
recentGateResults: recentGateResults.slice(-MAX_RECENT_GATE_RESULTS),
|
|
140
|
+
relevantFiles,
|
|
141
|
+
operationalNotes: state.blueprint.operationalNotes,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Fresh context prompt builder
|
|
146
|
+
// ============================================================================
|
|
147
|
+
/**
|
|
148
|
+
* Build a fresh prompt for a work unit that needs a context reset.
|
|
149
|
+
*
|
|
150
|
+
* This replaces the standard buildWorkUnitPrompt when iterationCount has
|
|
151
|
+
* exceeded the context reset threshold. It provides all necessary context
|
|
152
|
+
* in a single prompt without relying on prior conversation history.
|
|
153
|
+
*
|
|
154
|
+
* @param workUnit The work unit to build the prompt for.
|
|
155
|
+
* @param state The parent factory instance state.
|
|
156
|
+
* @param gateOutput The gate failure output from the most recent iteration (if any).
|
|
157
|
+
* @returns The full prompt string for a fresh builder session.
|
|
158
|
+
*/
|
|
159
|
+
export function buildFreshContextPrompt(workUnit, state, gateOutput) {
|
|
160
|
+
const lines = [];
|
|
161
|
+
lines.push('You are a builder agent working on a factory work unit.');
|
|
162
|
+
lines.push('');
|
|
163
|
+
lines.push('## Context Reset');
|
|
164
|
+
lines.push(`This is a FRESH context session. Previous iterations (${workUnit.iterationCount}) ` +
|
|
165
|
+
'did not pass the quality gates. Your conversation history has been reset to ' +
|
|
166
|
+
'give you a clean start. All relevant context is included below.');
|
|
167
|
+
lines.push('');
|
|
168
|
+
lines.push('## Work Unit');
|
|
169
|
+
lines.push(`**Title:** ${workUnit.title}`);
|
|
170
|
+
if (workUnit.description) {
|
|
171
|
+
lines.push(`**Description:** ${workUnit.description}`);
|
|
172
|
+
}
|
|
173
|
+
lines.push(`**Iteration:** ${workUnit.iterationCount + 1} (fresh context)`);
|
|
174
|
+
lines.push('');
|
|
175
|
+
if (state.specification) {
|
|
176
|
+
lines.push('## Instance Specification');
|
|
177
|
+
lines.push(state.specification);
|
|
178
|
+
lines.push('');
|
|
179
|
+
}
|
|
180
|
+
if (state.blueprint.operationalNotes) {
|
|
181
|
+
lines.push('## Operational Notes');
|
|
182
|
+
lines.push(state.blueprint.operationalNotes);
|
|
183
|
+
lines.push('');
|
|
184
|
+
}
|
|
185
|
+
lines.push('## Instructions');
|
|
186
|
+
lines.push('1. Implement the work described above.');
|
|
187
|
+
lines.push('2. Follow the project\'s coding standards (see CLAUDE.md if present).');
|
|
188
|
+
lines.push('3. Ensure the code compiles and passes tests.');
|
|
189
|
+
lines.push('4. Commit your changes when done.');
|
|
190
|
+
lines.push('');
|
|
191
|
+
if (gateOutput) {
|
|
192
|
+
lines.push('## Previous Gate Feedback');
|
|
193
|
+
lines.push('The following feedback is from the most recent gate evaluation. ' +
|
|
194
|
+
'Address these issues in your implementation:');
|
|
195
|
+
lines.push('');
|
|
196
|
+
// Truncate very long gate output to keep the prompt manageable
|
|
197
|
+
const maxGateOutputLength = 8000;
|
|
198
|
+
if (gateOutput.length > maxGateOutputLength) {
|
|
199
|
+
lines.push(gateOutput.slice(0, maxGateOutputLength));
|
|
200
|
+
lines.push('... (gate output truncated)');
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
lines.push(gateOutput);
|
|
204
|
+
}
|
|
205
|
+
lines.push('');
|
|
206
|
+
}
|
|
207
|
+
lines.push('## Important');
|
|
208
|
+
lines.push('This is a retry with fresh context. Review the existing code in the worktree ' +
|
|
209
|
+
'carefully before making changes -- previous iterations may have made partial progress. ' +
|
|
210
|
+
'Focus on the gate feedback above to understand what still needs to be fixed.');
|
|
211
|
+
return lines.join('\n');
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Build a fresh context prompt from a ContextPayload.
|
|
215
|
+
*
|
|
216
|
+
* Used by the FactoryContextManager class when handling reset operations
|
|
217
|
+
* via the ContextManager interface.
|
|
218
|
+
*/
|
|
219
|
+
export function buildFreshContextPromptFromPayload(payload, blueprint, operationalNotes) {
|
|
220
|
+
const sections = [];
|
|
221
|
+
// Role and orientation
|
|
222
|
+
sections.push('# Builder Session Context', '', 'You are a builder in a software factory. Your context has been reset to give you', 'a fresh start. This prompt contains everything you need to continue your work.', '');
|
|
223
|
+
// Work unit scope
|
|
224
|
+
sections.push('## Work Unit', `**Title:** ${payload.workUnitTitle}`);
|
|
225
|
+
if (payload.workUnitDescription) {
|
|
226
|
+
sections.push(`**Description:** ${payload.workUnitDescription}`);
|
|
227
|
+
}
|
|
228
|
+
sections.push('');
|
|
229
|
+
// Strategy context
|
|
230
|
+
sections.push('## Strategy Scope', '', payload.strategyScope, '');
|
|
231
|
+
// Interface contracts
|
|
232
|
+
if (payload.interfaceContracts.produces.length > 0 || payload.interfaceContracts.consumes.length > 0) {
|
|
233
|
+
sections.push('### Interface Contracts', '');
|
|
234
|
+
if (payload.interfaceContracts.produces.length > 0) {
|
|
235
|
+
sections.push('**This strategy produces:**');
|
|
236
|
+
for (const item of payload.interfaceContracts.produces) {
|
|
237
|
+
sections.push(`- **${item.name}**: ${item.description}`);
|
|
238
|
+
}
|
|
239
|
+
sections.push('');
|
|
240
|
+
}
|
|
241
|
+
if (payload.interfaceContracts.consumes.length > 0) {
|
|
242
|
+
sections.push('**This strategy consumes (from dependencies):**');
|
|
243
|
+
for (const item of payload.interfaceContracts.consumes) {
|
|
244
|
+
sections.push(`- **${item.name}**: ${item.description}`);
|
|
245
|
+
}
|
|
246
|
+
sections.push('');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Iteration history from gate results
|
|
250
|
+
if (payload.recentGateResults.length > 0) {
|
|
251
|
+
sections.push('## Previous Gate Results', '');
|
|
252
|
+
sections.push('The following gate results are from previous iterations of this work unit.', 'Use them to understand what has been tried and what needs to be fixed.', '');
|
|
253
|
+
for (const result of payload.recentGateResults) {
|
|
254
|
+
const status = result.passed ? 'PASSED' : 'FAILED';
|
|
255
|
+
sections.push(`### [${status}] ${result.checkName}`);
|
|
256
|
+
if (!result.passed && result.output) {
|
|
257
|
+
const output = result.output.length > 3000
|
|
258
|
+
? '...[truncated]...\n' + result.output.slice(-3000)
|
|
259
|
+
: result.output;
|
|
260
|
+
sections.push('```');
|
|
261
|
+
sections.push(output);
|
|
262
|
+
sections.push('```');
|
|
263
|
+
}
|
|
264
|
+
sections.push('');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Files to load
|
|
268
|
+
if (payload.relevantFiles.length > 0) {
|
|
269
|
+
sections.push('## Files to Load', '', 'Start by reading these files to understand the current state of the codebase:', '');
|
|
270
|
+
for (const file of payload.relevantFiles) {
|
|
271
|
+
sections.push(`- \`${file}\``);
|
|
272
|
+
}
|
|
273
|
+
sections.push('');
|
|
274
|
+
}
|
|
275
|
+
// Operational notes
|
|
276
|
+
const notes = operationalNotes ?? payload.operationalNotes ?? blueprint.operationalNotes;
|
|
277
|
+
if (notes) {
|
|
278
|
+
sections.push('## Operational Notes', '', notes, '');
|
|
279
|
+
}
|
|
280
|
+
// Scope boundary
|
|
281
|
+
sections.push('## Scope Boundary', '', 'IMPORTANT: Stay within the scope of your assigned work unit.', 'Do NOT modify code outside of your scope boundary.', 'Do NOT attempt to implement features assigned to other work units or strategies.', 'Focus exclusively on completing the work described above.', '', '## Instructions', '', '1. Read the files listed above to understand the current state.', '2. Implement the work described in your work unit scope.', '3. Follow the project\'s coding standards (see CLAUDE.md if present).', '4. Ensure the code compiles and passes tests.', '5. Commit your changes when done.');
|
|
282
|
+
return sections.join('\n');
|
|
283
|
+
}
|
|
284
|
+
// ============================================================================
|
|
285
|
+
// Context directive executor (payload routing)
|
|
286
|
+
// ============================================================================
|
|
287
|
+
/**
|
|
288
|
+
* Execute a context management directive by building the appropriate payload.
|
|
289
|
+
*
|
|
290
|
+
* This is the entry point called by the trigger execution system
|
|
291
|
+
* (workflow-transition.ts) when a manage_context trigger fires. It routes
|
|
292
|
+
* the directive to the correct payload builder.
|
|
293
|
+
*
|
|
294
|
+
* @param directive The context directive from the workflow trigger.
|
|
295
|
+
* @returns The message payload to send to the builder, or null if no action needed.
|
|
296
|
+
*/
|
|
297
|
+
export function executeDirective(directive) {
|
|
298
|
+
switch (directive.type) {
|
|
299
|
+
case 'compact':
|
|
300
|
+
console.log(`${LOG_PREFIX} Building compact payload`);
|
|
301
|
+
return buildCompactPayload();
|
|
302
|
+
case 'load_files':
|
|
303
|
+
if (!directive.files || directive.files.length === 0) {
|
|
304
|
+
console.warn(`${LOG_PREFIX} load_files directive with no files -- skipping`);
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
console.log(`${LOG_PREFIX} Building load_files payload (${directive.files.length} file(s))`);
|
|
308
|
+
return buildLoadFilesPayload(directive.files);
|
|
309
|
+
case 'reset':
|
|
310
|
+
// Reset requires work unit and state context that the directive doesn't carry.
|
|
311
|
+
// The reset flow is handled separately in the execution module via
|
|
312
|
+
// buildResetPayload() / buildFreshContextPrompt().
|
|
313
|
+
console.log(`${LOG_PREFIX} Reset directive received -- handled by execution module`);
|
|
314
|
+
return null;
|
|
315
|
+
default: {
|
|
316
|
+
// Exhaustive check
|
|
317
|
+
const _exhaustive = directive.type;
|
|
318
|
+
console.warn(`${LOG_PREFIX} Unknown directive type: ${String(_exhaustive)}`);
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// ============================================================================
|
|
324
|
+
// Context Manager implementation
|
|
325
|
+
// ============================================================================
|
|
326
|
+
/**
|
|
327
|
+
* Factory context manager implementation.
|
|
328
|
+
*
|
|
329
|
+
* Translates context operations into message payloads. The actual process
|
|
330
|
+
* I/O (sending messages, restarting processes) is handled by the caller
|
|
331
|
+
* (execution.ts).
|
|
332
|
+
*/
|
|
333
|
+
export class FactoryContextManager {
|
|
334
|
+
blueprint;
|
|
335
|
+
constructor(blueprint) {
|
|
336
|
+
this.blueprint = blueprint;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Execute a context management operation.
|
|
340
|
+
*
|
|
341
|
+
* Returns a ContextOperationResult containing the message text to send
|
|
342
|
+
* to the builder session. The caller is responsible for actually
|
|
343
|
+
* delivering the message (via stdin for compact/load_files, or by
|
|
344
|
+
* restarting the process for reset).
|
|
345
|
+
*/
|
|
346
|
+
async executeOperation(sessionId, operation) {
|
|
347
|
+
switch (operation.type) {
|
|
348
|
+
case 'compact':
|
|
349
|
+
return this.handleCompact(sessionId);
|
|
350
|
+
case 'reset':
|
|
351
|
+
return this.handleReset(sessionId, operation.contextPayload);
|
|
352
|
+
case 'load_files':
|
|
353
|
+
return this.handleLoadFiles(sessionId, operation.files);
|
|
354
|
+
default: {
|
|
355
|
+
const _exhaustive = operation;
|
|
356
|
+
return {
|
|
357
|
+
success: false,
|
|
358
|
+
operation: _exhaustive.type,
|
|
359
|
+
error: `Unknown context operation type`,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Build a context payload from the current factory instance state for
|
|
366
|
+
* a given work unit.
|
|
367
|
+
*/
|
|
368
|
+
buildResetPayload(state, workUnitId) {
|
|
369
|
+
return buildContextPayload(state, workUnitId);
|
|
370
|
+
}
|
|
371
|
+
// --------------------------------------------------------------------------
|
|
372
|
+
// Operation handlers
|
|
373
|
+
// --------------------------------------------------------------------------
|
|
374
|
+
handleCompact(sessionId) {
|
|
375
|
+
console.log(`${LOG_PREFIX} Compact operation for session ${sessionId}`);
|
|
376
|
+
return {
|
|
377
|
+
success: true,
|
|
378
|
+
operation: 'compact',
|
|
379
|
+
message: buildCompactPayload(),
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
handleReset(sessionId, payload) {
|
|
383
|
+
console.log(`${LOG_PREFIX} Reset operation for session ${sessionId}`);
|
|
384
|
+
const message = buildFreshContextPromptFromPayload(payload, this.blueprint, payload.operationalNotes);
|
|
385
|
+
return {
|
|
386
|
+
success: true,
|
|
387
|
+
operation: 'reset',
|
|
388
|
+
message,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
handleLoadFiles(sessionId, files) {
|
|
392
|
+
if (files.length === 0) {
|
|
393
|
+
return {
|
|
394
|
+
success: false,
|
|
395
|
+
operation: 'load_files',
|
|
396
|
+
error: 'No files specified for load_files operation',
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
console.log(`${LOG_PREFIX} Load files operation for session ${sessionId}: ${files.length} file(s)`);
|
|
400
|
+
return {
|
|
401
|
+
success: true,
|
|
402
|
+
operation: 'load_files',
|
|
403
|
+
message: buildLoadFilesPayload(files),
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// ============================================================================
|
|
408
|
+
// Threshold helper
|
|
409
|
+
// ============================================================================
|
|
410
|
+
/**
|
|
411
|
+
* Determine whether a work unit needs a context reset based on its
|
|
412
|
+
* iteration count and the configured threshold.
|
|
413
|
+
*
|
|
414
|
+
* @param iterationCount The current iteration count of the work unit.
|
|
415
|
+
* @param threshold The configured context reset threshold (default: 3).
|
|
416
|
+
* @returns True if the work unit should get a fresh context on next spawn.
|
|
417
|
+
*/
|
|
418
|
+
export function needsContextReset(iterationCount, threshold = DEFAULT_CONTEXT_RESET_AFTER_ITERATIONS) {
|
|
419
|
+
return iterationCount > 0 && iterationCount >= threshold;
|
|
420
|
+
}
|
|
421
|
+
//# sourceMappingURL=context-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../src/context-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orphan detection for factory crash recovery.
|
|
3
|
+
*
|
|
4
|
+
* Scans for orphaned worktrees, stale sessions, and incomplete instances
|
|
5
|
+
* that were left behind after an unclean orchestrator shutdown.
|
|
6
|
+
*
|
|
7
|
+
* Provides:
|
|
8
|
+
* - Git worktree list parsing
|
|
9
|
+
* - Factory worktree directory scanning
|
|
10
|
+
* - Types shared between detection and resolution modules
|
|
11
|
+
*/
|
|
12
|
+
import type { FactoryConfig } from './types.js';
|
|
13
|
+
export interface OrphanedWorktree {
|
|
14
|
+
/** Absolute path to the worktree directory on disk. */
|
|
15
|
+
worktreePath: string;
|
|
16
|
+
/** Git branch name derived from the worktree entry (if available). */
|
|
17
|
+
branchName: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface RecoveryAction {
|
|
20
|
+
type: 'worktree_wip_committed' | 'session_reset' | 'instance_paused' | 'escalation_created' | 'execution_unit_reset';
|
|
21
|
+
/** Entity ID (worktree path, session ID, instance ID, or execution unit ID). */
|
|
22
|
+
entityId: string;
|
|
23
|
+
/** Human-readable description of what was done. */
|
|
24
|
+
description: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RecoveryResult {
|
|
27
|
+
/** Number of orphaned worktrees found on disk. */
|
|
28
|
+
orphanedWorktreesFound: number;
|
|
29
|
+
/** Number of WIP commits created for orphaned worktrees. */
|
|
30
|
+
wipCommitsCreated: number;
|
|
31
|
+
/** Number of sessions reset from 'running' to 'failed'. */
|
|
32
|
+
sessionsReset: number;
|
|
33
|
+
/** Number of instances reset from 'building'/'gating' to 'paused'. */
|
|
34
|
+
instancesPaused: number;
|
|
35
|
+
/** Number of escalations created for paused instances. */
|
|
36
|
+
escalationsCreated: number;
|
|
37
|
+
/** Number of execution units reset from 'assigned'/'running' to 'idle'. */
|
|
38
|
+
executionUnitsReset: number;
|
|
39
|
+
/** Detailed log of all recovery actions taken. */
|
|
40
|
+
actions: RecoveryAction[];
|
|
41
|
+
/** Non-fatal errors encountered during recovery. */
|
|
42
|
+
errors: string[];
|
|
43
|
+
}
|
|
44
|
+
interface GitResult {
|
|
45
|
+
success: boolean;
|
|
46
|
+
output: string;
|
|
47
|
+
error: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run a git command synchronously and return a structured result.
|
|
51
|
+
* Never throws -- callers inspect `result.success`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function runGit(args: string[], cwd: string): GitResult;
|
|
54
|
+
/**
|
|
55
|
+
* Parse `git worktree list --porcelain` output to build a map of
|
|
56
|
+
* worktree path -> branch name for all registered worktrees.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseWorktreeList(repoPath: string): Map<string, string>;
|
|
59
|
+
/**
|
|
60
|
+
* Scan the factory worktree directory for directories that exist on disk.
|
|
61
|
+
*
|
|
62
|
+
* Returns all subdirectories found in `factoryWorktreeDir`, each with
|
|
63
|
+
* its git branch name (if git tracks it) or null.
|
|
64
|
+
*
|
|
65
|
+
* The caller determines which worktrees are "orphaned" by comparing
|
|
66
|
+
* against the in-memory active instances map (which is empty on fresh start).
|
|
67
|
+
*/
|
|
68
|
+
export declare function scanFactoryWorktrees(config: FactoryConfig): OrphanedWorktree[];
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=crash-detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crash-detection.d.ts","sourceRoot":"","sources":["../src/crash-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMhD,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,wBAAwB,GAAG,eAAe,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,sBAAsB,CAAC;IACrH,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,eAAe,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kDAAkD;IAClD,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,oDAAoD;IACpD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AASD,UAAU,SAAS;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAgC7D;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,EAAE,CAyC9E"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orphan detection for factory crash recovery.
|
|
3
|
+
*
|
|
4
|
+
* Scans for orphaned worktrees, stale sessions, and incomplete instances
|
|
5
|
+
* that were left behind after an unclean orchestrator shutdown.
|
|
6
|
+
*
|
|
7
|
+
* Provides:
|
|
8
|
+
* - Git worktree list parsing
|
|
9
|
+
* - Factory worktree directory scanning
|
|
10
|
+
* - Types shared between detection and resolution modules
|
|
11
|
+
*/
|
|
12
|
+
import { execFileSync } from 'node:child_process';
|
|
13
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
14
|
+
import { join, resolve } from 'node:path';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Git helpers (synchronous, same pattern as git-factory.ts)
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/** Default timeout for git CLI operations (30 seconds -- read-only ops are fast). */
|
|
19
|
+
const GIT_TIMEOUT_MS = 30_000;
|
|
20
|
+
/**
|
|
21
|
+
* Run a git command synchronously and return a structured result.
|
|
22
|
+
* Never throws -- callers inspect `result.success`.
|
|
23
|
+
*/
|
|
24
|
+
export function runGit(args, cwd) {
|
|
25
|
+
try {
|
|
26
|
+
const output = execFileSync('git', args, {
|
|
27
|
+
cwd,
|
|
28
|
+
encoding: 'utf-8',
|
|
29
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
30
|
+
timeout: GIT_TIMEOUT_MS,
|
|
31
|
+
});
|
|
32
|
+
return { success: true, output: output.trim(), error: '' };
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
const execErr = err;
|
|
36
|
+
if (execErr.killed || execErr.signal === 'SIGTERM') {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
output: execErr.stdout?.toString() ?? '',
|
|
40
|
+
error: `Git operation timed out after ${GIT_TIMEOUT_MS}ms: git ${args.join(' ')}`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
output: execErr.stdout?.toString() ?? '',
|
|
46
|
+
error: execErr.stderr?.toString() ?? execErr.message ?? 'Unknown git error',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// Worktree scanning
|
|
52
|
+
// ============================================================================
|
|
53
|
+
/**
|
|
54
|
+
* Parse `git worktree list --porcelain` output to build a map of
|
|
55
|
+
* worktree path -> branch name for all registered worktrees.
|
|
56
|
+
*/
|
|
57
|
+
export function parseWorktreeList(repoPath) {
|
|
58
|
+
const result = runGit(['worktree', 'list', '--porcelain'], repoPath);
|
|
59
|
+
const map = new Map();
|
|
60
|
+
if (!result.success)
|
|
61
|
+
return map;
|
|
62
|
+
let currentPath = null;
|
|
63
|
+
for (const line of result.output.split('\n')) {
|
|
64
|
+
if (line.startsWith('worktree ')) {
|
|
65
|
+
currentPath = line.slice('worktree '.length);
|
|
66
|
+
}
|
|
67
|
+
else if (line.startsWith('branch refs/heads/') && currentPath) {
|
|
68
|
+
map.set(currentPath, line.slice('branch refs/heads/'.length));
|
|
69
|
+
currentPath = null;
|
|
70
|
+
}
|
|
71
|
+
else if (line === '') {
|
|
72
|
+
currentPath = null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return map;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Scan the factory worktree directory for directories that exist on disk.
|
|
79
|
+
*
|
|
80
|
+
* Returns all subdirectories found in `factoryWorktreeDir`, each with
|
|
81
|
+
* its git branch name (if git tracks it) or null.
|
|
82
|
+
*
|
|
83
|
+
* The caller determines which worktrees are "orphaned" by comparing
|
|
84
|
+
* against the in-memory active instances map (which is empty on fresh start).
|
|
85
|
+
*/
|
|
86
|
+
export function scanFactoryWorktrees(config) {
|
|
87
|
+
const { factoryWorktreeDir, repoPath } = config;
|
|
88
|
+
if (!existsSync(factoryWorktreeDir)) {
|
|
89
|
+
console.log(`[crash-recovery] Factory worktree directory does not exist: ${factoryWorktreeDir}`);
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
// Read subdirectories
|
|
93
|
+
const entries = readdirSync(factoryWorktreeDir);
|
|
94
|
+
const subdirs = entries.filter((entry) => {
|
|
95
|
+
const fullPath = join(factoryWorktreeDir, entry);
|
|
96
|
+
try {
|
|
97
|
+
return statSync(fullPath).isDirectory();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
if (subdirs.length === 0)
|
|
104
|
+
return [];
|
|
105
|
+
// Parse git worktree list to map paths -> branch names
|
|
106
|
+
const worktreeMap = parseWorktreeList(repoPath);
|
|
107
|
+
const pathToBranch = new Map();
|
|
108
|
+
for (const [wtPath, branch] of worktreeMap) {
|
|
109
|
+
pathToBranch.set(resolve(wtPath), branch);
|
|
110
|
+
}
|
|
111
|
+
// Build orphan list
|
|
112
|
+
const orphans = [];
|
|
113
|
+
for (const subdir of subdirs) {
|
|
114
|
+
const fullPath = resolve(join(factoryWorktreeDir, subdir));
|
|
115
|
+
const branchName = pathToBranch.get(fullPath) ?? null;
|
|
116
|
+
orphans.push({
|
|
117
|
+
worktreePath: fullPath,
|
|
118
|
+
branchName,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return orphans;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=crash-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crash-detection.js","sourceRoot":"","sources":["../src/crash-detection.ts"],"names":[],"mappings":"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"}
|