@telora/daemon 0.15.26 → 0.15.28
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/build-info.json +2 -2
- package/dist/assembly-resolvers.d.ts.map +1 -1
- package/dist/assembly-resolvers.js +210 -0
- package/dist/assembly-resolvers.js.map +1 -1
- package/dist/audit-phase.d.ts +85 -0
- package/dist/audit-phase.d.ts.map +1 -0
- package/dist/audit-phase.js +271 -0
- package/dist/audit-phase.js.map +1 -0
- package/dist/cli/session-state.d.ts +54 -0
- package/dist/cli/session-state.d.ts.map +1 -0
- package/dist/cli/session-state.js +177 -0
- package/dist/cli/session-state.js.map +1 -0
- package/dist/focus-completion.d.ts +63 -4
- package/dist/focus-completion.d.ts.map +1 -1
- package/dist/focus-completion.js +119 -47
- package/dist/focus-completion.js.map +1 -1
- package/dist/focus-engine.d.ts.map +1 -1
- package/dist/focus-engine.js +19 -0
- package/dist/focus-engine.js.map +1 -1
- package/dist/focus-loop.d.ts +2 -0
- package/dist/focus-loop.d.ts.map +1 -1
- package/dist/focus-loop.js +15 -11
- package/dist/focus-loop.js.map +1 -1
- package/dist/focus-merge.d.ts +5 -1
- package/dist/focus-merge.d.ts.map +1 -1
- package/dist/focus-merge.js +13 -9
- package/dist/focus-merge.js.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/merge-back-loop.d.ts +103 -0
- package/dist/merge-back-loop.d.ts.map +1 -0
- package/dist/merge-back-loop.js +449 -0
- package/dist/merge-back-loop.js.map +1 -0
- package/dist/queries/audit-runs.d.ts +38 -0
- package/dist/queries/audit-runs.d.ts.map +1 -0
- package/dist/queries/audit-runs.js +39 -0
- package/dist/queries/audit-runs.js.map +1 -0
- package/dist/queries/focuses.d.ts.map +1 -1
- package/dist/queries/focuses.js +1 -0
- package/dist/queries/focuses.js.map +1 -1
- package/dist/queries/issues.d.ts +41 -0
- package/dist/queries/issues.d.ts.map +1 -1
- package/dist/queries/issues.js +39 -0
- package/dist/queries/issues.js.map +1 -1
- package/dist/queries/schemas.d.ts +2 -0
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +1 -0
- package/dist/queries/schemas.js.map +1 -1
- package/dist/queries/sessions.d.ts +11 -0
- package/dist/queries/sessions.d.ts.map +1 -1
- package/dist/queries/sessions.js +28 -0
- package/dist/queries/sessions.js.map +1 -1
- package/dist/spawner-lifecycle.d.ts +29 -0
- package/dist/spawner-lifecycle.d.ts.map +1 -1
- package/dist/spawner-lifecycle.js +67 -0
- package/dist/spawner-lifecycle.js.map +1 -1
- package/dist/spawner.d.ts +3 -0
- package/dist/spawner.d.ts.map +1 -1
- package/dist/spawner.js +2 -0
- package/dist/spawner.js.map +1 -1
- package/dist/stage-classifier.d.ts +1 -1
- package/dist/stage-classifier.d.ts.map +1 -1
- package/dist/stage-classifier.js +3 -3
- package/dist/stage-classifier.js.map +1 -1
- package/dist/types/focus.d.ts +1 -0
- package/dist/types/focus.d.ts.map +1 -1
- package/dist/verification-engine.d.ts +3 -2
- package/dist/verification-engine.d.ts.map +1 -1
- package/dist/verification-engine.js +3 -2
- package/dist/verification-engine.js.map +1 -1
- package/dist/worktree-state.d.ts +58 -0
- package/dist/worktree-state.d.ts.map +1 -0
- package/dist/worktree-state.js +135 -0
- package/dist/worktree-state.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autonomous reality-tree audit phase.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the runAuditPhase scaffold with a one-shot LLM assessor session
|
|
5
|
+
* that compares the focus's observable state against the CRT/FRT and mutates
|
|
6
|
+
* the graph via reality_tree_* MCP tools. The session's narrated summary
|
|
7
|
+
* is captured to an `audit_runs` row for human review.
|
|
8
|
+
*
|
|
9
|
+
* Failure modes never throw -- each path returns outcome='continue' with
|
|
10
|
+
* an explanatory rationale and metadata.errors entries. This keeps the
|
|
11
|
+
* focus loop running so a transient audit failure does not stall execution.
|
|
12
|
+
*/
|
|
13
|
+
import { resolveAssemblyRecipe } from './assembly-engine.js';
|
|
14
|
+
// Side-effect import: registers resolvers used by the audit recipe.
|
|
15
|
+
import './assembly-resolvers.js';
|
|
16
|
+
import { getRecentFocusCycleEvaluation, } from './queries/focus-cycle-evaluations.js';
|
|
17
|
+
import { insertAuditRun, updateAuditRun } from './queries/audit-runs.js';
|
|
18
|
+
import { getFocusDeliveries } from './queries/focuses.js';
|
|
19
|
+
import { getConfig } from './queries/shared.js';
|
|
20
|
+
import { spawnAuditAgent as spawnerSpawnAuditAgent, } from './spawner.js';
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Constants exposed for testing and reuse
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Ordered assembly recipe for the audit prompt. Each entry resolves to a
|
|
26
|
+
* markdown section that gets composed into the assessor's input. Order
|
|
27
|
+
* matters: the assessor reads top-down so cycle context comes first, then
|
|
28
|
+
* code-level diff, then the live graph it must reconcile.
|
|
29
|
+
*/
|
|
30
|
+
export const AUDIT_ASSEMBLY_RECIPE = [
|
|
31
|
+
'focus.context',
|
|
32
|
+
'retired_injections',
|
|
33
|
+
'delivery.listing(scope=done_since_last_audit)',
|
|
34
|
+
'git.diff_against_base',
|
|
35
|
+
'agent_session_summaries',
|
|
36
|
+
'agent_escalations',
|
|
37
|
+
'reality_tree.snapshot',
|
|
38
|
+
];
|
|
39
|
+
/** MCP tool names the assessor session is permitted to call. */
|
|
40
|
+
export const AUDIT_MCP_TOOLS = [
|
|
41
|
+
'mcp__telora-products__telora_reality_tree',
|
|
42
|
+
'mcp__telora-products__telora_reality_tree_node',
|
|
43
|
+
'mcp__telora-products__telora_reality_tree_edge',
|
|
44
|
+
'mcp__telora-products__telora_reality_tree_link',
|
|
45
|
+
];
|
|
46
|
+
/** Default Claude model for the audit assessor. Override via deps. */
|
|
47
|
+
export const AUDIT_DEFAULT_MODEL = 'sonnet';
|
|
48
|
+
/** Default timeout for the assessor session (15 minutes). */
|
|
49
|
+
export const AUDIT_DEFAULT_TIMEOUT_MS = 15 * 60 * 1000;
|
|
50
|
+
/**
|
|
51
|
+
* Audit prompt. The assessor is told its role, given the assembled context
|
|
52
|
+
* via stdin/CLI, and instructed to emit a fenced audit-summary tail block
|
|
53
|
+
* the daemon can parse.
|
|
54
|
+
*/
|
|
55
|
+
export const AUDIT_PROMPT = [
|
|
56
|
+
'You are the autonomous reality-tree audit assessor for a Telora focus.',
|
|
57
|
+
'',
|
|
58
|
+
'Your job is to compare observable reality against the focus\'s reality tree (CRT) and apply mutations directly via the reality_tree_* MCP tools so the graph reflects what actually happened during the just-completed audit cycle.',
|
|
59
|
+
'',
|
|
60
|
+
'You have read access to the worktree and full mutation surface on the focus\'s reality tree. You do NOT propose changes for human ratification -- you make the changes. Be conservative: only mutate when the evidence in the diff, narrations, or escalations is unambiguous.',
|
|
61
|
+
'',
|
|
62
|
+
'Common mutations:',
|
|
63
|
+
'- Add or refresh evidence on an entity node when the diff shows a related change.',
|
|
64
|
+
'- Retire an injection node (set status=verified, run reality_tree_node verify) when the FRT overlay is observably true.',
|
|
65
|
+
'- Add a new entity node for an observation the tree does not yet capture.',
|
|
66
|
+
'- Flip a UDE to a desired_effect via the verify mutation when the targeted injection has retired and reality has shifted.',
|
|
67
|
+
'- Adjust an edge when a dependency appears or dissolves.',
|
|
68
|
+
'',
|
|
69
|
+
'Do NOT mutate nodes you have no evidence for. Do NOT mutate workflow state -- only the reality tree.',
|
|
70
|
+
'',
|
|
71
|
+
'When you are done, emit ONE fenced markdown block as the very last thing in your output, exactly in this shape (do not skip any field):',
|
|
72
|
+
'',
|
|
73
|
+
'```audit-summary',
|
|
74
|
+
'nodes_touched: <integer>',
|
|
75
|
+
'edges_touched: <integer>',
|
|
76
|
+
'summary: |',
|
|
77
|
+
' <markdown narrative -- one bullet per significant mutation, with seq numbers>',
|
|
78
|
+
'```',
|
|
79
|
+
'',
|
|
80
|
+
'If you make no changes, still emit the block with nodes_touched: 0 / edges_touched: 0 and a one-line summary explaining why no mutations were warranted.',
|
|
81
|
+
].join('\n');
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Summary parser
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
/**
|
|
86
|
+
* Parse the audit-summary tail block from assessor stdout. Returns null
|
|
87
|
+
* fields when the block is missing or malformed; the caller treats those
|
|
88
|
+
* as advisory zeros and writes them to the audit_runs row.
|
|
89
|
+
*/
|
|
90
|
+
export function parseAuditSummary(stdout) {
|
|
91
|
+
const fenceRegex = /```audit-summary\s*\n([\s\S]*?)```/g;
|
|
92
|
+
let lastMatch = null;
|
|
93
|
+
let m;
|
|
94
|
+
while ((m = fenceRegex.exec(stdout)) !== null) {
|
|
95
|
+
lastMatch = m;
|
|
96
|
+
}
|
|
97
|
+
if (!lastMatch) {
|
|
98
|
+
return { summaryMd: null, nodesTouched: 0, edgesTouched: 0 };
|
|
99
|
+
}
|
|
100
|
+
const body = lastMatch[1];
|
|
101
|
+
let nodesTouched = 0;
|
|
102
|
+
let edgesTouched = 0;
|
|
103
|
+
let summaryMd = null;
|
|
104
|
+
const nodesMatch = /^\s*nodes_touched:\s*(\d+)\s*$/m.exec(body);
|
|
105
|
+
if (nodesMatch)
|
|
106
|
+
nodesTouched = parseInt(nodesMatch[1], 10);
|
|
107
|
+
const edgesMatch = /^\s*edges_touched:\s*(\d+)\s*$/m.exec(body);
|
|
108
|
+
if (edgesMatch)
|
|
109
|
+
edgesTouched = parseInt(edgesMatch[1], 10);
|
|
110
|
+
// summary: | <newline> then indented lines until end of block.
|
|
111
|
+
const summaryStart = /^\s*summary:\s*\|\s*$/m.exec(body);
|
|
112
|
+
if (summaryStart) {
|
|
113
|
+
const start = summaryStart.index + summaryStart[0].length;
|
|
114
|
+
const tail = body.slice(start);
|
|
115
|
+
// Each indented line (>= 2 spaces) is part of the summary; collect until
|
|
116
|
+
// we hit a non-indented non-empty line (none expected, but be safe).
|
|
117
|
+
const lines = tail.split('\n');
|
|
118
|
+
const collected = [];
|
|
119
|
+
for (const raw of lines) {
|
|
120
|
+
if (raw.trim().length === 0) {
|
|
121
|
+
collected.push('');
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const dedented = raw.replace(/^ {2}/, '');
|
|
125
|
+
collected.push(dedented);
|
|
126
|
+
}
|
|
127
|
+
const joined = collected.join('\n').trim();
|
|
128
|
+
if (joined.length > 0)
|
|
129
|
+
summaryMd = joined;
|
|
130
|
+
}
|
|
131
|
+
return { summaryMd, nodesTouched, edgesTouched };
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Default dependency wiring
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
async function defaultAssembleContext(focusId, recipe) {
|
|
137
|
+
const config = getConfig();
|
|
138
|
+
const deliveries = await getFocusDeliveries(focusId);
|
|
139
|
+
const ctx = {
|
|
140
|
+
focusId,
|
|
141
|
+
deliveryIds: deliveries.map(d => d.id),
|
|
142
|
+
worktreePath: null,
|
|
143
|
+
config,
|
|
144
|
+
organizationId: config.organizationId,
|
|
145
|
+
productId: config.productId,
|
|
146
|
+
};
|
|
147
|
+
return await resolveAssemblyRecipe([...recipe], ctx);
|
|
148
|
+
}
|
|
149
|
+
async function defaultGetCurrentCycleNumber(focusId) {
|
|
150
|
+
const prev = await getRecentFocusCycleEvaluation(focusId);
|
|
151
|
+
if (!prev)
|
|
152
|
+
return 1;
|
|
153
|
+
// The audit phase is the entry to a new cycle iff the prior tick was
|
|
154
|
+
// evaluate -> continue. Otherwise we're inside an existing cycle.
|
|
155
|
+
if (prev.phase === 'evaluate' && prev.outcome === 'continue') {
|
|
156
|
+
return prev.cycle_number + 1;
|
|
157
|
+
}
|
|
158
|
+
return prev.cycle_number;
|
|
159
|
+
}
|
|
160
|
+
export const defaultAuditDeps = {
|
|
161
|
+
assembleContext: defaultAssembleContext,
|
|
162
|
+
insertAuditRun: ({ focusId, cycleNumber, model, sessionId }) => insertAuditRun({ focusId, cycleNumber, model, sessionId }),
|
|
163
|
+
updateAuditRun: ({ auditRunId, summaryMd, nodesTouched, edgesTouched }) => updateAuditRun({ auditRunId, summaryMd, nodesTouched, edgesTouched }),
|
|
164
|
+
getCurrentCycleNumber: defaultGetCurrentCycleNumber,
|
|
165
|
+
spawnAuditAgent: (opts) => spawnerSpawnAuditAgent(opts),
|
|
166
|
+
parseAuditSummary,
|
|
167
|
+
getConfig,
|
|
168
|
+
};
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
// Core phase
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
/**
|
|
173
|
+
* Run the audit phase for a focus. Spawns a one-shot assessor, captures
|
|
174
|
+
* the audit-summary tail block, and writes an audit_runs row. Always
|
|
175
|
+
* returns 'continue' so the focus loop advances regardless of audit
|
|
176
|
+
* outcome -- the row + metadata.errors describe what happened.
|
|
177
|
+
*/
|
|
178
|
+
export async function runAuditPhase(focusId, deps = defaultAuditDeps) {
|
|
179
|
+
const errors = [];
|
|
180
|
+
const metadata = {};
|
|
181
|
+
let cycleNumber = 1;
|
|
182
|
+
try {
|
|
183
|
+
cycleNumber = await deps.getCurrentCycleNumber(focusId);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
errors.push(`cycle_lookup: ${err.message}`);
|
|
187
|
+
}
|
|
188
|
+
metadata.cycleNumber = cycleNumber;
|
|
189
|
+
let assembled = '';
|
|
190
|
+
try {
|
|
191
|
+
assembled = await deps.assembleContext(focusId, AUDIT_ASSEMBLY_RECIPE);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
errors.push(`assembly: ${err.message}`);
|
|
195
|
+
}
|
|
196
|
+
let auditRunId = null;
|
|
197
|
+
try {
|
|
198
|
+
const row = await deps.insertAuditRun({
|
|
199
|
+
focusId, cycleNumber, model: AUDIT_DEFAULT_MODEL, sessionId: null,
|
|
200
|
+
});
|
|
201
|
+
auditRunId = row.id;
|
|
202
|
+
metadata.auditRunId = row.id;
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
errors.push(`insert_audit_run: ${err.message}`);
|
|
206
|
+
}
|
|
207
|
+
const config = deps.getConfig();
|
|
208
|
+
const prompt = assembled
|
|
209
|
+
? `${assembled}\n\n---\n\n${AUDIT_PROMPT}`
|
|
210
|
+
: AUDIT_PROMPT;
|
|
211
|
+
let spawnResult;
|
|
212
|
+
try {
|
|
213
|
+
spawnResult = await deps.spawnAuditAgent({
|
|
214
|
+
config,
|
|
215
|
+
prompt,
|
|
216
|
+
worktreePath: null,
|
|
217
|
+
focusId,
|
|
218
|
+
cycleNumber,
|
|
219
|
+
model: AUDIT_DEFAULT_MODEL,
|
|
220
|
+
timeoutMs: AUDIT_DEFAULT_TIMEOUT_MS,
|
|
221
|
+
allowedTools: AUDIT_MCP_TOOLS,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
errors.push(`spawn: ${err.message}`);
|
|
226
|
+
spawnResult = { exitCode: null, stdout: '', stderr: '', errorMessage: err.message };
|
|
227
|
+
}
|
|
228
|
+
if (spawnResult.errorMessage) {
|
|
229
|
+
errors.push(`spawn: ${spawnResult.errorMessage}`);
|
|
230
|
+
}
|
|
231
|
+
if (spawnResult.exitCode !== null && spawnResult.exitCode !== 0) {
|
|
232
|
+
errors.push(`exit_code: ${spawnResult.exitCode}`);
|
|
233
|
+
if (spawnResult.stderr) {
|
|
234
|
+
metadata.stderrTail = spawnResult.stderr.slice(-1000);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
const parser = deps.parseAuditSummary ?? parseAuditSummary;
|
|
238
|
+
const summary = parser(spawnResult.stdout);
|
|
239
|
+
if (summary.summaryMd === null) {
|
|
240
|
+
errors.push('summary_block_missing');
|
|
241
|
+
}
|
|
242
|
+
metadata.nodesTouched = summary.nodesTouched;
|
|
243
|
+
metadata.edgesTouched = summary.edgesTouched;
|
|
244
|
+
if (auditRunId) {
|
|
245
|
+
try {
|
|
246
|
+
await deps.updateAuditRun({
|
|
247
|
+
auditRunId,
|
|
248
|
+
summaryMd: summary.summaryMd,
|
|
249
|
+
nodesTouched: summary.nodesTouched,
|
|
250
|
+
edgesTouched: summary.edgesTouched,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
errors.push(`update_audit_run: ${err.message}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (errors.length > 0) {
|
|
258
|
+
metadata.errors = errors;
|
|
259
|
+
return {
|
|
260
|
+
outcome: 'continue',
|
|
261
|
+
rationale: `audit cycle ${cycleNumber} completed with ${errors.length} issue(s)`,
|
|
262
|
+
metadata,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
outcome: 'continue',
|
|
267
|
+
rationale: `audit cycle ${cycleNumber} -- ${summary.nodesTouched} nodes touched, ${summary.edgesTouched} edges touched`,
|
|
268
|
+
metadata,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=audit-phase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-phase.js","sourceRoot":"","sources":["../src/audit-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,qBAAqB,EAAwB,MAAM,sBAAsB,CAAC;AACnF,oEAAoE;AACpE,OAAO,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,GAE9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAoB,MAAM,yBAAyB,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EACL,eAAe,IAAI,sBAAsB,GAG1C,MAAM,cAAc,CAAC;AAGtB,8EAA8E;AAC9E,0CAA0C;AAC1C,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAsB;IACtD,eAAe;IACf,oBAAoB;IACpB,+CAA+C;IAC/C,uBAAuB;IACvB,yBAAyB;IACzB,mBAAmB;IACnB,uBAAuB;CACxB,CAAC;AAEF,gEAAgE;AAChE,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,2CAA2C;IAC3C,gDAAgD;IAChD,gDAAgD;IAChD,gDAAgD;CACjD,CAAC;AAEF,sEAAsE;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC;AAE5C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,wEAAwE;IACxE,EAAE;IACF,qOAAqO;IACrO,EAAE;IACF,gRAAgR;IAChR,EAAE;IACF,mBAAmB;IACnB,mFAAmF;IACnF,yHAAyH;IACzH,2EAA2E;IAC3E,2HAA2H;IAC3H,0DAA0D;IAC1D,EAAE;IACF,sGAAsG;IACtG,EAAE;IACF,yIAAyI;IACzI,EAAE;IACF,kBAAkB;IAClB,0BAA0B;IAC1B,0BAA0B;IAC1B,YAAY;IACZ,iFAAiF;IACjF,KAAK;IACL,EAAE;IACF,0JAA0J;CAC3J,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAsCb,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,UAAU,GAAG,qCAAqC,CAAC;IACzD,IAAI,SAAS,GAA2B,IAAI,CAAC;IAC7C,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,SAAS,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAC/D,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,SAAS,GAAkB,IAAI,CAAC;IAEpC,MAAM,UAAU,GAAG,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,IAAI,UAAU;QAAE,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAE3D,MAAM,UAAU,GAAG,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,IAAI,UAAU;QAAE,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAE3D,+DAA+D;IAC/D,MAAM,YAAY,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,yEAAyE;QACzE,qEAAqE;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACnB,SAAS;YACX,CAAC;YACD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS,GAAG,MAAM,CAAC;IAC5C,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AACnD,CAAC;AAED,8EAA8E;AAC9E,4BAA4B;AAC5B,8EAA8E;AAE9E,KAAK,UAAU,sBAAsB,CAAC,OAAe,EAAE,MAAyB;IAC9E,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,GAAG,GAAoB;QAC3B,OAAO;QACP,WAAW,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,YAAY,EAAE,IAAI;QAClB,MAAM;QACN,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;IACF,OAAO,MAAM,qBAAqB,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,OAAe;IACzD,MAAM,IAAI,GAAG,MAAM,6BAA6B,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,qEAAqE;IACrE,kEAAkE;IAClE,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU,IAAI,IAAI,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC,YAAY,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAmB;IAC9C,eAAe,EAAE,sBAAsB;IACvC,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAC7D,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC5D,cAAc,EAAE,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,EAAE,CACxE,cAAc,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IACvE,qBAAqB,EAAE,4BAA4B;IACnD,eAAe,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC;IACvD,iBAAiB;IACjB,SAAS;CACV,CAAC;AAEF,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,OAAuB,gBAAgB;IAEvC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAE7C,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,iBAAkB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC;IAEnC,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,aAAc,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC;YACpC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,IAAI;SAClE,CAAC,CAAC;QACH,UAAU,GAAG,GAAG,CAAC,EAAE,CAAC;QACpB,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,qBAAsB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,SAAS;QACtB,CAAC,CAAC,GAAG,SAAS,cAAc,YAAY,EAAE;QAC1C,CAAC,CAAC,YAAY,CAAC;IAEjB,IAAI,WAA6B,CAAC;IAClC,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC;YACvC,MAAM;YACN,MAAM;YACN,YAAY,EAAE,IAAI;YAClB,OAAO;YACP,WAAW;YACX,KAAK,EAAE,mBAAmB;YAC1B,SAAS,EAAE,wBAAwB;YACnC,YAAY,EAAE,eAAe;SAC9B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,UAAW,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,WAAW,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC;IACjG,CAAC;IAED,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,UAAU,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,WAAW,CAAC,QAAQ,KAAK,IAAI,IAAI,WAAW,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QAClD,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;YACvB,QAAQ,CAAC,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACvC,CAAC;IACD,QAAQ,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC7C,QAAQ,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAE7C,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,cAAc,CAAC;gBACxB,UAAU;gBACV,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,YAAY,EAAE,OAAO,CAAC,YAAY;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,qBAAsB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;QACzB,OAAO;YACL,OAAO,EAAE,UAAU;YACnB,SAAS,EAAE,eAAe,WAAW,mBAAmB,MAAM,CAAC,MAAM,WAAW;YAChF,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,UAAU;QACnB,SAAS,EAAE,eAAe,WAAW,OAAO,OAAO,CAAC,YAAY,mBAAmB,OAAO,CAAC,YAAY,gBAAgB;QACvH,QAAQ;KACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `telora-daemon session-state` subcommand.
|
|
3
|
+
*
|
|
4
|
+
* One-shot bootstrap helper for the Claude Code SessionStart and PreToolUse
|
|
5
|
+
* hooks. Reads `.telora/daemon.json` from cwd (or `--config <path>`), calls
|
|
6
|
+
* the product-api `session_state` action, and emits either:
|
|
7
|
+
*
|
|
8
|
+
* - default: two-line invariant summary suitable for Claude's session
|
|
9
|
+
* context. Line 1 is the connection (URL + org + product name); line 2
|
|
10
|
+
* reminds the agent to resolve dynamic state (active focuses, branches,
|
|
11
|
+
* deliveries) on demand via MCP. The plain path deliberately omits
|
|
12
|
+
* dynamic state -- it changes during a session and stale snapshots in
|
|
13
|
+
* the bootstrap are noise.
|
|
14
|
+
* - `--json`: full structured payload (including activeFocus, branches,
|
|
15
|
+
* deliveryCounts) for enforcement hooks and other programmatic consumers.
|
|
16
|
+
*
|
|
17
|
+
* Designed to be silent and fast at session open: missing daemon.json means
|
|
18
|
+
* "not Telora-connected" and the command exits 0 with no output. Backend
|
|
19
|
+
* errors and git errors degrade gracefully -- they print to stderr and the
|
|
20
|
+
* command still exits 0 so the hook never blocks Claude Code.
|
|
21
|
+
*/
|
|
22
|
+
interface SessionStateResponse {
|
|
23
|
+
success?: boolean;
|
|
24
|
+
connectedUrl?: string;
|
|
25
|
+
organizationId?: string;
|
|
26
|
+
organizationName?: string | null;
|
|
27
|
+
productId?: string;
|
|
28
|
+
productName?: string;
|
|
29
|
+
activeFocus?: null | {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
assignedAgentRoleId: string | null;
|
|
33
|
+
assignedAgentRoleName: string | null;
|
|
34
|
+
pipelineConfig: Record<string, unknown> | null;
|
|
35
|
+
};
|
|
36
|
+
deliveryCounts?: Record<string, number>;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface SessionStateOptions {
|
|
40
|
+
/** Emit structured JSON instead of human-readable text. */
|
|
41
|
+
json?: boolean;
|
|
42
|
+
/** Override the daemon.json path (default: ./.telora/daemon.json). */
|
|
43
|
+
config?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Two-line invariant summary. Dynamic state (active focus, branches,
|
|
47
|
+
* deliveries) is intentionally omitted -- it should be resolved on demand
|
|
48
|
+
* via MCP at the point of use, not baked into the bootstrap where it goes
|
|
49
|
+
* stale during the session. Exported for unit testing.
|
|
50
|
+
*/
|
|
51
|
+
export declare function formatPlain(state: SessionStateResponse): string;
|
|
52
|
+
export declare function runSessionState(opts: SessionStateOptions): Promise<void>;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=session-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-state.d.ts","sourceRoot":"","sources":["../../src/cli/session-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAqBH,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,IAAI,GAAG;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;QACrC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KAChD,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwGD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAQ/D;AAiBD,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B9E"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `telora-daemon session-state` subcommand.
|
|
3
|
+
*
|
|
4
|
+
* One-shot bootstrap helper for the Claude Code SessionStart and PreToolUse
|
|
5
|
+
* hooks. Reads `.telora/daemon.json` from cwd (or `--config <path>`), calls
|
|
6
|
+
* the product-api `session_state` action, and emits either:
|
|
7
|
+
*
|
|
8
|
+
* - default: two-line invariant summary suitable for Claude's session
|
|
9
|
+
* context. Line 1 is the connection (URL + org + product name); line 2
|
|
10
|
+
* reminds the agent to resolve dynamic state (active focuses, branches,
|
|
11
|
+
* deliveries) on demand via MCP. The plain path deliberately omits
|
|
12
|
+
* dynamic state -- it changes during a session and stale snapshots in
|
|
13
|
+
* the bootstrap are noise.
|
|
14
|
+
* - `--json`: full structured payload (including activeFocus, branches,
|
|
15
|
+
* deliveryCounts) for enforcement hooks and other programmatic consumers.
|
|
16
|
+
*
|
|
17
|
+
* Designed to be silent and fast at session open: missing daemon.json means
|
|
18
|
+
* "not Telora-connected" and the command exits 0 with no output. Backend
|
|
19
|
+
* errors and git errors degrade gracefully -- they print to stderr and the
|
|
20
|
+
* command still exits 0 so the hook never blocks Claude Code.
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
23
|
+
import { execFileSync } from 'node:child_process';
|
|
24
|
+
import { resolve } from 'node:path';
|
|
25
|
+
function loadDaemonJson(configPath) {
|
|
26
|
+
if (!existsSync(configPath))
|
|
27
|
+
return null;
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
process.stderr.write(`session-state: cannot parse ${configPath}: ${err.message}\n`);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function tryGit(args, cwd) {
|
|
37
|
+
try {
|
|
38
|
+
return execFileSync('git', args, {
|
|
39
|
+
cwd,
|
|
40
|
+
encoding: 'utf-8',
|
|
41
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
42
|
+
}).trim();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function collectBranchInfo(integrationBranch, repoPath) {
|
|
49
|
+
// Verify the integration branch exists locally; if not, skip git work.
|
|
50
|
+
const verifyRef = tryGit(['rev-parse', '--verify', integrationBranch], repoPath);
|
|
51
|
+
if (!verifyRef)
|
|
52
|
+
return [];
|
|
53
|
+
const branchesRaw = tryGit(['for-each-ref', '--format=%(refname:short)', 'refs/heads/'], repoPath);
|
|
54
|
+
if (!branchesRaw)
|
|
55
|
+
return [];
|
|
56
|
+
const branches = branchesRaw.split('\n').filter(b => b && b !== integrationBranch);
|
|
57
|
+
const infos = [];
|
|
58
|
+
for (const branch of branches) {
|
|
59
|
+
// Skip the usual main-line branches to keep output focused on focus work.
|
|
60
|
+
if (branch === 'main' || branch === 'master')
|
|
61
|
+
continue;
|
|
62
|
+
const countStr = tryGit(['rev-list', '--count', `${integrationBranch}..${branch}`], repoPath);
|
|
63
|
+
if (!countStr)
|
|
64
|
+
continue;
|
|
65
|
+
const commitsAhead = parseInt(countStr, 10);
|
|
66
|
+
if (!Number.isFinite(commitsAhead) || commitsAhead <= 0)
|
|
67
|
+
continue;
|
|
68
|
+
const info = { branchName: branch, commitsAhead };
|
|
69
|
+
const oldestCommitTs = tryGit([
|
|
70
|
+
'log',
|
|
71
|
+
`${integrationBranch}..${branch}`,
|
|
72
|
+
'--reverse',
|
|
73
|
+
'--format=%ct',
|
|
74
|
+
'-1',
|
|
75
|
+
], repoPath);
|
|
76
|
+
if (oldestCommitTs) {
|
|
77
|
+
const ts = parseInt(oldestCommitTs, 10);
|
|
78
|
+
if (Number.isFinite(ts)) {
|
|
79
|
+
info.oldestUnmergedAge = Math.max(0, Math.floor(Date.now() / 1000 - ts));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
infos.push(info);
|
|
83
|
+
}
|
|
84
|
+
infos.sort((a, b) => b.commitsAhead - a.commitsAhead);
|
|
85
|
+
return infos;
|
|
86
|
+
}
|
|
87
|
+
async function callSessionState(cfg, productId) {
|
|
88
|
+
if (!cfg.teloraUrl || !cfg.trackerId) {
|
|
89
|
+
process.stderr.write('session-state: daemon.json missing teloraUrl or trackerId\n');
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const url = `${cfg.teloraUrl}/functions/v1/product-api`;
|
|
93
|
+
const controller = new AbortController();
|
|
94
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
95
|
+
try {
|
|
96
|
+
const response = await fetch(url, {
|
|
97
|
+
method: 'POST',
|
|
98
|
+
headers: {
|
|
99
|
+
Authorization: `Bearer ${cfg.trackerId}`,
|
|
100
|
+
'Content-Type': 'application/json',
|
|
101
|
+
},
|
|
102
|
+
body: JSON.stringify({ action: 'session_state', productId }),
|
|
103
|
+
signal: controller.signal,
|
|
104
|
+
});
|
|
105
|
+
const data = (await response.json());
|
|
106
|
+
if (!response.ok || data.error) {
|
|
107
|
+
process.stderr.write(`session-state: API error ${response.status}: ${data.error ?? 'unknown'}\n`);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
process.stderr.write(`session-state: fetch failed: ${err.message}\n`);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
clearTimeout(timeout);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Two-line invariant summary. Dynamic state (active focus, branches,
|
|
122
|
+
* deliveries) is intentionally omitted -- it should be resolved on demand
|
|
123
|
+
* via MCP at the point of use, not baked into the bootstrap where it goes
|
|
124
|
+
* stale during the session. Exported for unit testing.
|
|
125
|
+
*/
|
|
126
|
+
export function formatPlain(state) {
|
|
127
|
+
const url = state.connectedUrl ?? '';
|
|
128
|
+
const orgName = state.organizationName ?? 'unknown';
|
|
129
|
+
const productName = state.productName ?? 'unknown';
|
|
130
|
+
return [
|
|
131
|
+
`Telora connected: ${url} / ${orgName} / ${productName}`,
|
|
132
|
+
'Active focuses, branches, and deliveries are resolved on demand via Telora MCP.',
|
|
133
|
+
].join('\n');
|
|
134
|
+
}
|
|
135
|
+
function resolveProductIdAndRepoPath(cfg) {
|
|
136
|
+
const cwd = process.cwd();
|
|
137
|
+
if (cfg.products && cfg.products.length > 0) {
|
|
138
|
+
const first = cfg.products[0];
|
|
139
|
+
return {
|
|
140
|
+
productId: first.id ?? cfg.productId ?? null,
|
|
141
|
+
repoPath: first.repoPath ?? cwd,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return { productId: cfg.productId ?? null, repoPath: cwd };
|
|
145
|
+
}
|
|
146
|
+
export async function runSessionState(opts) {
|
|
147
|
+
const configPath = resolve(opts.config ?? '.telora/daemon.json');
|
|
148
|
+
const cfg = loadDaemonJson(configPath);
|
|
149
|
+
if (!cfg) {
|
|
150
|
+
// Not Telora-connected -- silent success.
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const { productId, repoPath } = resolveProductIdAndRepoPath(cfg);
|
|
154
|
+
if (!productId) {
|
|
155
|
+
process.stderr.write('session-state: daemon.json has no productId\n');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const state = await callSessionState(cfg, productId);
|
|
159
|
+
if (!state)
|
|
160
|
+
return;
|
|
161
|
+
if (cfg.teloraUrl)
|
|
162
|
+
state.connectedUrl = cfg.teloraUrl;
|
|
163
|
+
if (opts.json) {
|
|
164
|
+
// JSON path retains dynamic state for programmatic consumers
|
|
165
|
+
// (enforcement hooks, observability). The git work is only done here.
|
|
166
|
+
const integrationBranch = cfg.engines?.strategy?.integrationBranch ?? 'integration';
|
|
167
|
+
const branches = collectBranchInfo(integrationBranch, repoPath);
|
|
168
|
+
const payload = {
|
|
169
|
+
...state,
|
|
170
|
+
branches,
|
|
171
|
+
};
|
|
172
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
process.stdout.write(`${formatPlain(state)}\n`);
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=session-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-state.js","sourceRoot":"","sources":["../../src/cli/session-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,18 +7,77 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { DaemonConfig, FocusTeamState, FocusDeliveryInfo, Workflow, PolicyFailureMode } from './types.js';
|
|
9
9
|
import type { StageAdvanceResult } from './delivery-lifecycle.js';
|
|
10
|
+
import { mergeFocusBranch } from './focus-merge.js';
|
|
11
|
+
import { branchHasUnmergedCommits } from './git.js';
|
|
10
12
|
export { isStatusTerminal, isStatusAgentActionable } from './stage-classifier.js';
|
|
11
13
|
/**
|
|
12
14
|
* Decide whether to attempt mergeFocusBranch on team exit.
|
|
13
15
|
*
|
|
16
|
+
* The gate asks "does the branch have clean committed work?" rather than
|
|
17
|
+
* "did the team session exit cleanly?" -- so a team that exits via review-
|
|
18
|
+
* cycle SIGTERM, role-clear, daemon crash, or manual termination still gets
|
|
19
|
+
* its committed work propagated to integration.
|
|
20
|
+
*
|
|
14
21
|
* Skip merge when:
|
|
15
|
-
* - The team
|
|
16
|
-
*
|
|
17
|
-
*
|
|
22
|
+
* - The team is still in its planning phase (cancellation mid-planning --
|
|
23
|
+
* nothing scoped, nothing to merge), OR
|
|
24
|
+
* - The team is a read-only audit session (read-only violation; commits, if
|
|
25
|
+
* any, are surfaced separately by the existing readOnly guard), OR
|
|
26
|
+
* - The branch has no committed work ahead of integration (clean exit with
|
|
27
|
+
* no commits, e.g. audit team or planning-only team).
|
|
18
28
|
*
|
|
19
29
|
* Exported for unit testing the gate logic in isolation.
|
|
20
30
|
*/
|
|
21
|
-
export declare function shouldAttemptMerge(
|
|
31
|
+
export declare function shouldAttemptMerge(teamState: Pick<FocusTeamState, 'planningPhase' | 'readOnly'>, branchHasCommits: boolean): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Statuses for deliveries whose git state should be reported on team
|
|
34
|
+
* completion. Includes 'done' so a focus whose deliveries all reached done
|
|
35
|
+
* before the branch was merged (review SIGTERM, role-clear, deferred merge,
|
|
36
|
+
* etc.) still attempts the merge instead of being short-circuited as
|
|
37
|
+
* "no worked deliveries". Excludes 'queued'/'planning'/'paused'/'cancelled'
|
|
38
|
+
* — those represent work that never started or was abandoned.
|
|
39
|
+
*
|
|
40
|
+
* Exported for unit testing.
|
|
41
|
+
*/
|
|
42
|
+
export declare const REPORTABLE_DELIVERY_STATUSES: ReadonlySet<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Filter delivery list to those whose git state should be reported on team
|
|
45
|
+
* completion. Excludes already-merged deliveries so we don't re-report them.
|
|
46
|
+
*
|
|
47
|
+
* Exported for unit testing the filter logic without invoking handleTeamCompletion.
|
|
48
|
+
*/
|
|
49
|
+
export declare function selectWorkedDeliveryIds(deliveries: readonly {
|
|
50
|
+
id: string;
|
|
51
|
+
executionStatus: string | null;
|
|
52
|
+
}[], alreadyMerged: ReadonlySet<string>): string[];
|
|
53
|
+
export interface FocusMergeAttemptDeps {
|
|
54
|
+
branchHasUnmergedCommits: typeof branchHasUnmergedCommits;
|
|
55
|
+
mergeFocusBranch: typeof mergeFocusBranch;
|
|
56
|
+
}
|
|
57
|
+
export interface FocusMergeAttemptResult {
|
|
58
|
+
attempted: boolean;
|
|
59
|
+
mergeSucceeded: boolean;
|
|
60
|
+
exitReason: string | null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decide whether to merge the focus branch and, if so, run the merge.
|
|
64
|
+
*
|
|
65
|
+
* This is the integration of three separate concerns that the merge gate
|
|
66
|
+
* conflated before:
|
|
67
|
+
* 1. Branch state: does the focus branch actually have committed work?
|
|
68
|
+
* 2. Team gate: planningPhase + readOnly safety nets in shouldAttemptMerge.
|
|
69
|
+
* 3. Per-delivery telemetry: workedDeliveryIds is passed through for
|
|
70
|
+
* git-state reporting inside mergeFocusBranch.
|
|
71
|
+
*
|
|
72
|
+
* Returns attempted=false when the gate skips the merge (clean exit with
|
|
73
|
+
* nothing to merge, planning-phase, or read-only). Returns attempted=true
|
|
74
|
+
* with the merge result otherwise.
|
|
75
|
+
*
|
|
76
|
+
* Exported so tests can verify the threading from done-only deliveries +
|
|
77
|
+
* branch-with-commits to a real mergeFocusBranch invocation, without having
|
|
78
|
+
* to mock all of handleTeamCompletion's other side effects.
|
|
79
|
+
*/
|
|
80
|
+
export declare function attemptFocusMerge(config: DaemonConfig, teamState: FocusTeamState, sessionId: string, workedDeliveryIds: string[], deps?: FocusMergeAttemptDeps): Promise<FocusMergeAttemptResult>;
|
|
22
81
|
export interface TeamCompletionParams {
|
|
23
82
|
config: DaemonConfig;
|
|
24
83
|
teamState: FocusTeamState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus-completion.d.ts","sourceRoot":"","sources":["../src/focus-completion.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAcpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"focus-completion.d.ts","sourceRoot":"","sources":["../src/focus-completion.ts"],"names":[],"mappings":"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"}
|