@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.
Files changed (29) hide show
  1. package/dist/modules/execution/DeployerStepController.d.ts +185 -0
  2. package/dist/modules/execution/DeployerStepController.d.ts.map +1 -0
  3. package/dist/modules/execution/DeployerStepController.js +670 -0
  4. package/dist/modules/execution/DeployerStepController.js.map +1 -0
  5. package/dist/modules/execution/ExecutionService.d.ts +8 -211
  6. package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
  7. package/dist/modules/execution/ExecutionService.js +59 -805
  8. package/dist/modules/execution/ExecutionService.js.map +1 -1
  9. package/dist/modules/execution/FollowUpGateController.d.ts +104 -0
  10. package/dist/modules/execution/FollowUpGateController.d.ts.map +1 -0
  11. package/dist/modules/execution/FollowUpGateController.js +317 -0
  12. package/dist/modules/execution/FollowUpGateController.js.map +1 -0
  13. package/dist/modules/execution/RunAdmission.d.ts +204 -0
  14. package/dist/modules/execution/RunAdmission.d.ts.map +1 -0
  15. package/dist/modules/execution/RunAdmission.js +571 -0
  16. package/dist/modules/execution/RunAdmission.js.map +1 -0
  17. package/dist/modules/execution/RunDispatcher.d.ts +24 -196
  18. package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
  19. package/dist/modules/execution/RunDispatcher.js +70 -929
  20. package/dist/modules/execution/RunDispatcher.js.map +1 -1
  21. package/dist/modules/execution/review-kinds.d.ts +41 -0
  22. package/dist/modules/execution/review-kinds.d.ts.map +1 -0
  23. package/dist/modules/execution/review-kinds.js +241 -0
  24. package/dist/modules/execution/review-kinds.js.map +1 -0
  25. package/dist/modules/observability/AgentContextObservabilityService.d.ts +24 -2
  26. package/dist/modules/observability/AgentContextObservabilityService.d.ts.map +1 -1
  27. package/dist/modules/observability/AgentContextObservabilityService.js +39 -7
  28. package/dist/modules/observability/AgentContextObservabilityService.js.map +1 -1
  29. 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":"AAWA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAKtD,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,eAAe,CAAA;AAmBtB;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAoB;IACxD,MAAM,OAAO,GAAG,GAA6B,EAAE;QAC7C,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO,EAAE,CAAC;YAC5C,MAAM,IAAI,aAAa,CAAC,6CAA6C,CAAC,CAAA;QACxE,CAAC;QACD,OAAO,IAAI,CAAC,wBAAwB,CAAA;IACtC,CAAC,CAAA;IACD,OAAO;QACL,SAAS,EAAE,8BAA8B;QACzC,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO;QACvD,WAAW,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC;QAChE,MAAM,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAC5B,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;YAC7B,aAAa,EAAE,MAAM,CAAC,wBAAwB;YAC9C,gBAAgB,EAAE,MAAM,CAAC,4BAA4B;SACtD,CAAC;QACJ,QAAQ,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CACjC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,gBAAgB,EAAE,MAAM,CAAC,4BAA4B,EAAE,CAAC;QAC7F,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;YACtD,MAAM,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;QACzD,CAAC;QACD,gBAAgB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC5E,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC1E,iBAAiB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC9E,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC1E,sBAAsB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAC9C,OAAO,EAAE,CAAC,sBAAsB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC;QACvD,yBAAyB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CACvD,OAAO,EAAE,CAAC,yBAAyB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC;QAChE,mBAAmB,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;YACzC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;YACrB,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAA;YAC7F,MAAM,GAAG,CAAC,0BAA0B,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;gBAClD,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;aACtF,CAAC,CAAA;YACF,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAA;QACvF,CAAC;QACD,aAAa,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;YACrB,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAA;YAC7F,MAAM,GAAG,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;gBACrC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;aACtF,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;KAC9F,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAoB;IACnD,MAAM,OAAO,GAAG,GAAyB,EAAE;QACzC,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC/B,MAAM,IAAI,aAAa,CAAC,wCAAwC,CAAC,CAAA;QACnE,CAAC;QACD,OAAO,IAAI,CAAC,oBAAoB,CAAA;IAClC,CAAC,CAAA;IACD,OAAO;QACL,SAAS,EAAE,yBAAyB;QACpC,sFAAsF;QACtF,uFAAuF;QACvF,mFAAmF;QACnF,2FAA2F;QAC3F,+EAA+E;QAC/E,UAAU,EAAE,gBAAgB;QAC5B,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB;QAC1C,WAAW,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC;QAChE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAClC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;YACrB,MAAM,UAAU,GAAG,MAAM,+BAA+B,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;YAC5E,IAAI,MAAqB,CAAA;YACzB,IAAI,UAAU,EAAE,CAAC;gBACf,yFAAyF;gBACzF,uFAAuF;gBACvF,sFAAsF;gBACtF,2FAA2F;gBAC3F,uFAAuF;gBACvF,uEAAuE;gBACvE,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;oBAC1C,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,aAAa,EAAE,MAAM,CAAC,wBAAwB;oBAC9C,gBAAgB,EAAE,MAAM;iBACzB,CAAC,CAAA;YACJ,CAAC;iBAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBACxB,mFAAmF;gBACnF,sFAAsF;gBACtF,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;oBAC1C,OAAO,EAAE,OAAO;oBAChB,SAAS,EAAE,EAAE;oBACb,aAAa,EAAE,MAAM,CAAC,wBAAwB;oBAC9C,gBAAgB,EAAE,MAAM,CAAC,4BAA4B;iBACtD,CAAC,CAAA;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;oBACtC,aAAa,EAAE,MAAM,CAAC,wBAAwB;oBAC9C,gBAAgB,EAAE,MAAM,CAAC,4BAA4B;oBACrD,aAAa,EAAE,MAAM,qBAAqB,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC;iBAC/D,CAAC,CAAA;YACJ,CAAC;YACD,uFAAuF;YACvF,uFAAuF;YACvF,8FAA8F;YAC9F,MAAM,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;YACtD,OAAO,MAAM,CAAA;QACf,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE;YACvC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;YACrB,2FAA2F;YAC3F,oFAAoF;YACpF,IAAI,CAAC,GAAG,CAAC,OAAO;gBAAE,OAAO,GAAG,CAAC,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;YAC3D,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,gBAAgB,EAAE,MAAM,CAAC,4BAA4B,EAAE,CAAC,CAAA;QAC9F,CAAC;QACD,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;YACrD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;YACrB,uFAAuF;YACvF,sFAAsF;YACtF,wDAAwD;YACxD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjB,MAAM,GAAG,CAAC,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;gBACxC,OAAM;YACR,CAAC;YACD,MAAM,aAAa,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;YACpE,MAAM,GAAG,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAA;QAClE,CAAC;QACD,gBAAgB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC5E,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC1E,iBAAiB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC9E,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC1E,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;KAC1F,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAsB,EACtB,SAAiB,EACjB,IAAoB;IAEpB,MAAM,OAAO,GAAG,GAAsB,EAAE;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC,KAAK,CAAC,CAAA;QAC5C,IAAI,CAAC,GAAG,EAAE,OAAO;YAAE,MAAM,IAAI,aAAa,CAAC,wCAAwC,CAAC,CAAA;QACpF,OAAO,GAAG,CAAA;IACZ,CAAC,CAAA;IACD,OAAO;QACL,SAAS;QACT,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO;QAC1D,WAAW,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC;QAChE,MAAM,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAC5B,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;YAC7B,aAAa,EAAE,MAAM,CAAC,wBAAwB;YAC9C,gBAAgB,EAAE,MAAM,CAAC,4BAA4B;SACtD,CAAC;QACJ,QAAQ,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CACjC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,gBAAgB,EAAE,MAAM,CAAC,4BAA4B,EAAE,CAAC;QAC7F,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;YACtD,MAAM,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;QACzD,CAAC;QACD,gBAAgB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC5E,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC1E,iBAAiB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC9E,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC1E,IAAI,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;KAChG,CAAA;AACH,CAAC;AAED,6EAA6E;AAC7E,qFAAqF;AACrF,yFAAyF;AACzF,sFAAsF;AACtF,gDAAgD;AAEhD,6FAA6F;AAC7F,SAAS,gBAAgB,CAAC,QAA2B;IACnD,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAA;QAC5B,IAAI,CAAC,CAAC,SAAS,KAAK,2BAA2B,IAAI,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC,MAAM,CAAA;IAC9E,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,2FAA2F;AAC3F,KAAK,UAAU,qBAAqB,CAClC,IAAoB,EACpB,WAAmB,EACnB,OAAe;IAEf,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAClE,IAAI,CAAC,KAAK,EAAE,WAAW;QAAE,OAAO,SAAS,CAAA;IACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;IACnF,OAAO,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1D,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,0BAA0B,CACjC,QAA2B;IAE3B,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAA;QAC5B,IAAI,CAAC,CAAC,SAAS,KAAK,2BAA2B,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;YAAE,SAAQ;QACnF,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAA;QAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAA;IACjE,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,kFAAkF;AAClF,KAAK,UAAU,+BAA+B,CAC5C,IAAoB,EACpB,WAAmB,EACnB,OAAe;IAEf,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAClE,IAAI,CAAC,KAAK,EAAE,WAAW;QAAE,OAAO,SAAS,CAAA;IACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;IACnF,OAAO,QAAQ,CAAC,CAAC,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACpE,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,oBAAoB,CACjC,IAAoB,EACpB,WAAmB,EACnB,OAAe,EACf,MAAqB;IAErB,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc;QAAE,OAAM;IACpE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IACtF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAClC,MAAM,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;AAC1F,CAAC"}
