@cat-factory/orchestration 0.123.3 → 0.123.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/modules/execution/DeployerStepController.d.ts +185 -0
- package/dist/modules/execution/DeployerStepController.d.ts.map +1 -0
- package/dist/modules/execution/DeployerStepController.js +670 -0
- package/dist/modules/execution/DeployerStepController.js.map +1 -0
- package/dist/modules/execution/ExecutionService.d.ts +8 -211
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
- package/dist/modules/execution/ExecutionService.js +59 -805
- package/dist/modules/execution/ExecutionService.js.map +1 -1
- package/dist/modules/execution/FollowUpGateController.d.ts +104 -0
- package/dist/modules/execution/FollowUpGateController.d.ts.map +1 -0
- package/dist/modules/execution/FollowUpGateController.js +317 -0
- package/dist/modules/execution/FollowUpGateController.js.map +1 -0
- package/dist/modules/execution/RunAdmission.d.ts +204 -0
- package/dist/modules/execution/RunAdmission.d.ts.map +1 -0
- package/dist/modules/execution/RunAdmission.js +571 -0
- package/dist/modules/execution/RunAdmission.js.map +1 -0
- package/dist/modules/execution/RunDispatcher.d.ts +24 -196
- package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
- package/dist/modules/execution/RunDispatcher.js +70 -929
- package/dist/modules/execution/RunDispatcher.js.map +1 -1
- package/dist/modules/execution/review-kinds.d.ts +41 -0
- package/dist/modules/execution/review-kinds.d.ts.map +1 -0
- package/dist/modules/execution/review-kinds.js +241 -0
- package/dist/modules/execution/review-kinds.js.map +1 -0
- package/dist/modules/observability/AgentContextObservabilityService.d.ts +24 -2
- package/dist/modules/observability/AgentContextObservabilityService.d.ts.map +1 -1
- package/dist/modules/observability/AgentContextObservabilityService.js +39 -7
- package/dist/modules/observability/AgentContextObservabilityService.js.map +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { assertFound, ConflictError } from '@cat-factory/kernel';
|
|
2
|
+
import { bugInvestigation } from '@cat-factory/agents';
|
|
3
|
+
import { BUG_INVESTIGATOR_AGENT_KIND, CLARITY_REVIEW_AGENT_KIND, REQUIREMENTS_REVIEW_AGENT_KIND, } from './ci.logic.js';
|
|
4
|
+
/**
|
|
5
|
+
* The requirements subject for the review gate: closures over the requirements reviewer
|
|
6
|
+
* service. The service-not-configured guard preserves the exact 409 the inline reviewer
|
|
7
|
+
* raised before this extraction.
|
|
8
|
+
*/
|
|
9
|
+
export function buildRequirementsKind(deps) {
|
|
10
|
+
const require = () => {
|
|
11
|
+
if (!deps.requirementReviewService?.enabled) {
|
|
12
|
+
throw new ConflictError('The requirements reviewer is not configured');
|
|
13
|
+
}
|
|
14
|
+
return deps.requirementReviewService;
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
agentKind: REQUIREMENTS_REVIEW_AGENT_KIND,
|
|
18
|
+
entityName: 'Requirement review',
|
|
19
|
+
enabled: () => !!deps.requirementReviewService?.enabled,
|
|
20
|
+
getForBlock: (ws, blockId) => require().getForBlock(ws, blockId),
|
|
21
|
+
review: (ws, block, preset) => require().review(ws, block.id, {
|
|
22
|
+
maxIterations: preset.maxRequirementIterations,
|
|
23
|
+
concernThreshold: preset.maxRequirementConcernAllowed,
|
|
24
|
+
}),
|
|
25
|
+
reReview: (ws, reviewId, preset) => require().reReview(ws, reviewId, { concernThreshold: preset.maxRequirementConcernAllowed }),
|
|
26
|
+
incorporate: async (ws, _blockId, reviewId, feedback) => {
|
|
27
|
+
await require().incorporate(ws, reviewId, { feedback });
|
|
28
|
+
},
|
|
29
|
+
markIncorporated: (ws, reviewId) => require().markIncorporated(ws, reviewId),
|
|
30
|
+
markReReviewing: (ws, reviewId) => require().markReReviewing(ws, reviewId),
|
|
31
|
+
markIncorporating: (ws, reviewId) => require().markIncorporating(ws, reviewId),
|
|
32
|
+
grantExtraRound: (ws, reviewId) => require().grantExtraRound(ws, reviewId),
|
|
33
|
+
prepareRecommendations: (ws, reviewId, items) => require().prepareRecommendations(ws, reviewId, items),
|
|
34
|
+
markRecommendationPending: (ws, reviewId, recId, note) => require().markRecommendationPending(ws, reviewId, recId, note),
|
|
35
|
+
fillRecommendations: async (ws, blockId) => {
|
|
36
|
+
const svc = require();
|
|
37
|
+
const review = assertFound(await svc.getForBlock(ws, blockId), 'Requirement review', blockId);
|
|
38
|
+
await svc.fillPendingRecommendations(ws, review.id, {
|
|
39
|
+
onProgress: (r) => deps.events.requirementReviewChanged?.(ws, r) ?? Promise.resolve(),
|
|
40
|
+
});
|
|
41
|
+
return assertFound(await svc.getForBlock(ws, blockId), 'Requirement review', blockId);
|
|
42
|
+
},
|
|
43
|
+
autoRecommend: async (ws, blockId) => {
|
|
44
|
+
const svc = require();
|
|
45
|
+
const review = assertFound(await svc.getForBlock(ws, blockId), 'Requirement review', blockId);
|
|
46
|
+
await svc.autoRecommend(ws, review.id, {
|
|
47
|
+
onProgress: (r) => deps.events.requirementReviewChanged?.(ws, r) ?? Promise.resolve(),
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
emit: (ws, review) => deps.events.requirementReviewChanged?.(ws, review) ?? Promise.resolve(),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The clarity (bug-report triage) subject for the review gate: threads any upstream
|
|
55
|
+
* `bug-investigator` output into the reviewer/incorporation context, otherwise identical to
|
|
56
|
+
* the requirements kind.
|
|
57
|
+
*/
|
|
58
|
+
export function buildClarityKind(deps) {
|
|
59
|
+
const require = () => {
|
|
60
|
+
if (!deps.clarityReviewService) {
|
|
61
|
+
throw new ConflictError('The clarity reviewer is not configured');
|
|
62
|
+
}
|
|
63
|
+
return deps.clarityReviewService;
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
agentKind: CLARITY_REVIEW_AGENT_KIND,
|
|
67
|
+
// Enabled whenever the clarity STORE is wired — the bug-triage seed/auto-pass path is
|
|
68
|
+
// deterministic (driven by the upstream investigator's structured triage) and needs no
|
|
69
|
+
// reviewer model, so the gate must activate even with no model configured. The LLM
|
|
70
|
+
// review/incorporate/re-review paths still resolve their own model (and degrade gracefully
|
|
71
|
+
// when unwired: no investigation + no model ⇒ the review closure auto-passes).
|
|
72
|
+
entityName: 'Clarity review',
|
|
73
|
+
enabled: () => !!deps.clarityReviewService,
|
|
74
|
+
getForBlock: (ws, blockId) => require().getForBlock(ws, blockId),
|
|
75
|
+
review: async (ws, block, preset) => {
|
|
76
|
+
const svc = require();
|
|
77
|
+
const structured = await structuredInvestigationForBlock(deps, ws, block.id);
|
|
78
|
+
let review;
|
|
79
|
+
if (structured) {
|
|
80
|
+
// An upstream structured `bug-investigator`: seed the gate from its triage — NO reviewer
|
|
81
|
+
// LLM. `clear` → auto-pass; `needs_clarification` → one blocking finding per question.
|
|
82
|
+
// The investigator explicitly asked for clarification, so those questions ALWAYS park
|
|
83
|
+
// for a human — the requirements-review concern tolerance (`maxRequirementConcernAllowed`,
|
|
84
|
+
// which governs the requirements reviewer, not bug triage) must not silently auto-pass
|
|
85
|
+
// them — hence a fixed `none` threshold here rather than the preset's.
|
|
86
|
+
review = await svc.seedReview(ws, block.id, {
|
|
87
|
+
clarity: structured.clarity,
|
|
88
|
+
questions: structured.questions,
|
|
89
|
+
maxIterations: preset.maxRequirementIterations,
|
|
90
|
+
concernThreshold: 'none',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else if (!svc.enabled) {
|
|
94
|
+
// No structured investigation and no reviewer model: nothing to review against, so
|
|
95
|
+
// auto-pass (equivalent to the old pass-through when the reviewer wasn't configured).
|
|
96
|
+
review = await svc.seedReview(ws, block.id, {
|
|
97
|
+
clarity: 'clear',
|
|
98
|
+
questions: [],
|
|
99
|
+
maxIterations: preset.maxRequirementIterations,
|
|
100
|
+
concernThreshold: preset.maxRequirementConcernAllowed,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
review = await svc.review(ws, block.id, {
|
|
105
|
+
maxIterations: preset.maxRequirementIterations,
|
|
106
|
+
concernThreshold: preset.maxRequirementConcernAllowed,
|
|
107
|
+
investigation: await investigationForBlock(deps, ws, block.id),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Whenever the gate parks with open questions — from the deterministic seed OR the LLM
|
|
111
|
+
// reviewer — best-effort echo them onto the linked tracker issue (answers still arrive
|
|
112
|
+
// in-app). A settled/auto-passed review echoes nothing; a tracker outage never fails the run.
|
|
113
|
+
await echoClarityQuestions(deps, ws, block.id, review);
|
|
114
|
+
return review;
|
|
115
|
+
},
|
|
116
|
+
reReview: async (ws, reviewId, preset) => {
|
|
117
|
+
const svc = require();
|
|
118
|
+
// No reviewer model wired: a re-review can't run, so settle the loop (converge) instead of
|
|
119
|
+
// throwing — the deterministic seed path can reach a park with no model configured.
|
|
120
|
+
if (!svc.enabled)
|
|
121
|
+
return svc.markIncorporated(ws, reviewId);
|
|
122
|
+
return svc.reReview(ws, reviewId, { concernThreshold: preset.maxRequirementConcernAllowed });
|
|
123
|
+
},
|
|
124
|
+
incorporate: async (ws, blockId, reviewId, feedback) => {
|
|
125
|
+
const svc = require();
|
|
126
|
+
// No reviewer model: can't LLM-fold the answers into a clarified report, so settle the
|
|
127
|
+
// review as-is (the run advances on the raw report + the recorded answers) instead of
|
|
128
|
+
// throwing — keeps the model-free seed path resolvable.
|
|
129
|
+
if (!svc.enabled) {
|
|
130
|
+
await svc.markIncorporated(ws, reviewId);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const investigation = await investigationForBlock(deps, ws, blockId);
|
|
134
|
+
await svc.incorporate(ws, reviewId, { feedback, investigation });
|
|
135
|
+
},
|
|
136
|
+
markIncorporated: (ws, reviewId) => require().markIncorporated(ws, reviewId),
|
|
137
|
+
markReReviewing: (ws, reviewId) => require().markReReviewing(ws, reviewId),
|
|
138
|
+
markIncorporating: (ws, reviewId) => require().markIncorporating(ws, reviewId),
|
|
139
|
+
grantExtraRound: (ws, reviewId) => require().grantExtraRound(ws, reviewId),
|
|
140
|
+
emit: (ws, review) => deps.events.clarityReviewChanged?.(ws, review) ?? Promise.resolve(),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* A brainstorm (structured-dialogue) subject for the review gate, parameterised by stage.
|
|
145
|
+
* Otherwise identical to the requirements kind — the service handles its own upstream context
|
|
146
|
+
* (the architecture stage seeds from the refined requirements). The brainstorm services
|
|
147
|
+
* resolve their model exactly like the requirements reviewer, so the cap knobs are reused.
|
|
148
|
+
*/
|
|
149
|
+
export function buildBrainstormKind(stage, agentKind, deps) {
|
|
150
|
+
const require = () => {
|
|
151
|
+
const svc = deps.brainstormServices?.[stage];
|
|
152
|
+
if (!svc?.enabled)
|
|
153
|
+
throw new ConflictError('The brainstorm agent is not configured');
|
|
154
|
+
return svc;
|
|
155
|
+
};
|
|
156
|
+
return {
|
|
157
|
+
agentKind,
|
|
158
|
+
entityName: 'Brainstorm session',
|
|
159
|
+
enabled: () => !!deps.brainstormServices?.[stage]?.enabled,
|
|
160
|
+
getForBlock: (ws, blockId) => require().getForBlock(ws, blockId),
|
|
161
|
+
review: (ws, block, preset) => require().review(ws, block.id, {
|
|
162
|
+
maxIterations: preset.maxRequirementIterations,
|
|
163
|
+
concernThreshold: preset.maxRequirementConcernAllowed,
|
|
164
|
+
}),
|
|
165
|
+
reReview: (ws, reviewId, preset) => require().reReview(ws, reviewId, { concernThreshold: preset.maxRequirementConcernAllowed }),
|
|
166
|
+
incorporate: async (ws, _blockId, reviewId, feedback) => {
|
|
167
|
+
await require().incorporate(ws, reviewId, { feedback });
|
|
168
|
+
},
|
|
169
|
+
markIncorporated: (ws, reviewId) => require().markIncorporated(ws, reviewId),
|
|
170
|
+
markReReviewing: (ws, reviewId) => require().markReReviewing(ws, reviewId),
|
|
171
|
+
markIncorporating: (ws, reviewId) => require().markIncorporating(ws, reviewId),
|
|
172
|
+
grantExtraRound: (ws, reviewId) => require().grantExtraRound(ws, reviewId),
|
|
173
|
+
emit: (ws, session) => deps.events.brainstormSessionChanged?.(ws, session) ?? Promise.resolve(),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// ---- clarity-review context helpers (bug-report triage) ------------------
|
|
177
|
+
// The clarity gate triages a block's bug report — optionally enriched by an upstream
|
|
178
|
+
// `bug-investigator` step's prose output — through the SAME ReviewGateController flow as
|
|
179
|
+
// requirements; these helpers resolve that investigator output as the triage subject,
|
|
180
|
+
// threaded into the clarity {@link ReviewKind}.
|
|
181
|
+
/** The latest `bug-investigator` step output on a run (the triage subject), or undefined. */
|
|
182
|
+
function investigationFor(instance) {
|
|
183
|
+
for (let i = instance.steps.length - 1; i >= 0; i--) {
|
|
184
|
+
const s = instance.steps[i];
|
|
185
|
+
if (s.agentKind === BUG_INVESTIGATOR_AGENT_KIND && s.output)
|
|
186
|
+
return s.output;
|
|
187
|
+
}
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
/** Resolve a block's investigator output via its current execution (off the gate path). */
|
|
191
|
+
async function investigationForBlock(deps, workspaceId, blockId) {
|
|
192
|
+
const block = await deps.blockRepository.get(workspaceId, blockId);
|
|
193
|
+
if (!block?.executionId)
|
|
194
|
+
return undefined;
|
|
195
|
+
const instance = await deps.executionRepository.get(workspaceId, block.executionId);
|
|
196
|
+
return instance ? investigationFor(instance) : undefined;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The latest `bug-investigator` step's STRUCTURED triage on a run — its `clarity` verdict +
|
|
200
|
+
* `questions` — parsed leniently from `step.custom`. Drives the clarity gate's seed/auto-pass
|
|
201
|
+
* (see {@link buildClarityKind}): a structured investigator upstream means the gate seeds its
|
|
202
|
+
* findings from `questions` (or auto-passes on `clarity === 'clear'`) instead of running its
|
|
203
|
+
* own reviewer LLM. Undefined when no investigator ran or its result wasn't structured (an
|
|
204
|
+
* older prose investigator, or an unparseable reply) — the gate then falls back to the LLM path.
|
|
205
|
+
*/
|
|
206
|
+
function structuredInvestigationFor(instance) {
|
|
207
|
+
for (let i = instance.steps.length - 1; i >= 0; i--) {
|
|
208
|
+
const s = instance.steps[i];
|
|
209
|
+
if (s.agentKind !== BUG_INVESTIGATOR_AGENT_KIND || s.custom === undefined)
|
|
210
|
+
continue;
|
|
211
|
+
const parsed = bugInvestigation.safeParse(s.custom);
|
|
212
|
+
if (!parsed)
|
|
213
|
+
return undefined;
|
|
214
|
+
return { clarity: parsed.clarity, questions: parsed.questions };
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
/** Resolve a block's structured investigator triage via its current execution. */
|
|
219
|
+
async function structuredInvestigationForBlock(deps, workspaceId, blockId) {
|
|
220
|
+
const block = await deps.blockRepository.get(workspaceId, blockId);
|
|
221
|
+
if (!block?.executionId)
|
|
222
|
+
return undefined;
|
|
223
|
+
const instance = await deps.executionRepository.get(workspaceId, block.executionId);
|
|
224
|
+
return instance ? structuredInvestigationFor(instance) : undefined;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Best-effort echo of a parked clarity review's open questions onto the block's linked tracker
|
|
228
|
+
* issue (see {@link IssueWritebackProvider.postQuestions}). Fires for BOTH the deterministic
|
|
229
|
+
* investigator seed and the LLM reviewer, so identical human-parked states behave the same. A
|
|
230
|
+
* settled/auto-passed review (status `incorporated`) or one with no open items echoes nothing,
|
|
231
|
+
* and a tracker outage never fails the run.
|
|
232
|
+
*/
|
|
233
|
+
async function echoClarityQuestions(deps, workspaceId, blockId, review) {
|
|
234
|
+
if (!deps.issueWriteback || review.status === 'incorporated')
|
|
235
|
+
return;
|
|
236
|
+
const questions = review.items.filter((i) => i.status === 'open').map((i) => i.detail);
|
|
237
|
+
if (questions.length === 0)
|
|
238
|
+
return;
|
|
239
|
+
await deps.issueWriteback.postQuestions(workspaceId, blockId, questions).catch(() => { });
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=review-kinds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-kinds.js","sourceRoot":"","sources":["../../../src/modules/execution/review-kinds.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,14 @@ export declare const MAX_AGENT_CONTEXT_CHARS: number;
|
|
|
16
16
|
* prompts first), so the most useful context survives when the budget is reached.
|
|
17
17
|
*/
|
|
18
18
|
export declare const MAX_AGENT_CONTEXT_TOTAL_CHARS: number;
|
|
19
|
+
/**
|
|
20
|
+
* Stored in place of a secret-bearing file's body. A file whose NAME marks it as a raw
|
|
21
|
+
* credential store (`.env`, `*.pem`, an SSH key, `.npmrc`, …) has no field-name/URL
|
|
22
|
+
* scaffolding for {@link redactSecrets}'s pattern rules to latch onto — a bare PEM block or
|
|
23
|
+
* a `KEY=value` dump would pass through the shape scrub verbatim — so its whole body is
|
|
24
|
+
* dropped rather than persisted.
|
|
25
|
+
*/
|
|
26
|
+
export declare const SECRET_FILE_PLACEHOLDER = "[REDACTED: secret-shaped file omitted from snapshot]";
|
|
19
27
|
export interface AgentContextObservabilityServiceDependencies {
|
|
20
28
|
agentContextSnapshotRepository: AgentContextSnapshotRepository;
|
|
21
29
|
workspaceSettingsRepository: WorkspaceSettingsRepository;
|
|
@@ -53,8 +61,22 @@ export declare class AgentContextObservabilityService implements AgentContextRec
|
|
|
53
61
|
/**
|
|
54
62
|
* Persist one dispatch's context, assigning its id + timestamp. Returns without
|
|
55
63
|
* storing when prompt recording is disabled deployment-wide or the workspace has
|
|
56
|
-
* turned `storeAgentContext` off.
|
|
57
|
-
*
|
|
64
|
+
* turned `storeAgentContext` off.
|
|
65
|
+
*
|
|
66
|
+
* Every stored body is a defence-in-depth SECRET SCRUB before it lands in the telemetry
|
|
67
|
+
* store: prompts, fragment bodies and injected file contents run through
|
|
68
|
+
* {@link redactSecrets} (a value the dispatch site's allow-list can't fully guarantee is
|
|
69
|
+
* clean — a task description, a linked doc, or an injected file may embed a token), and a
|
|
70
|
+
* file whose NAME marks it as a raw credential store ({@link isSecretShapedFilename}) has
|
|
71
|
+
* its whole body dropped ({@link SECRET_FILE_PLACEHOLDER}), since a bare PEM/`.env` body
|
|
72
|
+
* has no scaffolding for the shape rules to catch. Scrub happens BEFORE the size budget so
|
|
73
|
+
* truncation can never split a secret across the cap and defeat the pattern match. Bodies
|
|
74
|
+
* are then clamped so an oversized prompt/file never drops the whole snapshot.
|
|
75
|
+
*
|
|
76
|
+
* The `extras` bag is deep-scrubbed too ({@link redactSecretsDeep}): several of its values
|
|
77
|
+
* are human-authored free text (the run's decisions, revision feedback) — the SAME token-
|
|
78
|
+
* in-prose risk as a task description — so every string it carries at any depth is scrubbed
|
|
79
|
+
* rather than trusting the dispatch-site allow-list to have kept it clean.
|
|
58
80
|
*/
|
|
59
81
|
record(input: RecordAgentContextInput): Promise<void>;
|
|
60
82
|
/** Snapshots recorded for a run, newest first (for the observability drill-down). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentContextObservabilityService.d.ts","sourceRoot":"","sources":["../../../src/modules/observability/AgentContextObservabilityService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,KAAK,EACL,WAAW,EACX,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"AgentContextObservabilityService.d.ts","sourceRoot":"","sources":["../../../src/modules/observability/AgentContextObservabilityService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,KAAK,EACL,WAAW,EACX,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAA;AAQ5B;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAAa,CAAA;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,QAAkB,CAAA;AAO5D;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,yDAAyD,CAAA;AAuB7F,MAAM,WAAW,4CAA4C;IAC3D,8BAA8B,EAAE,8BAA8B,CAAA;IAC9D,2BAA2B,EAAE,2BAA2B,CAAA;IACxD,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,gCAAiC,YAAW,oBAAoB;IAC3E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgC;IAC3D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC,YAAY,EACV,8BAA8B,EAC9B,2BAA2B,EAC3B,WAAW,EACX,KAAK,EACL,aAAoB,GACrB,EAAE,4CAA4C,EAM9C;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACG,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B1D;IAED,qFAAqF;IACrF,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAEzF;YAEa,YAAY;CAI3B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_WORKSPACE_SETTINGS } from '@cat-factory/kernel';
|
|
1
|
+
import { DEFAULT_WORKSPACE_SETTINGS, isSecretShapedFilename, redactSecrets, redactSecretsDeep, } from '@cat-factory/kernel';
|
|
2
2
|
/**
|
|
3
3
|
* Defensive upper bound (characters) on any single stored body — a prompt or one
|
|
4
4
|
* injected file. Real agent context sits far below this; the cap exists only so a
|
|
@@ -21,6 +21,14 @@ function clamp(text) {
|
|
|
21
21
|
return text;
|
|
22
22
|
return `${text.slice(0, MAX_AGENT_CONTEXT_CHARS)}\n…[truncated ${text.length - MAX_AGENT_CONTEXT_CHARS} chars]`;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Stored in place of a secret-bearing file's body. A file whose NAME marks it as a raw
|
|
26
|
+
* credential store (`.env`, `*.pem`, an SSH key, `.npmrc`, …) has no field-name/URL
|
|
27
|
+
* scaffolding for {@link redactSecrets}'s pattern rules to latch onto — a bare PEM block or
|
|
28
|
+
* a `KEY=value` dump would pass through the shape scrub verbatim — so its whole body is
|
|
29
|
+
* dropped rather than persisted.
|
|
30
|
+
*/
|
|
31
|
+
export const SECRET_FILE_PLACEHOLDER = '[REDACTED: secret-shaped file omitted from snapshot]';
|
|
24
32
|
/**
|
|
25
33
|
* A shared character budget for one snapshot. Each call first applies the per-body cap,
|
|
26
34
|
* then trims against the remaining aggregate budget — so the bodies passed earlier (the
|
|
@@ -71,8 +79,22 @@ export class AgentContextObservabilityService {
|
|
|
71
79
|
/**
|
|
72
80
|
* Persist one dispatch's context, assigning its id + timestamp. Returns without
|
|
73
81
|
* storing when prompt recording is disabled deployment-wide or the workspace has
|
|
74
|
-
* turned `storeAgentContext` off.
|
|
75
|
-
*
|
|
82
|
+
* turned `storeAgentContext` off.
|
|
83
|
+
*
|
|
84
|
+
* Every stored body is a defence-in-depth SECRET SCRUB before it lands in the telemetry
|
|
85
|
+
* store: prompts, fragment bodies and injected file contents run through
|
|
86
|
+
* {@link redactSecrets} (a value the dispatch site's allow-list can't fully guarantee is
|
|
87
|
+
* clean — a task description, a linked doc, or an injected file may embed a token), and a
|
|
88
|
+
* file whose NAME marks it as a raw credential store ({@link isSecretShapedFilename}) has
|
|
89
|
+
* its whole body dropped ({@link SECRET_FILE_PLACEHOLDER}), since a bare PEM/`.env` body
|
|
90
|
+
* has no scaffolding for the shape rules to catch. Scrub happens BEFORE the size budget so
|
|
91
|
+
* truncation can never split a secret across the cap and defeat the pattern match. Bodies
|
|
92
|
+
* are then clamped so an oversized prompt/file never drops the whole snapshot.
|
|
93
|
+
*
|
|
94
|
+
* The `extras` bag is deep-scrubbed too ({@link redactSecretsDeep}): several of its values
|
|
95
|
+
* are human-authored free text (the run's decisions, revision feedback) — the SAME token-
|
|
96
|
+
* in-prose risk as a task description — so every string it carries at any depth is scrubbed
|
|
97
|
+
* rather than trusting the dispatch-site allow-list to have kept it clean.
|
|
76
98
|
*/
|
|
77
99
|
async record(input) {
|
|
78
100
|
if (!this.recordPrompts)
|
|
@@ -82,14 +104,24 @@ export class AgentContextObservabilityService {
|
|
|
82
104
|
// One shared budget per snapshot, consumed prompts-first so the most useful context
|
|
83
105
|
// survives if a dispatch injects an unusual amount of file content.
|
|
84
106
|
const budget = makeBudget();
|
|
107
|
+
// Scrub credentials, THEN clamp — a truncated body must never hide a half-cut secret.
|
|
108
|
+
const scrub = (text) => budget(redactSecrets(text) ?? '');
|
|
85
109
|
const snapshot = {
|
|
86
110
|
...input,
|
|
87
111
|
id: this.idGenerator.next('ctx'),
|
|
88
112
|
createdAt: this.clock.now(),
|
|
89
|
-
systemPrompt:
|
|
90
|
-
userPrompt:
|
|
91
|
-
fragments: input.fragments.map((f) => ({ id: f.id, body:
|
|
92
|
-
contextFiles: input.contextFiles.map((f) => ({
|
|
113
|
+
systemPrompt: scrub(input.systemPrompt),
|
|
114
|
+
userPrompt: scrub(input.userPrompt),
|
|
115
|
+
fragments: input.fragments.map((f) => ({ id: f.id, body: scrub(f.body) })),
|
|
116
|
+
contextFiles: input.contextFiles.map((f) => ({
|
|
117
|
+
...f,
|
|
118
|
+
content: isSecretShapedFilename(f.path)
|
|
119
|
+
? budget(SECRET_FILE_PLACEHOLDER)
|
|
120
|
+
: scrub(f.content),
|
|
121
|
+
})),
|
|
122
|
+
// Structural bits, but some values (decisions, revision feedback) are free-text prose
|
|
123
|
+
// that can embed a token — scrub every string in the bag, not just the known bodies.
|
|
124
|
+
extras: redactSecretsDeep(input.extras),
|
|
93
125
|
};
|
|
94
126
|
await this.repository.record(snapshot);
|
|
95
127
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentContextObservabilityService.js","sourceRoot":"","sources":["../../../src/modules/observability/AgentContextObservabilityService.ts"],"names":[],"mappings":"AASA,OAAO,
|
|
1
|
+
{"version":3,"file":"AgentContextObservabilityService.js","sourceRoot":"","sources":["../../../src/modules/observability/AgentContextObservabilityService.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/orchestration",
|
|
3
|
-
"version": "0.123.
|
|
3
|
+
"version": "0.123.5",
|
|
4
4
|
"description": "Delivery-workflow engine for the Agent Architecture Board (execution, bootstrap, pipelines, board, boardScan, requirements, and composition root).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,20 +25,20 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"ai": "^6.0.230",
|
|
28
|
-
"@cat-factory/agents": "0.62.
|
|
29
|
-
"@cat-factory/caching": "0.10.
|
|
30
|
-
"@cat-factory/contracts": "0.148.
|
|
31
|
-
"@cat-factory/integrations": "0.86.
|
|
32
|
-
"@cat-factory/kernel": "0.
|
|
33
|
-
"@cat-factory/prompt-fragments": "0.13.
|
|
34
|
-
"@cat-factory/sandbox": "0.9.
|
|
35
|
-
"@cat-factory/spend": "0.12.
|
|
36
|
-
"@cat-factory/workspaces": "0.16.
|
|
28
|
+
"@cat-factory/agents": "0.62.12",
|
|
29
|
+
"@cat-factory/caching": "0.10.9",
|
|
30
|
+
"@cat-factory/contracts": "0.148.1",
|
|
31
|
+
"@cat-factory/integrations": "0.86.4",
|
|
32
|
+
"@cat-factory/kernel": "0.140.0",
|
|
33
|
+
"@cat-factory/prompt-fragments": "0.13.39",
|
|
34
|
+
"@cat-factory/sandbox": "0.9.103",
|
|
35
|
+
"@cat-factory/spend": "0.12.53",
|
|
36
|
+
"@cat-factory/workspaces": "0.16.6"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"typescript": "7.0.2",
|
|
40
40
|
"vitest": "^4.1.10",
|
|
41
|
-
"@cat-factory/sandbox-fixtures": "0.7.
|
|
41
|
+
"@cat-factory/sandbox-fixtures": "0.7.174"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsc -b tsconfig.build.json",
|