@@ -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. Bodies are clamped so an oversized prompt/file
57
- * never drops the whole snapshot.
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;AAG5B;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAAa,CAAA;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,QAAkB,CAAA;AA4B5D,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;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB1D;IAED,qFAAqF;IACrF,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAEzF;YAEa,YAAY;CAI3B"}
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. Bodies are clamped so an oversized prompt/file
75
- * never drops the whole snapshot.
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: budget(input.systemPrompt),
90
- userPrompt: budget(input.userPrompt),
91
- fragments: input.fragments.map((f) => ({ id: f.id, body: budget(f.body) })),
92
- contextFiles: input.contextFiles.map((f) => ({ ...f, content: budget(f.content) })),
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":"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"}
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",
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.11",
29
- "@cat-factory/caching": "0.10.8",
30
- "@cat-factory/contracts": "0.148.0",
31
- "@cat-factory/integrations": "0.86.3",
32
- "@cat-factory/kernel": "0.139.3",
33
- "@cat-factory/prompt-fragments": "0.13.38",
34
- "@cat-factory/sandbox": "0.9.102",
35
- "@cat-factory/spend": "0.12.52",
36
- "@cat-factory/workspaces": "0.16.5"
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.173"
41
+ "@cat-factory/sandbox-fixtures": "0.7.174"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsc -b tsconfig.build.json",