@rhei-team/rhei 1.0.0-beta.0

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 (30) hide show
  1. package/README.md +1048 -0
  2. package/bin/rhei-mcp.js +3 -0
  3. package/dist/index.d.ts +12 -0
  4. package/dist/index.js +86366 -0
  5. package/dist/premium/contracts.d.ts +445 -0
  6. package/dist/premium/contracts.js +97 -0
  7. package/dist/vendor/rhei-core/briefs.js +1276 -0
  8. package/dist/vendor/rhei-core/codeAgent.js +615 -0
  9. package/dist/vendor/rhei-core/codeEditSession.js +293 -0
  10. package/dist/vendor/rhei-core/codeIntelligence.js +4287 -0
  11. package/dist/vendor/rhei-core/codeMarket.js +8946 -0
  12. package/dist/vendor/rhei-core/codeReviewIntelligence.js +5918 -0
  13. package/dist/vendor/rhei-core/codeSemantics.js +172427 -0
  14. package/dist/vendor/rhei-core/codeStory.js +667 -0
  15. package/dist/vendor/rhei-core/codeStrategyPlan.js +663 -0
  16. package/dist/vendor/rhei-core/codeTrail.js +2781 -0
  17. package/dist/vendor/rhei-core/codeWorkHandoff.js +281 -0
  18. package/dist/vendor/rhei-core/contextQuery.js +1119 -0
  19. package/dist/vendor/rhei-core/contextRouting.js +2052 -0
  20. package/dist/vendor/rhei-core/evidenceLedger.js +5336 -0
  21. package/dist/vendor/rhei-core/executionSafety.js +0 -0
  22. package/dist/vendor/rhei-core/goalIntelligence.js +2218 -0
  23. package/dist/vendor/rhei-core/model-lanes.js +75 -0
  24. package/dist/vendor/rhei-core/now.js +127 -0
  25. package/dist/vendor/rhei-core/package.json +29 -0
  26. package/dist/vendor/rhei-core/programPlan.js +3153 -0
  27. package/dist/vendor/rhei-core/search.js +196 -0
  28. package/dist/vendor/rhei-core/serviceIntelligence.js +1734 -0
  29. package/dist/vendor/rhei-core/workflowPlan.js +1660 -0
  30. package/package.json +41 -0
@@ -0,0 +1,2218 @@
1
+ // ../core/src/goalIntelligence/types.ts
2
+ var GOAL_INTELLIGENCE_SCHEMA_VERSION = 1;
3
+ var GOAL_INTELLIGENCE_COMPACT_REF_LIMIT = 12;
4
+ var GOAL_STEWARD_DECISION_VALUES = [
5
+ "continue_active_goal",
6
+ "replace_active_goal",
7
+ "branch_goal",
8
+ "start_goal",
9
+ "ask_for_goal_boundary"
10
+ ];
11
+ var GOAL_MEMORY_CANDIDATE_KIND_VALUES = [
12
+ "style_preference",
13
+ "code_rewrite_preference",
14
+ "outcome_pattern",
15
+ "lifecycle_file_pattern",
16
+ "lifecycle_worktask_pattern",
17
+ "validation_practice",
18
+ "risk_pattern",
19
+ "proof_requirement",
20
+ "review_process"
21
+ ];
22
+ var GOAL_MEMORY_CANDIDATE_SOURCE_KIND_VALUES = [
23
+ "goal_lifecycle",
24
+ "outcome_feedback",
25
+ "learn_from_outcome",
26
+ "preference_replay",
27
+ "pr_review",
28
+ "code_trail",
29
+ "om_entry",
30
+ "manual",
31
+ "goal_outcome_feedback",
32
+ "goal_lifecycle_observation",
33
+ "code_review",
34
+ "observational_memory",
35
+ "explicit"
36
+ ];
37
+ var GOAL_MEMORY_CANDIDATE_STATUS_VALUES = [
38
+ "candidate",
39
+ "needs_more_evidence",
40
+ "ready_for_review",
41
+ "rejected",
42
+ "promoted_to_learning",
43
+ "submitted_to_truth",
44
+ "truth_approved",
45
+ "truth_rejected"
46
+ ];
47
+ // ../core/src/goalIntelligence/candidateHelpers.ts
48
+ var GOAL_MEMORY_HASH_PREFIX = "goal-memory";
49
+ function buildGoalMemoryCandidateIdentityV1(args) {
50
+ const normalizedGoal = normalizeGoalMemoryTextV1(args.goal);
51
+ const goalHash = normalizedGoal ? `${GOAL_MEMORY_HASH_PREFIX}:goal:${stableHash(normalizedGoal)}` : undefined;
52
+ const sourceEventId = cleanString(args.sourceEventId) ?? firstString(args.sourceIds) ?? `${GOAL_MEMORY_HASH_PREFIX}:source-event:${stableHash({
53
+ sourceKind: args.sourceKind,
54
+ candidateKind: args.candidateKind,
55
+ title: normalizeGoalMemoryTextV1(args.title),
56
+ summary: normalizeGoalMemoryTextV1(args.summary),
57
+ goalHash,
58
+ goalSessionId: cleanString(args.goalSessionId),
59
+ targetRefs: normalizedStringSet(args.targetRefs),
60
+ filePaths: normalizedStringSet(args.filePaths),
61
+ evidenceRefs: normalizedStringSet(args.evidenceRefs),
62
+ observationRefs: normalizedStringSet(args.observationRefs),
63
+ taskRefs: normalizedStringSet(args.taskRefs)
64
+ })}`;
65
+ const sourceHash = `${GOAL_MEMORY_HASH_PREFIX}:source:${stableHash({
66
+ sourceKind: args.sourceKind,
67
+ sourceEventId,
68
+ sourceIds: normalizedStringSet(args.sourceIds),
69
+ candidateKind: args.candidateKind,
70
+ title: normalizeGoalMemoryTextV1(args.title),
71
+ summary: normalizeGoalMemoryTextV1(args.summary),
72
+ normalizedRule: normalizeGoalMemoryTextV1(args.normalizedRule),
73
+ goalHash,
74
+ goalSessionId: cleanString(args.goalSessionId),
75
+ filePaths: normalizedStringSet(args.filePaths),
76
+ targetRefs: normalizedStringSet(args.targetRefs),
77
+ evidenceRefs: normalizedStringSet(args.evidenceRefs),
78
+ observationRefs: normalizedStringSet(args.observationRefs),
79
+ taskRefs: normalizedStringSet(args.taskRefs),
80
+ serviceConnectionIds: normalizedStringSet(args.serviceConnectionIds)
81
+ })}`;
82
+ const dedupeKey = `${GOAL_MEMORY_HASH_PREFIX}:dedupe:${stableHash({
83
+ sourceKind: args.sourceKind,
84
+ candidateKind: args.candidateKind,
85
+ goalHash: goalHash ?? cleanString(args.goalSessionId),
86
+ goalSessionId: cleanString(args.goalSessionId),
87
+ activeGoalId: cleanString(args.activeGoalId),
88
+ parentGoalId: cleanString(args.parentGoalId),
89
+ supersedesGoalId: cleanString(args.supersedesGoalId),
90
+ filePaths: normalizedStringSet(args.filePaths),
91
+ targetRefs: normalizedStringSet(args.targetRefs),
92
+ normalizedRule: normalizeGoalMemoryTextV1(args.normalizedRule ?? args.summary ?? args.title),
93
+ serviceConnectionIds: normalizedStringSet(args.serviceConnectionIds)
94
+ })}`;
95
+ return {
96
+ candidateId: `${GOAL_MEMORY_HASH_PREFIX}:candidate:${stableHash(dedupeKey)}`,
97
+ dedupeKey,
98
+ sourceHash,
99
+ sourceEventId,
100
+ goalHash
101
+ };
102
+ }
103
+ function normalizeGoalMemoryTextV1(value) {
104
+ const text = cleanString(value);
105
+ if (!text)
106
+ return;
107
+ return text.toLowerCase().replace(/\s+/g, " ").trim();
108
+ }
109
+ function collectGoalMemoryFilePathsV1(values) {
110
+ return uniqueStrings(values.flatMap((value) => stringList(value)).filter(looksLikeFilePath));
111
+ }
112
+ function goalMemoryCandidateSourceIdsV1(values) {
113
+ return uniqueStrings(values.flatMap((value) => stringList(value))).slice(0, 24);
114
+ }
115
+ function normalizedStringSet(values) {
116
+ return uniqueStrings(values ?? []).map((value) => normalizeGoalMemoryTextV1(value) ?? value).sort();
117
+ }
118
+ function firstString(values) {
119
+ return uniqueStrings(values ?? [])[0];
120
+ }
121
+ function stringList(value) {
122
+ if (Array.isArray(value))
123
+ return value.map((item) => cleanString(item)).filter((item) => Boolean(item));
124
+ const text = cleanString(value);
125
+ return text ? [text] : [];
126
+ }
127
+ function uniqueStrings(values) {
128
+ return Array.from(new Set(values.map((value) => value?.trim()).filter((value) => Boolean(value))));
129
+ }
130
+ function looksLikeFilePath(value) {
131
+ if (!value.includes("/"))
132
+ return false;
133
+ if (/^(https?:|git:|diff:|trail:|vitest:|test:|validation:|receipt:|goal:|goal-session:|service:)/i.test(value))
134
+ return false;
135
+ return /\.[a-z0-9]+($|[:#])/i.test(value) || value.startsWith("packages/") || value.startsWith("apps/") || value.startsWith("convex/") || value.startsWith("docs/") || value.startsWith("src/");
136
+ }
137
+ function cleanString(value) {
138
+ if (typeof value !== "string")
139
+ return;
140
+ const text = value.trim();
141
+ return text.length > 0 ? text : undefined;
142
+ }
143
+ function stableHash(value) {
144
+ const text = stableJson(value);
145
+ let hash = 2166136261;
146
+ for (let index = 0;index < text.length; index += 1) {
147
+ hash ^= text.charCodeAt(index);
148
+ hash = Math.imul(hash, 16777619);
149
+ }
150
+ return (hash >>> 0).toString(16).padStart(8, "0").slice(0, 12);
151
+ }
152
+ function stableJson(value) {
153
+ if (Array.isArray(value))
154
+ return `[${value.map(stableJson).join(",")}]`;
155
+ if (value && typeof value === "object") {
156
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`).join(",")}}`;
157
+ }
158
+ return JSON.stringify(value);
159
+ }
160
+ // ../core/src/goalIntelligence/builders.ts
161
+ var COMPACT_REF_LIMIT = 12;
162
+ var CLOSED_OUTCOMES = new Set(["accepted", "closed", "fixed", "passed", "pass"]);
163
+ var GOAL_INTELLIGENCE_GUARDRAILS = {
164
+ reportOnly: true,
165
+ advisoryOnly: true,
166
+ noAuthority: true,
167
+ noHiddenExecution: true,
168
+ noProviderCalls: true,
169
+ noGraphMutation: true,
170
+ noMemoryPromotion: true,
171
+ noTranscriptReplay: true,
172
+ noServiceWrite: true,
173
+ memoryPromotionRequiresExplicitPath: true,
174
+ compactContinuityOnly: true,
175
+ serviceConnectionsAreEvidenceOnly: true,
176
+ appendRequiresExplicitIntent: true
177
+ };
178
+ function buildGoalIntelligenceGuardrailsV1() {
179
+ return { ...GOAL_INTELLIGENCE_GUARDRAILS };
180
+ }
181
+ function buildGoalSessionV1({ args, goal }) {
182
+ const session = asRecord(args["goalSession"]) ?? {};
183
+ const steering = asRecord(args["steering"]) ?? {};
184
+ const goalSessionId = cleanString2(session["goalSessionId"]) ?? cleanString2(steering["goalSessionId"]) ?? cleanString2(args["goalSessionId"]);
185
+ const activeGoalId = cleanString2(session["activeGoalId"]) ?? cleanString2(steering["activeGoalId"]) ?? cleanString2(args["activeGoalId"]);
186
+ const incomingGoalId = cleanString2(session["incomingGoalId"]) ?? cleanString2(steering["incomingGoalId"]) ?? cleanString2(args["incomingGoalId"]);
187
+ const parentGoalId = cleanString2(session["parentGoalId"]) ?? cleanString2(steering["parentGoalId"]) ?? activeGoalId;
188
+ const supersedesGoalId = cleanString2(session["supersedesGoalId"]) ?? cleanString2(steering["supersedesGoalId"]);
189
+ const activeGoal = cleanString2(session["activeGoal"]) ?? cleanString2(steering["activeGoal"]) ?? cleanString2(args["activeGoal"]);
190
+ const incomingGoal = cleanString2(session["incomingGoal"]) ?? cleanString2(steering["incomingGoal"]) ?? goal;
191
+ return removeUndefined({
192
+ schemaVersion: 1,
193
+ kind: "goal_session",
194
+ goalSessionId,
195
+ activeGoalId,
196
+ incomingGoalId,
197
+ parentGoalId,
198
+ supersedesGoalId,
199
+ activeGoal,
200
+ incomingGoal,
201
+ contextRunIds: uniqueStrings2(stringList2(session["contextRunIds"])),
202
+ codeMarketSnapshotIds: uniqueStrings2(stringList2(session["codeMarketSnapshotIds"])),
203
+ codeWorkroomSessionId: cleanString2(session["codeWorkroomSessionId"]),
204
+ codeTrailRefs: uniqueStrings2(stringList2(session["codeTrailRefs"])),
205
+ prReviewRefs: uniqueStrings2(stringList2(session["prReviewRefs"])),
206
+ commitRefs: uniqueStrings2(stringList2(session["commitRefs"])),
207
+ validationRefs: uniqueStrings2(stringList2(session["validationRefs"])),
208
+ outcomeFeedbackRefs: uniqueStrings2(stringList2(session["outcomeFeedbackRefs"])),
209
+ serviceConnectionIds: uniqueStrings2(stringList2(session["serviceConnectionIds"])),
210
+ staleRefs: uniqueStrings2(stringList2(session["staleRefs"])),
211
+ openQuestions: uniqueStrings2(stringList2(session["openQuestions"])),
212
+ completedSteps: uniqueStrings2(stringList2(session["completedSteps"])),
213
+ remainingSteps: uniqueStrings2(stringList2(session["remainingSteps"])),
214
+ boundaryPolicy: "new_goal_requires_explicit_steer_decision",
215
+ refsOnly: true,
216
+ ...buildGoalIntelligenceGuardrailsV1()
217
+ });
218
+ }
219
+ function goalSessionHasContinuityV1(goalSession) {
220
+ if (!goalSession)
221
+ return false;
222
+ return [
223
+ "completedSteps",
224
+ "remainingSteps",
225
+ "contextRunIds",
226
+ "codeMarketSnapshotIds",
227
+ "codeTrailRefs",
228
+ "prReviewRefs",
229
+ "commitRefs",
230
+ "validationRefs",
231
+ "outcomeFeedbackRefs",
232
+ "staleRefs",
233
+ "openQuestions"
234
+ ].some((field) => stringList2(goalSession[field]).length > 0);
235
+ }
236
+ function collectGoalServiceConnectionIdsV1(args) {
237
+ const outcomeFeedback = asRecord(args["outcomeFeedback"]);
238
+ const steering = asRecord(args["steering"]);
239
+ const intelligenceCommit = asRecord(args["intelligenceCommit"]);
240
+ const preferenceReplay = asRecord(args["preferenceReplay"]);
241
+ const diagnosticClosure = asRecord(args["diagnosticClosure"]);
242
+ const serviceImpact = asRecord(args["serviceImpact"]);
243
+ return uniqueStrings2([
244
+ ...stringList2(args["serviceConnectionIds"]),
245
+ ...stringList2(outcomeFeedback?.["serviceConnectionIds"]),
246
+ ...stringList2(steering?.["serviceConnectionIds"]),
247
+ ...stringList2(intelligenceCommit?.["serviceConnectionIds"]),
248
+ ...stringList2(preferenceReplay?.["serviceConnectionIds"]),
249
+ ...stringList2(diagnosticClosure?.["serviceConnectionIds"]),
250
+ ...stringList2(serviceImpact?.["serviceConnectionIds"]),
251
+ ...serviceConnectionIdsFromEvidence(args["serviceConnections"])
252
+ ]);
253
+ }
254
+ function buildGoalOutcomeFeedbackV1({ args, goal, serviceConnectionIds }) {
255
+ const feedback = asRecord(args["outcomeFeedback"]) ?? {};
256
+ const correctionKind = cleanString2(feedback["correctionKind"]) ?? cleanString2(feedback["kind"]) ?? inferCorrectionKind(feedback);
257
+ const outcome = cleanString2(feedback["outcome"]) ?? cleanString2(feedback["status"]);
258
+ const before = cleanString2(feedback["before"]) ?? cleanString2(feedback["original"]);
259
+ const after = cleanString2(feedback["after"]) ?? cleanString2(feedback["rewrite"]) ?? cleanString2(feedback["humanRewrite"]) ?? cleanString2(feedback["corrected"]);
260
+ const stylePreference = cleanString2(feedback["stylePreference"]) ?? cleanString2(feedback["preference"]);
261
+ const rationale = cleanString2(feedback["rationale"]) ?? cleanString2(feedback["reason"]);
262
+ const acceptedRefs = collectAcceptedRefsV1(args, feedback);
263
+ const rejectedRefs = collectRejectedRefsV1(args, feedback);
264
+ const missingRefs = collectMissingRefsV1(args, feedback);
265
+ const evidenceRefs = uniqueStrings2([
266
+ ...stringList2(args["evidenceRefs"]),
267
+ ...stringList2(feedback["evidenceRefs"]),
268
+ ...acceptedRefs,
269
+ ...rejectedRefs,
270
+ ...missingRefs,
271
+ ...stringList2(args["exactRefs"])
272
+ ]);
273
+ const goalSession = asRecord(args["goalSession"]);
274
+ const outcomeFeedbackRefs = uniqueStrings2([
275
+ ...stringList2(args["outcomeFeedbackRefs"]),
276
+ ...stringList2(feedback["outcomeFeedbackRefs"])
277
+ ]);
278
+ const targetRefs = uniqueStrings2([
279
+ ...evidenceRefs,
280
+ ...stringList2(args["refs"]),
281
+ ...stringList2(args["refIds"]),
282
+ ...stringList2(args["selectedRefs"]),
283
+ ...stringList2(args["requiredRefs"]),
284
+ ...stringList2(args["candidateRefs"])
285
+ ]).slice(0, COMPACT_REF_LIMIT);
286
+ const filePaths = collectGoalMemoryFilePathsV1([
287
+ args["changedFiles"],
288
+ args["paths"],
289
+ args["files"],
290
+ args["exactRefs"],
291
+ acceptedRefs,
292
+ rejectedRefs,
293
+ missingRefs,
294
+ evidenceRefs
295
+ ]).slice(0, COMPACT_REF_LIMIT);
296
+ const taskRefs = uniqueStrings2([
297
+ ...stringList2(args["validationRefs"]),
298
+ ...stringList2(args["diffRefs"]),
299
+ ...stringList2(args["codeTrailRefs"]),
300
+ ...stringList2(args["prReviewRefs"]),
301
+ ...outcomeFeedbackRefs
302
+ ]).slice(0, COMPACT_REF_LIMIT);
303
+ const preferenceSignals = buildPreferenceSignals({ outcome, correctionKind, before, after, stylePreference, rationale, evidenceRefs });
304
+ const memoryCandidates = buildOutcomeMemoryCandidates({
305
+ goal,
306
+ goalSessionId: cleanString2(goalSession?.["goalSessionId"]),
307
+ activeGoalId: cleanString2(goalSession?.["activeGoalId"]),
308
+ parentGoalId: cleanString2(goalSession?.["parentGoalId"]),
309
+ supersedesGoalId: cleanString2(goalSession?.["supersedesGoalId"]),
310
+ correctionKind,
311
+ outcome,
312
+ after,
313
+ stylePreference,
314
+ rationale,
315
+ acceptedRefs,
316
+ evidenceRefs,
317
+ targetRefs,
318
+ filePaths,
319
+ taskRefs,
320
+ outcomeFeedbackRefs,
321
+ serviceConnectionIds
322
+ });
323
+ return removeUndefined({
324
+ kind: "rhei_code_goal_outcome_feedback",
325
+ schemaVersion: 1,
326
+ correctionKind,
327
+ outcome,
328
+ rationale,
329
+ evidenceRefs,
330
+ acceptedRefs,
331
+ rejectedRefs,
332
+ missingRefs,
333
+ preferenceSignals,
334
+ memoryCandidates,
335
+ serviceConnectionIds,
336
+ closedLoops: uniqueStrings2([
337
+ "feedback:outcome_captured",
338
+ memoryCandidates.length > 0 ? "feedback:memory_candidate_emitted" : undefined,
339
+ evidenceRefs.length > 0 ? "feedback:evidence_refs_linked" : undefined
340
+ ]),
341
+ noMemoryWrite: true,
342
+ ...buildGoalIntelligenceGuardrailsV1()
343
+ });
344
+ }
345
+ function buildGoalStewardDecisionV1({ args, goal }) {
346
+ const steering = asRecord(args["steering"]) ?? {};
347
+ const goalSession = asRecord(args["goalSession"]) ?? {};
348
+ const activeGoal = cleanString2(steering["activeGoal"]) ?? cleanString2(goalSession["activeGoal"]) ?? cleanString2(args["activeGoal"]);
349
+ const incomingGoal = cleanString2(steering["incomingGoal"]) ?? cleanString2(goalSession["incomingGoal"]) ?? goal;
350
+ const allowAppend = booleanValue(steering["allowAppend"]) ?? booleanValue(args["allowAppend"]) ?? false;
351
+ const forceNewGoal = booleanValue(steering["forceNewGoal"]) ?? booleanValue(args["forceNewGoal"]) ?? false;
352
+ const replaceActiveGoal = booleanValue(steering["replaceActiveGoal"]) ?? booleanValue(args["replaceActiveGoal"]) ?? false;
353
+ const similarity = activeGoal && incomingGoal ? goalSimilarity(activeGoal, incomingGoal) : undefined;
354
+ const decision = steeringDecision({ activeGoal, incomingGoal, allowAppend, forceNewGoal, replaceActiveGoal, similarity });
355
+ const reasonCodes = steeringReasonCodes({ activeGoal, incomingGoal, allowAppend, forceNewGoal, replaceActiveGoal, similarity, decision });
356
+ return removeUndefined({
357
+ kind: "rhei_code_goal_steering",
358
+ schemaVersion: 1,
359
+ decision,
360
+ policy: "latest_explicit_goal_wins_unless_append_is_explicit",
361
+ activeGoal,
362
+ incomingGoal,
363
+ activeGoalId: cleanString2(steering["activeGoalId"]) ?? cleanString2(goalSession["activeGoalId"]) ?? cleanString2(args["activeGoalId"]),
364
+ incomingGoalId: cleanString2(steering["incomingGoalId"]) ?? cleanString2(goalSession["incomingGoalId"]) ?? cleanString2(args["incomingGoalId"]),
365
+ parentGoalId: cleanString2(steering["parentGoalId"]) ?? cleanString2(goalSession["parentGoalId"]),
366
+ supersedesGoalId: cleanString2(steering["supersedesGoalId"]) ?? cleanString2(goalSession["supersedesGoalId"]),
367
+ similarity,
368
+ appendAllowed: allowAppend,
369
+ activeGoalShouldChange: decision === "start_goal" || decision === "branch_goal" || decision === "replace_active_goal",
370
+ requiresExplicitUserConfirmation: decision === "ask_for_goal_boundary" || decision === "branch_goal",
371
+ reasonCodes,
372
+ recommendedNextStep: steeringNextStep(decision),
373
+ serviceConnectionIds: collectGoalServiceConnectionIdsV1(args),
374
+ ...buildGoalIntelligenceGuardrailsV1()
375
+ });
376
+ }
377
+ function buildGoalResumeV1({ args, goal, goalSession, serviceConnectionIds: baseServiceConnectionIds }) {
378
+ const resume = asRecord(args["resume"]) ?? {};
379
+ const normalizedSession = normalizedGoalSession(goalSession, goal, resume);
380
+ const serviceConnectionIds = uniqueStrings2([
381
+ ...baseServiceConnectionIds,
382
+ ...stringList2(resume["serviceConnectionIds"]),
383
+ ...normalizedSession.serviceConnectionIds
384
+ ]);
385
+ const exactRefs = uniqueStrings2([...stringList2(args["exactRefs"]), ...stringList2(resume["exactRefs"])]);
386
+ const evidenceRefs = collectGoalEvidenceRefsV1(args, resume);
387
+ const continuityPacket = buildGoalContinuityPacketV1({
388
+ goal,
389
+ goalSession: normalizedSession,
390
+ resume,
391
+ exactRefs,
392
+ evidenceRefs
393
+ });
394
+ const commitRefs = uniqueStrings2([...normalizedSession.commitRefs, ...stringList2(resume["commitRefs"])]);
395
+ return {
396
+ kind: "rhei_code_goal_resume",
397
+ schemaVersion: 1,
398
+ goalSession: normalizedSession,
399
+ goalSessionId: normalizedSession.goalSessionId,
400
+ activeGoalId: normalizedSession.activeGoalId,
401
+ parentGoalId: normalizedSession.parentGoalId,
402
+ supersedesGoalId: normalizedSession.supersedesGoalId,
403
+ continuityPacket,
404
+ intelligenceBackends: {
405
+ codeMarket: {
406
+ contextRunIds: uniqueStrings2([...normalizedSession.contextRunIds, ...stringList2(resume["contextRunIds"])]),
407
+ snapshotIds: uniqueStrings2([...normalizedSession.codeMarketSnapshotIds, ...stringList2(resume["codeMarketSnapshotIds"])])
408
+ },
409
+ codeTrail: { refs: uniqueStrings2([...normalizedSession.codeTrailRefs, ...stringList2(resume["codeTrailRefs"])]) },
410
+ prReview: { refs: uniqueStrings2([...normalizedSession.prReviewRefs, ...stringList2(resume["prReviewRefs"])]) },
411
+ git: { commitRefs },
412
+ repoIntelligence: { evidenceRefs: evidenceRefs.slice(0, COMPACT_REF_LIMIT) }
413
+ },
414
+ serviceConnectionIds,
415
+ ...buildGoalIntelligenceGuardrailsV1()
416
+ };
417
+ }
418
+ function buildGoalContinuityPacketV1({
419
+ goal,
420
+ goalSession,
421
+ resume = {},
422
+ exactRefs = [],
423
+ evidenceRefs = [],
424
+ maxRefs = COMPACT_REF_LIMIT
425
+ }) {
426
+ const completedSteps = uniqueStrings2([
427
+ ...goalSession.completedSteps,
428
+ ...stringList2(resume["completedSteps"])
429
+ ]);
430
+ const remainingSteps = uniqueStrings2([
431
+ ...goalSession.remainingSteps,
432
+ ...stringList2(resume["remainingSteps"])
433
+ ]);
434
+ const commitRefs = uniqueStrings2([...goalSession.commitRefs, ...stringList2(resume["commitRefs"])]);
435
+ const validationRefs = uniqueStrings2([...goalSession.validationRefs, ...stringList2(resume["validationRefs"])]);
436
+ const outcomeFeedbackRefs = uniqueStrings2([...goalSession.outcomeFeedbackRefs, ...stringList2(resume["outcomeFeedbackRefs"])]);
437
+ const done = uniqueStrings2([
438
+ ...completedSteps,
439
+ ...commitRefs.map((ref) => `commit:${ref}`),
440
+ ...validationRefs.map((ref) => `validation:${ref}`),
441
+ ...outcomeFeedbackRefs.map((ref) => `outcome:${ref}`)
442
+ ]);
443
+ const staleRefs = uniqueStrings2([...goalSession.staleRefs, ...stringList2(resume["staleRefs"])]);
444
+ const currentRefs = uniqueStrings2([...exactRefs, ...evidenceRefs]);
445
+ return removeUndefined({
446
+ schemaVersion: 1,
447
+ kind: "goal_continuity_packet",
448
+ goal,
449
+ done: done.slice(0, maxRefs),
450
+ doneOmitted: omittedAfterLimit(done.length, maxRefs),
451
+ currentRefs: currentRefs.slice(0, maxRefs),
452
+ currentRefsOmitted: omittedAfterLimit(currentRefs.length, maxRefs),
453
+ openQuestions: uniqueStrings2([...goalSession.openQuestions, ...stringList2(resume["openQuestions"])]),
454
+ remainingSteps,
455
+ staleRefs,
456
+ staleWarnings: staleRefs.map((ref) => `${ref} must be revalidated before reuse.`),
457
+ contextEngineering: "Resume from compact receipts and ranked deltas only; do not replay full transcripts into the next context window.",
458
+ ...buildGoalIntelligenceGuardrailsV1()
459
+ });
460
+ }
461
+ function buildGoalIntelligenceCommitV1({ args, goal, goalSession, serviceConnectionIds: baseServiceConnectionIds }) {
462
+ const input = asRecord(args["intelligenceCommit"]) ?? {};
463
+ const normalizedSession = normalizedGoalSession(goalSession, goal, input);
464
+ const commitRefs = uniqueStrings2([...stringList2(input["commitRefs"]), ...normalizedSession.commitRefs]);
465
+ const contextRunIds = uniqueStrings2([...stringList2(input["contextRunIds"]), ...normalizedSession.contextRunIds]);
466
+ const codeMarketSnapshotIds = uniqueStrings2([...stringList2(input["codeMarketSnapshotIds"]), ...normalizedSession.codeMarketSnapshotIds]);
467
+ const codeTrailRefs = uniqueStrings2([...stringList2(input["codeTrailRefs"]), ...normalizedSession.codeTrailRefs]);
468
+ const prReviewRefs = uniqueStrings2([...stringList2(input["prReviewRefs"]), ...normalizedSession.prReviewRefs]);
469
+ const validationRefs = uniqueStrings2([...stringList2(input["validationRefs"]), ...normalizedSession.validationRefs]);
470
+ const outcomeFeedbackRefs = uniqueStrings2([...stringList2(input["outcomeFeedbackRefs"]), ...normalizedSession.outcomeFeedbackRefs]);
471
+ const evidenceRefs = uniqueStrings2([
472
+ ...collectGoalEvidenceRefsV1(args, input),
473
+ ...commitRefs.map((ref) => `git:${ref}`),
474
+ ...validationRefs,
475
+ ...codeTrailRefs,
476
+ ...prReviewRefs,
477
+ ...outcomeFeedbackRefs
478
+ ]);
479
+ const intelligenceCommitId = cleanString2(input["intelligenceCommitId"]) ?? cleanString2(input["id"]) ?? `intel-commit:${goalStableHash({ goal, commitRefs, validationRefs, codeTrailRefs, prReviewRefs, evidenceRefs })}`;
480
+ return removeUndefined({
481
+ kind: "rhei_code_goal_intelligence_commit",
482
+ schemaVersion: 1,
483
+ intelligenceCommitId,
484
+ summary: cleanString2(input["summary"]) ?? "Report-only intelligence receipt linking source commits to context, validation, review, and outcome evidence.",
485
+ goal,
486
+ goalSession: normalizedSession,
487
+ gitCommitRefs: commitRefs,
488
+ contextRunIds,
489
+ codeMarketSnapshotIds,
490
+ codeTrailRefs,
491
+ prReviewRefs,
492
+ validationRefs,
493
+ outcomeFeedbackRefs,
494
+ evidenceRefs: evidenceRefs.slice(0, COMPACT_REF_LIMIT),
495
+ evidenceRefsOmitted: omittedAfterLimit(evidenceRefs.length, COMPACT_REF_LIMIT),
496
+ compareToGit: "Git records source diff history; this receipt records why-context, diagnostic, validation, PR review, service, and outcome evidence around that diff.",
497
+ serviceConnectionIds: uniqueStrings2([...baseServiceConnectionIds, ...stringList2(input["serviceConnectionIds"])]),
498
+ noSourceMutation: true,
499
+ noMemoryWrite: true,
500
+ ...buildGoalIntelligenceGuardrailsV1()
501
+ });
502
+ }
503
+ function buildPreferenceReplayV1({ args, goal, serviceConnectionIds }) {
504
+ const replay = asRecord(args["preferenceReplay"]) ?? {};
505
+ const outcomeFeedback = buildGoalOutcomeFeedbackV1({ args, goal, serviceConnectionIds });
506
+ const preferences = uniqueStrings2([
507
+ ...stringList2(replay["preferences"]),
508
+ cleanString2(replay["preference"]),
509
+ cleanString2(replay["stylePreference"]),
510
+ cleanString2(outcomeFeedback.rationale),
511
+ ...outcomeFeedback.preferenceSignals.flatMap((signal) => signal.kind === "style_preference" ? [signal.summary] : [])
512
+ ]);
513
+ const acceptedRefs = uniqueStrings2([
514
+ ...stringList2(args["acceptedRefs"]),
515
+ ...stringList2(replay["acceptedRefs"]),
516
+ ...outcomeFeedback.acceptedRefs
517
+ ]);
518
+ const rejectedRefs = uniqueStrings2([
519
+ ...stringList2(args["rejectedRefs"]),
520
+ ...stringList2(replay["rejectedRefs"]),
521
+ ...outcomeFeedback.rejectedRefs
522
+ ]);
523
+ const evidenceRefs = uniqueStrings2([
524
+ ...collectGoalEvidenceRefsV1(args, replay),
525
+ ...outcomeFeedback.evidenceRefs,
526
+ ...acceptedRefs,
527
+ ...rejectedRefs
528
+ ]);
529
+ return removeUndefined({
530
+ kind: "rhei_code_goal_preference_replay",
531
+ schemaVersion: 1,
532
+ goal,
533
+ preferences,
534
+ acceptedRefs,
535
+ rejectedRefs,
536
+ memoryCandidates: outcomeFeedback.memoryCandidates,
537
+ replayPlan: [
538
+ "Bias future proposals toward accepted human rewrites and explicit style preferences.",
539
+ "Keep rejected refs as negative examples for ranking only.",
540
+ "Promote memory only through the governed memory path after repeated evidence."
541
+ ],
542
+ evaluation: {
543
+ expectedSignals: uniqueStrings2([
544
+ preferences.length > 0 ? "style_preference_reused" : undefined,
545
+ outcomeFeedback.memoryCandidates.length > 0 ? "human_rewrite_pattern_matched" : undefined,
546
+ acceptedRefs.length > 0 ? "accepted_refs_ranked_higher" : undefined,
547
+ rejectedRefs.length > 0 ? "rejected_refs_ranked_lower" : undefined
548
+ ]),
549
+ trialFootprintRefs: evidenceRefs.slice(0, COMPACT_REF_LIMIT),
550
+ trialFootprintRefsOmitted: omittedAfterLimit(evidenceRefs.length, COMPACT_REF_LIMIT),
551
+ status: "replay_plan_ready_report_only"
552
+ },
553
+ rankingBiasEvidence: {
554
+ status: "advisory_only_no_memory_write",
555
+ acceptedRefs,
556
+ rejectedRefs,
557
+ evidenceRefs: evidenceRefs.slice(0, COMPACT_REF_LIMIT)
558
+ },
559
+ serviceConnectionIds,
560
+ noMemoryWrite: true,
561
+ ...buildGoalIntelligenceGuardrailsV1()
562
+ });
563
+ }
564
+ function buildDiagnosticClosureV1({ args, goal, serviceConnectionIds }) {
565
+ const closure = asRecord(args["diagnosticClosure"]) ?? {};
566
+ const diagnosticRefs = uniqueStrings2([...stringList2(closure["diagnosticRefs"]), ...stringList2(args["diagnosticRefs"])]);
567
+ const fixRefs = uniqueStrings2([...stringList2(closure["fixRefs"]), ...stringList2(args["fixRefs"])]);
568
+ const validationRefs = uniqueStrings2([
569
+ ...stringList2(closure["validationRefs"]),
570
+ ...stringList2(args["validationRefs"]),
571
+ ...stringList2(asRecord(args["goalSession"])?.["validationRefs"])
572
+ ]);
573
+ const outcome = cleanString2(closure["outcome"]) ?? cleanString2(closure["status"]) ?? cleanString2(args["outcome"]);
574
+ const evidenceRefs = uniqueStrings2([
575
+ ...collectGoalEvidenceRefsV1(args, closure),
576
+ ...diagnosticRefs,
577
+ ...fixRefs,
578
+ ...validationRefs
579
+ ]);
580
+ const closed = validationRefs.length > 0 && CLOSED_OUTCOMES.has((outcome ?? "").toLowerCase());
581
+ const status = closed ? "closed_with_validation" : validationRefs.length > 0 ? "validation_linked" : "needs_validation";
582
+ return removeUndefined({
583
+ kind: "rhei_code_goal_diagnostic_closure",
584
+ schemaVersion: 1,
585
+ goal,
586
+ status,
587
+ outcome,
588
+ diagnosticRefs,
589
+ fixRefs,
590
+ validationRefs,
591
+ evidenceRefs: evidenceRefs.slice(0, COMPACT_REF_LIMIT),
592
+ evidenceRefsOmitted: omittedAfterLimit(evidenceRefs.length, COMPACT_REF_LIMIT),
593
+ closedLoops: closed ? ["diagnostic:validated_fix", "diagnostic:outcome_captured"] : [],
594
+ nextAction: closed ? {
595
+ tool: "rhei_code_goal",
596
+ mode: "intelligence_commit",
597
+ reason: "Diagnostic evidence has validation; emit a compact intelligence receipt for future resume and replay."
598
+ } : {
599
+ tool: "rhei_code_context_for_goal",
600
+ input: "evidenceIntake",
601
+ reason: "Validation evidence is still required before the diagnostic loop can close."
602
+ },
603
+ serviceConnectionIds,
604
+ ...buildGoalIntelligenceGuardrailsV1()
605
+ });
606
+ }
607
+ function buildServiceImpactV1({ args, goal, serviceConnectionIds: baseServiceConnectionIds }) {
608
+ const impact = asRecord(args["serviceImpact"]) ?? {};
609
+ const serviceConnectionIds = uniqueStrings2([
610
+ ...baseServiceConnectionIds,
611
+ ...stringList2(impact["serviceConnectionIds"]),
612
+ ...serviceConnectionIdsFromEvidence(args["serviceConnections"])
613
+ ]);
614
+ const evidenceRefs = collectGoalEvidenceRefsV1(args, impact);
615
+ const impactedRefs = uniqueStrings2([
616
+ ...stringList2(impact["impactedRefs"]),
617
+ ...stringList2(impact["impactRefs"]),
618
+ ...stringList2(args["exactRefs"]),
619
+ ...evidenceRefs
620
+ ]);
621
+ const backendRefs = uniqueStrings2(stringList2(impact["backendRefs"]));
622
+ const uiRefs = uniqueStrings2(stringList2(impact["uiRefs"]));
623
+ const testRefs = uniqueStrings2(stringList2(impact["testRefs"]));
624
+ const docsRefs = uniqueStrings2(stringList2(impact["docsRefs"]));
625
+ return removeUndefined({
626
+ kind: "rhei_code_goal_service_impact",
627
+ schemaVersion: 1,
628
+ goal,
629
+ serviceConnectionIds,
630
+ serviceConnectionRefs: uniqueStrings2([
631
+ ...stringList2(impact["serviceConnectionRefs"]),
632
+ ...serviceConnectionIds
633
+ ]).slice(0, COMPACT_REF_LIMIT),
634
+ impactedRefs: impactedRefs.slice(0, COMPACT_REF_LIMIT),
635
+ impactedRefsOmitted: omittedAfterLimit(impactedRefs.length, COMPACT_REF_LIMIT),
636
+ impactedServices: serviceConnectionIds,
637
+ impactStatus: "evidence_linked_only",
638
+ promotionPath: "rhei_service_intelligence_for_goal",
639
+ nextSlice: {
640
+ backendRefs,
641
+ uiRefs,
642
+ testRefs,
643
+ docsRefs,
644
+ steps: [
645
+ "Run rhei_service_intelligence_for_goal with the same service evidence.",
646
+ "Choose the smallest backend, UI, test, or docs slice after service evidence is summarized.",
647
+ "Return validation refs to rhei_code_goal before any memory, service, or graph promotion path."
648
+ ],
649
+ guardrails: [
650
+ "No connector sync from service_impact.",
651
+ "No service write from service_impact.",
652
+ "No graph mutation from service_impact."
653
+ ]
654
+ },
655
+ nextAction: {
656
+ tool: "rhei_service_intelligence_for_goal",
657
+ reason: "Service impact is evidence-linked only; use the service intelligence bridge for impacted service/resource mapping."
658
+ },
659
+ gates: {
660
+ noConnectorSync: true,
661
+ noServiceWrite: true,
662
+ noGraphMutation: true,
663
+ requiresGovernedServiceIntelligencePromotion: true
664
+ },
665
+ ...buildGoalIntelligenceGuardrailsV1()
666
+ });
667
+ }
668
+ function buildGoalFeedbackLoopsV1(args) {
669
+ const loops = [];
670
+ if (args.mode === "edit") {
671
+ loops.push({
672
+ kind: "edit_loop",
673
+ status: "transaction_receipts_ready",
674
+ nextEvidenceLane: "rhei_code_goal mode=outcome_feedback or rhei_code_trail_export",
675
+ summary: "Edit transaction linked context, reads, proposal, dry-run, diff, validation, AgentEditSession receipt, and Trail evidence without apply authority."
676
+ });
677
+ }
678
+ if (args.mode === "verify") {
679
+ loops.push({
680
+ kind: "verify_loop",
681
+ status: "search_read_absence_receipts_ready",
682
+ nextEvidenceLane: "rhei_code_goal mode=edit or rhei_code_goal mode=report",
683
+ summary: "Verify transaction linked scoped search, exact reads, searched scopes/counts/confidence, caveats, absence proof, and Trail evidence without source writes."
684
+ });
685
+ }
686
+ if (args.mode === "trail") {
687
+ loops.push({
688
+ kind: "trail_loop",
689
+ status: "session_history_receipts_ready",
690
+ nextEvidenceLane: "rhei_code_goal mode=outcome_feedback or rhei_code_goal mode=report",
691
+ summary: "Trail transaction linked session reads, proposals, dry-runs, diffs, reverse diffs, validations, human decisions, replay refs, and CodeTrail export evidence without apply authority."
692
+ });
693
+ }
694
+ if (args.mode === "learn_from_outcome") {
695
+ loops.push({
696
+ kind: "learn_from_outcome_loop",
697
+ status: "replay_evidence_ready",
698
+ nextEvidenceLane: "rhei_code_goal mode=preference_replay or governed memory promotion",
699
+ summary: "Accepted/rejected outcomes and human rewrites are captured as replay evidence and memory candidates only; memory promotion remains explicitly gated."
700
+ });
701
+ }
702
+ if (args.mode === "report") {
703
+ loops.push({
704
+ kind: "report_loop",
705
+ status: "markdown_diff_receipt_ready",
706
+ nextEvidenceLane: "rhei_code_goal mode=intelligence_commit",
707
+ summary: "Markdown report output includes a diff preview and receipt; report writes are explicit and grant no product or apply authority."
708
+ });
709
+ }
710
+ if (args.mode === "diagnose") {
711
+ loops.push({
712
+ kind: "diagnostic_loop",
713
+ status: "closed_when_validation_evidence_returns",
714
+ nextEvidenceLane: "evidenceIntake",
715
+ summary: "Feed validation/CI/PR review output back into rhei_code_goal mode=diagnose or rhei_code_context_for_goal evidenceIntake."
716
+ });
717
+ }
718
+ if (args.mode === "outcome_feedback") {
719
+ loops.push({
720
+ kind: "outcome_feedback_loop",
721
+ status: "captured_report_only",
722
+ nextEvidenceLane: "rhei_code_review mode=generate_memory_candidates or governed memory promotion",
723
+ summary: "Human rewrite/style/outcome feedback is represented as memory candidates without writing memory."
724
+ });
725
+ }
726
+ if (args.mode === "steer") {
727
+ loops.push({
728
+ kind: "steering_loop",
729
+ status: "goal_boundary_decided",
730
+ summary: "New instructions branch or replace unless append is explicit or similarity is high."
731
+ });
732
+ }
733
+ if (args.mode === "resume") {
734
+ loops.push({ kind: "resume_loop", status: "continuity_captured_report_only", summary: "Resume metadata links the active goal to evidence without hidden execution." });
735
+ }
736
+ if (args.mode === "intelligence_commit") {
737
+ loops.push({ kind: "intelligence_commit_loop", status: "commit_evidence_captured_report_only", summary: "Commit, validation, PR, and Code Trail refs are linked as evidence only." });
738
+ }
739
+ if (args.mode === "preference_replay") {
740
+ loops.push({ kind: "preference_replay_loop", status: "replay_captured_report_only", summary: "Preference signals can be evaluated without writing memory." });
741
+ }
742
+ if (args.mode === "diagnostic_closure") {
743
+ loops.push({ kind: "diagnostic_closure_loop", status: "closure_captured_report_only", summary: "Diagnostics, fixes, validation, and outcomes are linked without authority escalation." });
744
+ }
745
+ if (args.mode === "service_impact") {
746
+ loops.push({ kind: "service_impact_loop", status: "service_impact_captured_report_only", summary: "Service impact evidence is linked without connector writes or graph mutation." });
747
+ }
748
+ if (args.mode === "start") {
749
+ loops.push({
750
+ kind: "goal_start_loop",
751
+ status: "lifecycle_start_captured_report_only",
752
+ nextEvidenceLane: "rhei_code_goal mode=checkpoint",
753
+ summary: "Goal lifecycle start links bounded context and ContextPacket evidence without creating task authority."
754
+ });
755
+ }
756
+ if (args.mode === "checkpoint") {
757
+ loops.push({
758
+ kind: "goal_checkpoint_loop",
759
+ status: "lifecycle_checkpoint_captured_report_only",
760
+ nextEvidenceLane: "rhei_code_goal mode=finish or validation evidence",
761
+ summary: "Goal lifecycle checkpoint captures edit, validation, PR, service, and CodeTrail refs as interim report-only evidence."
762
+ });
763
+ }
764
+ if (args.mode === "finish") {
765
+ loops.push({
766
+ kind: "goal_finish_loop",
767
+ status: "lifecycle_finish_captured_report_only",
768
+ nextEvidenceLane: "explicit CodeTrail import or governed memory promotion path",
769
+ summary: "Goal lifecycle finish emits final report-only evidence and soft observations without writing truth or memory."
770
+ });
771
+ }
772
+ if (args.mode === "context") {
773
+ loops.push({
774
+ kind: "context_loop",
775
+ status: "bounded_context_ready",
776
+ summary: "Use the compact context handoff, then return diagnostics or outcomes to this central goal surface."
777
+ });
778
+ }
779
+ return loops;
780
+ }
781
+ function collectGoalEvidenceRefsV1(args, extra) {
782
+ const goalSession = asRecord(args["goalSession"]);
783
+ const records = [
784
+ args,
785
+ goalSession,
786
+ asRecord(args["outcomeFeedback"]),
787
+ asRecord(args["steering"]),
788
+ asRecord(args["resume"]),
789
+ asRecord(args["intelligenceCommit"]),
790
+ asRecord(args["preferenceReplay"]),
791
+ asRecord(args["diagnosticClosure"]),
792
+ asRecord(args["serviceImpact"]),
793
+ extra
794
+ ].filter((record) => Boolean(record));
795
+ const fields = [
796
+ "exactRefs",
797
+ "evidenceRefs",
798
+ "acceptedRefs",
799
+ "rejectedRefs",
800
+ "missingRefs",
801
+ "primaryRefs",
802
+ "diagnosticRefs",
803
+ "fixRefs",
804
+ "validationRefs",
805
+ "commitRefs",
806
+ "contextRunIds",
807
+ "codeMarketSnapshotIds",
808
+ "codeTrailRefs",
809
+ "prReviewRefs",
810
+ "outcomeFeedbackRefs",
811
+ "serviceConnectionRefs",
812
+ "impactedRefs",
813
+ "impactRefs"
814
+ ];
815
+ return uniqueStrings2(records.flatMap((record) => fields.flatMap((field) => stringList2(record[field]))));
816
+ }
817
+ function collectAcceptedRefsV1(args, input) {
818
+ return uniqueStrings2([
819
+ ...stringList2(args["acceptedRefs"]),
820
+ ...stringList2(input?.["acceptedRefs"])
821
+ ]);
822
+ }
823
+ function collectRejectedRefsV1(args, input) {
824
+ return uniqueStrings2([
825
+ ...stringList2(args["rejectedRefs"]),
826
+ ...stringList2(input?.["rejectedRefs"])
827
+ ]);
828
+ }
829
+ function collectMissingRefsV1(args, input) {
830
+ return uniqueStrings2([
831
+ ...stringList2(args["missingRefs"]),
832
+ ...stringList2(input?.["missingRefs"])
833
+ ]);
834
+ }
835
+ function serviceConnectionIdsFromEvidence(value) {
836
+ return arrayValue(value).flatMap((item) => {
837
+ const record = asRecord(item);
838
+ if (!record)
839
+ return [];
840
+ const source = asRecord(record["source"]);
841
+ const target = asRecord(record["target"]);
842
+ const sourceId = cleanString2(source?.["id"]);
843
+ const targetId = cleanString2(target?.["id"]);
844
+ return uniqueStrings2([
845
+ cleanString2(record["id"]),
846
+ cleanString2(record["serviceConnectionId"]),
847
+ cleanString2(record["dedupeKey"]),
848
+ sourceId && targetId ? `${sourceId}->${targetId}` : undefined
849
+ ]);
850
+ });
851
+ }
852
+ function inferCorrectionKind(feedback) {
853
+ if (cleanString2(feedback["after"]) || cleanString2(feedback["rewrite"]) || cleanString2(feedback["humanRewrite"]) || cleanString2(feedback["corrected"])) {
854
+ return "human_rewrite";
855
+ }
856
+ if (cleanString2(feedback["stylePreference"]) || cleanString2(feedback["preference"]))
857
+ return "style_preference";
858
+ if (cleanString2(feedback["outcome"]) || cleanString2(feedback["status"]))
859
+ return "outcome";
860
+ return "correction";
861
+ }
862
+ function buildPreferenceSignals(args) {
863
+ const signals = [];
864
+ if (args.outcome) {
865
+ signals.push({
866
+ kind: "outcome",
867
+ value: args.outcome,
868
+ summary: "Outcome feedback captured for later proposal ranking."
869
+ });
870
+ }
871
+ if (args.after) {
872
+ signals.push({
873
+ kind: "human_rewrite",
874
+ correctionKind: args.correctionKind,
875
+ beforePresent: Boolean(args.before),
876
+ afterPresent: true,
877
+ summary: "Human rewrite captured as a style/preference signal, not as automatic memory."
878
+ });
879
+ }
880
+ if (args.stylePreference) {
881
+ signals.push({
882
+ kind: "style_preference",
883
+ summary: args.stylePreference
884
+ });
885
+ }
886
+ if (args.rationale) {
887
+ signals.push({
888
+ kind: "rationale",
889
+ summary: args.rationale
890
+ });
891
+ }
892
+ if (args.evidenceRefs.length > 0) {
893
+ signals.push({
894
+ kind: "evidence_link",
895
+ refs: args.evidenceRefs.slice(0, COMPACT_REF_LIMIT),
896
+ refsOmitted: omittedAfterLimit(args.evidenceRefs.length, COMPACT_REF_LIMIT)
897
+ });
898
+ }
899
+ return signals;
900
+ }
901
+ function buildOutcomeMemoryCandidates(args) {
902
+ const candidates = [];
903
+ if (args.after || args.stylePreference) {
904
+ const candidateKind = args.stylePreference ? "style_preference" : "code_rewrite_preference";
905
+ const title = args.stylePreference ? "Human style preference" : "Human rewrite preference";
906
+ const summary = args.stylePreference ?? "Human supplied a corrected rewrite; promote only through the governed memory path if this pattern repeats.";
907
+ const identity = buildGoalMemoryCandidateIdentityV1({
908
+ sourceKind: "outcome_feedback",
909
+ candidateKind,
910
+ title,
911
+ summary,
912
+ normalizedRule: summary,
913
+ goal: args.goal,
914
+ goalSessionId: args.goalSessionId,
915
+ activeGoalId: args.activeGoalId,
916
+ parentGoalId: args.parentGoalId,
917
+ supersedesGoalId: args.supersedesGoalId,
918
+ sourceIds: goalMemoryCandidateSourceIdsV1([args.outcomeFeedbackRefs, args.evidenceRefs]),
919
+ targetRefs: args.targetRefs,
920
+ filePaths: args.filePaths,
921
+ evidenceRefs: args.evidenceRefs,
922
+ taskRefs: args.taskRefs,
923
+ serviceConnectionIds: args.serviceConnectionIds
924
+ });
925
+ const status = args.evidenceRefs.length > 0 ? "ready_for_review" : "candidate";
926
+ candidates.push(removeUndefined({
927
+ kind: "memory_candidate",
928
+ candidateKind,
929
+ title,
930
+ summary,
931
+ normalizedRule: summary,
932
+ goal: args.goal,
933
+ correctionKind: args.correctionKind,
934
+ evidenceRefs: args.evidenceRefs.slice(0, COMPACT_REF_LIMIT),
935
+ serviceConnectionIds: args.serviceConnectionIds.slice(0, COMPACT_REF_LIMIT),
936
+ ...identity,
937
+ sourceKind: "outcome_feedback",
938
+ sourceIds: goalMemoryCandidateSourceIdsV1([args.outcomeFeedbackRefs, args.evidenceRefs]),
939
+ goalSessionId: args.goalSessionId,
940
+ activeGoalId: args.activeGoalId,
941
+ parentGoalId: args.parentGoalId,
942
+ supersedesGoalId: args.supersedesGoalId,
943
+ targetRefs: args.targetRefs.slice(0, COMPACT_REF_LIMIT),
944
+ filePaths: args.filePaths.slice(0, COMPACT_REF_LIMIT),
945
+ taskRefs: args.taskRefs.slice(0, COMPACT_REF_LIMIT),
946
+ outcomeFeedbackRefs: args.outcomeFeedbackRefs.slice(0, COMPACT_REF_LIMIT),
947
+ confidence: status === "ready_for_review" ? 0.8 : 0.55,
948
+ rank: status === "ready_for_review" ? 80 : 55,
949
+ status,
950
+ promotionStatus: status,
951
+ promotionBlockers: status === "ready_for_review" ? [] : ["promotion:requires_evidence_refs"],
952
+ reasonCodes: uniqueStrings2([
953
+ `goal_memory:${candidateKind}`,
954
+ "goal_memory:human_feedback",
955
+ status === "ready_for_review" ? "goal_memory:evidence_linked" : "goal_memory:candidate_only"
956
+ ]),
957
+ candidateOnly: true,
958
+ rankingUseOnly: true,
959
+ requiresUserConfirmation: true,
960
+ requiresRepeatedEvidence: status !== "ready_for_review",
961
+ requiresOmPolicyCheck: true,
962
+ memoryWrite: false,
963
+ truthWrite: false,
964
+ noMemoryWrite: true,
965
+ promotionRequired: true,
966
+ writeAuthority: false,
967
+ promotion: {
968
+ candidateOnly: true,
969
+ rankingUseOnly: true,
970
+ status,
971
+ eligibleForPromotionReview: status === "ready_for_review",
972
+ requiresUserConfirmation: true,
973
+ requiresRepeatedEvidence: status !== "ready_for_review",
974
+ requiresOmPolicyCheck: true,
975
+ promotionRequired: true,
976
+ writeAuthority: false,
977
+ memoryWrite: false,
978
+ truthWrite: false,
979
+ noMemoryWrite: true,
980
+ blockedReasons: status === "ready_for_review" ? [] : ["promotion:requires_evidence_refs"]
981
+ },
982
+ ...buildGoalIntelligenceGuardrailsV1()
983
+ }));
984
+ }
985
+ if (args.outcome || args.rationale) {
986
+ const title = "Outcome feedback pattern";
987
+ const summary = args.rationale ?? `Outcome recorded: ${args.outcome}.`;
988
+ const status = "needs_more_evidence";
989
+ const identity = buildGoalMemoryCandidateIdentityV1({
990
+ sourceKind: "outcome_feedback",
991
+ candidateKind: "outcome_pattern",
992
+ title,
993
+ summary,
994
+ normalizedRule: summary,
995
+ goal: args.goal,
996
+ goalSessionId: args.goalSessionId,
997
+ activeGoalId: args.activeGoalId,
998
+ parentGoalId: args.parentGoalId,
999
+ supersedesGoalId: args.supersedesGoalId,
1000
+ sourceIds: goalMemoryCandidateSourceIdsV1([args.outcomeFeedbackRefs, args.acceptedRefs, args.evidenceRefs]),
1001
+ targetRefs: args.targetRefs,
1002
+ filePaths: args.filePaths,
1003
+ evidenceRefs: args.evidenceRefs,
1004
+ taskRefs: args.taskRefs,
1005
+ serviceConnectionIds: args.serviceConnectionIds
1006
+ });
1007
+ candidates.push(removeUndefined({
1008
+ kind: "memory_candidate",
1009
+ candidateKind: "outcome_pattern",
1010
+ title,
1011
+ summary,
1012
+ normalizedRule: summary,
1013
+ goal: args.goal,
1014
+ evidenceRefs: args.evidenceRefs.slice(0, COMPACT_REF_LIMIT),
1015
+ serviceConnectionIds: args.serviceConnectionIds.slice(0, COMPACT_REF_LIMIT),
1016
+ ...identity,
1017
+ sourceKind: "outcome_feedback",
1018
+ sourceIds: goalMemoryCandidateSourceIdsV1([args.outcomeFeedbackRefs, args.acceptedRefs, args.evidenceRefs]),
1019
+ goalSessionId: args.goalSessionId,
1020
+ activeGoalId: args.activeGoalId,
1021
+ parentGoalId: args.parentGoalId,
1022
+ supersedesGoalId: args.supersedesGoalId,
1023
+ targetRefs: args.targetRefs.slice(0, COMPACT_REF_LIMIT),
1024
+ filePaths: args.filePaths.slice(0, COMPACT_REF_LIMIT),
1025
+ taskRefs: args.taskRefs.slice(0, COMPACT_REF_LIMIT),
1026
+ outcomeFeedbackRefs: args.outcomeFeedbackRefs.slice(0, COMPACT_REF_LIMIT),
1027
+ confidence: CLOSED_OUTCOMES.has(args.outcome ?? "") || args.acceptedRefs.length > 0 ? 0.55 : 0.35,
1028
+ rank: CLOSED_OUTCOMES.has(args.outcome ?? "") || args.acceptedRefs.length > 0 ? 55 : 35,
1029
+ status,
1030
+ promotionStatus: status,
1031
+ promotionBlockers: ["promotion:outcome_feedback_requires_repeated_evidence"],
1032
+ reasonCodes: uniqueStrings2([
1033
+ "goal_memory:outcome_pattern",
1034
+ "goal_memory:needs_more_evidence",
1035
+ args.acceptedRefs.length > 0 ? "goal_memory:accepted_refs_linked" : undefined
1036
+ ]),
1037
+ candidateOnly: true,
1038
+ rankingUseOnly: true,
1039
+ requiresUserConfirmation: true,
1040
+ requiresRepeatedEvidence: true,
1041
+ requiresOmPolicyCheck: true,
1042
+ memoryWrite: false,
1043
+ truthWrite: false,
1044
+ noMemoryWrite: true,
1045
+ promotionRequired: true,
1046
+ writeAuthority: false,
1047
+ promotion: {
1048
+ candidateOnly: true,
1049
+ rankingUseOnly: true,
1050
+ status,
1051
+ eligibleForPromotionReview: false,
1052
+ requiresUserConfirmation: true,
1053
+ requiresRepeatedEvidence: true,
1054
+ requiresOmPolicyCheck: true,
1055
+ promotionRequired: true,
1056
+ writeAuthority: false,
1057
+ memoryWrite: false,
1058
+ truthWrite: false,
1059
+ noMemoryWrite: true,
1060
+ blockedReasons: ["promotion:outcome_feedback_requires_repeated_evidence"]
1061
+ },
1062
+ ...buildGoalIntelligenceGuardrailsV1()
1063
+ }));
1064
+ }
1065
+ return candidates;
1066
+ }
1067
+ function steeringDecision(args) {
1068
+ if (!args.incomingGoal)
1069
+ return "ask_for_goal_boundary";
1070
+ if (!args.activeGoal)
1071
+ return "start_goal";
1072
+ if (args.replaceActiveGoal)
1073
+ return "replace_active_goal";
1074
+ if (args.forceNewGoal)
1075
+ return "branch_goal";
1076
+ if (args.allowAppend)
1077
+ return "continue_active_goal";
1078
+ if ((args.similarity ?? 0) >= 0.62)
1079
+ return "continue_active_goal";
1080
+ if ((args.similarity ?? 0) <= 0.28)
1081
+ return "branch_goal";
1082
+ return "ask_for_goal_boundary";
1083
+ }
1084
+ function steeringReasonCodes(args) {
1085
+ const reasons = ["steering:latest_explicit_goal_wins"];
1086
+ if (!args.incomingGoal)
1087
+ reasons.push("steering:missing_incoming_goal");
1088
+ if (!args.activeGoal)
1089
+ reasons.push("steering:no_active_goal");
1090
+ if (args.allowAppend)
1091
+ reasons.push("steering:append_explicitly_allowed");
1092
+ if (!args.allowAppend)
1093
+ reasons.push("steering:append_requires_explicit_intent");
1094
+ if (args.forceNewGoal)
1095
+ reasons.push("steering:force_new_goal");
1096
+ if (args.replaceActiveGoal)
1097
+ reasons.push("steering:replace_active_goal_requested");
1098
+ if (typeof args.similarity === "number") {
1099
+ if (args.similarity <= 0.28)
1100
+ reasons.push("steering:low_goal_similarity");
1101
+ else if (args.similarity >= 0.62)
1102
+ reasons.push("steering:high_goal_similarity");
1103
+ else
1104
+ reasons.push("steering:ambiguous_goal_similarity");
1105
+ }
1106
+ reasons.push(`steering:decision:${args.decision}`);
1107
+ return uniqueStrings2(reasons);
1108
+ }
1109
+ function steeringNextStep(decision) {
1110
+ if (decision === "continue_active_goal")
1111
+ return "Continue only because the goal is similar or append was explicit.";
1112
+ if (decision === "replace_active_goal")
1113
+ return "Start a new active goal that supersedes the prior goal.";
1114
+ if (decision === "branch_goal")
1115
+ return "Create a visible child/branch goal instead of appending silently to the active goal.";
1116
+ if (decision === "start_goal")
1117
+ return "Start a new goal session.";
1118
+ return "Ask the operator whether this instruction continues, replaces, or branches from the active goal.";
1119
+ }
1120
+ function normalizedGoalSession(goalSession, goal, extra) {
1121
+ const base = goalSession ?? buildGoalSessionV1({ args: {}, goal });
1122
+ const goalSessionId = cleanString2(extra["goalSessionId"]) ?? base.goalSessionId ?? `goal-session:${goalStableHash({ goal, activeGoal: base.activeGoal, incomingGoal: base.incomingGoal, parentGoalId: base.parentGoalId })}`;
1123
+ return removeUndefined({
1124
+ schemaVersion: 1,
1125
+ kind: "goal_session",
1126
+ goalSessionId,
1127
+ activeGoalId: cleanString2(extra["activeGoalId"]) ?? base.activeGoalId,
1128
+ incomingGoalId: cleanString2(extra["incomingGoalId"]) ?? base.incomingGoalId,
1129
+ parentGoalId: cleanString2(extra["parentGoalId"]) ?? base.parentGoalId,
1130
+ supersedesGoalId: cleanString2(extra["supersedesGoalId"]) ?? base.supersedesGoalId,
1131
+ activeGoal: cleanString2(extra["activeGoal"]) ?? base.activeGoal,
1132
+ incomingGoal: cleanString2(extra["incomingGoal"]) ?? base.incomingGoal ?? goal,
1133
+ contextRunIds: uniqueStrings2([...base.contextRunIds, ...stringList2(extra["contextRunIds"])]),
1134
+ codeMarketSnapshotIds: uniqueStrings2([...base.codeMarketSnapshotIds, ...stringList2(extra["codeMarketSnapshotIds"])]),
1135
+ codeWorkroomSessionId: cleanString2(extra["codeWorkroomSessionId"]) ?? base.codeWorkroomSessionId,
1136
+ codeTrailRefs: uniqueStrings2([...base.codeTrailRefs, ...stringList2(extra["codeTrailRefs"])]),
1137
+ prReviewRefs: uniqueStrings2([...base.prReviewRefs, ...stringList2(extra["prReviewRefs"])]),
1138
+ commitRefs: uniqueStrings2([...base.commitRefs, ...stringList2(extra["commitRefs"])]),
1139
+ validationRefs: uniqueStrings2([...base.validationRefs, ...stringList2(extra["validationRefs"])]),
1140
+ outcomeFeedbackRefs: uniqueStrings2([...base.outcomeFeedbackRefs, ...stringList2(extra["outcomeFeedbackRefs"])]),
1141
+ serviceConnectionIds: uniqueStrings2([...base.serviceConnectionIds, ...stringList2(extra["serviceConnectionIds"])]),
1142
+ staleRefs: uniqueStrings2([...base.staleRefs, ...stringList2(extra["staleRefs"])]),
1143
+ openQuestions: uniqueStrings2([...base.openQuestions, ...stringList2(extra["openQuestions"])]),
1144
+ completedSteps: uniqueStrings2([...base.completedSteps, ...stringList2(extra["completedSteps"])]),
1145
+ remainingSteps: uniqueStrings2([...base.remainingSteps, ...stringList2(extra["remainingSteps"])]),
1146
+ boundaryPolicy: "new_goal_requires_explicit_steer_decision",
1147
+ refsOnly: true,
1148
+ ...buildGoalIntelligenceGuardrailsV1()
1149
+ });
1150
+ }
1151
+ function goalStableHash(value) {
1152
+ let text;
1153
+ try {
1154
+ text = JSON.stringify(value, Object.keys(asRecord(value) ?? {}).sort());
1155
+ } catch {
1156
+ text = String(value);
1157
+ }
1158
+ let hash = 2166136261;
1159
+ for (let index = 0;index < text.length; index += 1) {
1160
+ hash ^= text.charCodeAt(index);
1161
+ hash = Math.imul(hash, 16777619);
1162
+ }
1163
+ return (hash >>> 0).toString(16).padStart(8, "0").slice(0, 8);
1164
+ }
1165
+ function goalSimilarity(left, right) {
1166
+ const leftTokens = goalTokens(left);
1167
+ const rightTokens = goalTokens(right);
1168
+ if (leftTokens.size === 0 || rightTokens.size === 0)
1169
+ return 0;
1170
+ let intersection = 0;
1171
+ for (const token of leftTokens) {
1172
+ if (rightTokens.has(token))
1173
+ intersection += 1;
1174
+ }
1175
+ const union = new Set([...leftTokens, ...rightTokens]).size;
1176
+ return Math.round(intersection / union * 100) / 100;
1177
+ }
1178
+ function goalTokens(value) {
1179
+ const stopWords = new Set(["a", "an", "and", "are", "as", "be", "by", "for", "in", "is", "it", "of", "on", "or", "the", "this", "to", "with"]);
1180
+ return new Set(value.toLowerCase().split(/[^a-z0-9_]+/g).map((token) => token.trim()).filter((token) => token.length > 2 && !stopWords.has(token)));
1181
+ }
1182
+ function booleanValue(value) {
1183
+ return typeof value === "boolean" ? value : undefined;
1184
+ }
1185
+ function stringList2(value) {
1186
+ return stringArray(value) ?? [];
1187
+ }
1188
+ function stringArray(value) {
1189
+ if (!Array.isArray(value))
1190
+ return;
1191
+ const output = value.map((item) => cleanString2(item)).filter((item) => Boolean(item));
1192
+ return output.length > 0 ? output : undefined;
1193
+ }
1194
+ function uniqueStrings2(values) {
1195
+ return Array.from(new Set(values.map((value) => value?.trim()).filter((value) => Boolean(value))));
1196
+ }
1197
+ function cleanString2(value) {
1198
+ if (typeof value !== "string")
1199
+ return;
1200
+ const text = value.trim();
1201
+ return text.length > 0 ? text : undefined;
1202
+ }
1203
+ function asRecord(value) {
1204
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
1205
+ }
1206
+ function arrayValue(value) {
1207
+ return Array.isArray(value) ? value : [];
1208
+ }
1209
+ function omittedAfterLimit(total, limit) {
1210
+ const omitted = Math.max(0, total - limit);
1211
+ return omitted > 0 ? omitted : undefined;
1212
+ }
1213
+ function removeUndefined(value) {
1214
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
1215
+ }
1216
+ // ../core/src/goalLifecycle/types.ts
1217
+ var GOAL_LIFECYCLE_SCHEMA_VERSION = 1;
1218
+ // ../core/src/goalLifecycle/progressSignals.ts
1219
+ function detectSearchLoopV1(args) {
1220
+ const byQuery = new Map;
1221
+ for (const item of args.searchQueries) {
1222
+ const query = normalizeQuery(item.query);
1223
+ if (!query)
1224
+ continue;
1225
+ byQuery.set(query, [...byQuery.get(query) ?? [], { query, at: item.at }]);
1226
+ }
1227
+ for (const [query, occurrences] of byQuery) {
1228
+ if (occurrences.length < 3)
1229
+ continue;
1230
+ const sorted = occurrences.sort((left, right) => left.at - right.at);
1231
+ const first = sorted[0]?.at ?? 0;
1232
+ const last = sorted[sorted.length - 1]?.at ?? first;
1233
+ const changedBetween = args.changeTimestamps.some((at) => at > first && at < last);
1234
+ if (changedBetween)
1235
+ continue;
1236
+ return signal("search_loop", "warning", {
1237
+ repeatedQuery: query,
1238
+ repeatCount: occurrences.length
1239
+ }, "consider_escalation");
1240
+ }
1241
+ return null;
1242
+ }
1243
+ function detectNoProgressCheckpointsV1(args) {
1244
+ const span = consecutiveNoGrowthSpan(args.checkpoints, (checkpoint) => [
1245
+ ...setKey(checkpoint.changedFiles),
1246
+ ...setKey(checkpoint.validationRefs).map((ref) => `validation:${ref}`)
1247
+ ]);
1248
+ if (span < 2)
1249
+ return null;
1250
+ return signal("no_progress_checkpoints", span >= 3 ? "warning" : "info", { checkpointSpan: span }, span >= 3 ? "consider_escalation" : "continue");
1251
+ }
1252
+ function detectValidationStuckV1(args) {
1253
+ let span = 1;
1254
+ let repeated = [];
1255
+ for (let index = 1;index < args.checkpoints.length; index += 1) {
1256
+ const previous = new Set(args.checkpoints[index - 1]?.failingValidationRefs ?? []);
1257
+ const current = setKey(args.checkpoints[index]?.failingValidationRefs ?? []);
1258
+ const overlap = current.filter((ref) => previous.has(ref));
1259
+ if (overlap.length > 0) {
1260
+ span += 1;
1261
+ repeated = overlap;
1262
+ } else {
1263
+ span = 1;
1264
+ repeated = [];
1265
+ }
1266
+ }
1267
+ if (span < 2 || repeated.length === 0)
1268
+ return null;
1269
+ return signal("validation_stuck", "warning", {
1270
+ checkpointSpan: span,
1271
+ failingValidationRefs: repeated
1272
+ }, "consider_escalation");
1273
+ }
1274
+ function buildGoalProgressObservationsV1(inputs) {
1275
+ const checkpoints = (inputs.checkpoints ?? []).map((checkpoint) => ({
1276
+ changedFiles: checkpoint.changedFiles ?? [],
1277
+ validationRefs: checkpoint.validationRefs ?? [],
1278
+ failingValidationRefs: checkpoint.failingValidationRefs ?? []
1279
+ }));
1280
+ const signals = [
1281
+ inputs.searchQueries ? detectSearchLoopV1({ searchQueries: inputs.searchQueries, changeTimestamps: inputs.changeTimestamps ?? [] }) : null,
1282
+ checkpoints.length > 0 ? detectNoProgressCheckpointsV1({ checkpoints }) : null,
1283
+ checkpoints.length > 0 ? detectValidationStuckV1({ checkpoints }) : null
1284
+ ].filter((item) => Boolean(item));
1285
+ return signals.map((progressSignal, index) => ({
1286
+ kind: "goal_lifecycle_observation",
1287
+ observationKind: "progress_observation",
1288
+ observationId: `goal-progress:${progressSignal.signal}:${index}`,
1289
+ title: progressSignal.signal.replace(/_/g, " "),
1290
+ summary: progressSignal.recommendation === "consider_escalation" ? "Progress signal suggests considering escalation." : "Progress signal suggests continuing with the current approach.",
1291
+ targetRefs: [],
1292
+ filePaths: [],
1293
+ evidenceRefs: progressSignal.evidence.failingValidationRefs ?? [],
1294
+ serviceConnectionIds: [],
1295
+ confidence: progressSignal.severity === "warning" ? 0.8 : 0.55,
1296
+ rank: progressSignal.severity === "warning" ? 70 : 45,
1297
+ reasonCodes: [`goal_progress:${progressSignal.signal}`, "goal_progress:advisory_only"],
1298
+ progressSignal,
1299
+ promotion: {
1300
+ candidateOnly: true,
1301
+ rankingUseOnly: true,
1302
+ eligibleForPromotionReview: false,
1303
+ requiresUserConfirmation: true,
1304
+ requiresRepeatedEvidence: true,
1305
+ requiresOmPolicyCheck: true,
1306
+ writeAuthority: false,
1307
+ memoryWrite: false,
1308
+ truthWrite: false,
1309
+ blockedReasons: ["progress_signal:no_authority"]
1310
+ },
1311
+ noAuthority: true
1312
+ }));
1313
+ }
1314
+ function signal(signalName, severity, evidence, recommendation) {
1315
+ return {
1316
+ kind: "goal_progress_signal",
1317
+ schemaVersion: GOAL_LIFECYCLE_SCHEMA_VERSION,
1318
+ signal: signalName,
1319
+ severity,
1320
+ evidence,
1321
+ recommendation,
1322
+ noAuthority: true
1323
+ };
1324
+ }
1325
+ function normalizeQuery(query) {
1326
+ return query.trim().toLowerCase().replace(/\s+/g, " ");
1327
+ }
1328
+ function setKey(values) {
1329
+ return [...new Set(values.map((value) => value.trim()).filter(Boolean))].sort();
1330
+ }
1331
+ function consecutiveNoGrowthSpan(items, keyFor) {
1332
+ let span = 1;
1333
+ for (let index = 1;index < items.length; index += 1) {
1334
+ const previous = new Set(keyFor(items[index - 1]));
1335
+ const current = keyFor(items[index]);
1336
+ const grew = current.some((value) => !previous.has(value));
1337
+ span = grew ? 1 : span + 1;
1338
+ }
1339
+ return span;
1340
+ }
1341
+
1342
+ // ../core/src/goalLifecycle/builders.ts
1343
+ var COMPACT_REF_LIMIT2 = 12;
1344
+ var MAX_OBSERVATIONS = 12;
1345
+ var MAX_MEMORY_CANDIDATES = 12;
1346
+ var MAX_FILE_OBSERVATION_CANDIDATES = 50;
1347
+ var UNSAFE_KEY_PATTERN = /(^|_|\b)(rawtranscript|transcript|messages|rawoutput|commandoutput|stdout|stderr|secret|apikey|api_key|token|memorycontent|providercall)(\b|_|$)/i;
1348
+ function buildGoalLifecycleV1({
1349
+ args,
1350
+ stage = lifecycleStageFromArgs(args),
1351
+ goal,
1352
+ goalSession,
1353
+ contextPacket,
1354
+ serviceConnectionIds = collectGoalServiceConnectionIdsV1(args),
1355
+ generatedAt,
1356
+ maxObservations = MAX_OBSERVATIONS,
1357
+ progressInputs
1358
+ }) {
1359
+ const normalizedSession = goalSession ?? buildGoalSessionV1({ args, goal });
1360
+ const stageArgs = lifecycleStageArgs(args, stage);
1361
+ const contextSummary = contextPacket ? summarizeContextPacket(contextPacket) : undefined;
1362
+ const evidence = collectLifecycleEvidence({
1363
+ args,
1364
+ stage,
1365
+ stageArgs,
1366
+ goalSession: normalizedSession,
1367
+ contextPacketSummary: contextSummary,
1368
+ serviceConnectionIds
1369
+ });
1370
+ const codeTrailUse = buildGoalLifecycleCodeTrailUseV1(evidence);
1371
+ const status = evaluateEvidenceStatus({ stage, contextSummary, evidence, codeTrailUse });
1372
+ const finalClaimPolicy = buildFinalClaimPolicy(status, evidence);
1373
+ const evidenceStatusDetail = buildEvidenceStatusDetail({ status, evidence, contextSummary, finalClaimPolicy });
1374
+ const taskLinks = buildTaskLinks(evidence, normalizedSession);
1375
+ const observations = buildGoalLifecycleObservationsV1({
1376
+ goal,
1377
+ status,
1378
+ evidence,
1379
+ contextSummary,
1380
+ codeTrailUse,
1381
+ maxObservations,
1382
+ progressInputs
1383
+ });
1384
+ const rankingHints = buildObservationRankingHintsV1(observations.visible);
1385
+ const feedbackLoops = buildLifecycleFeedbackLoops(stage);
1386
+ const lifecycleId = `goal-lifecycle:${stableHash2({
1387
+ stage,
1388
+ goal,
1389
+ goalSessionId: normalizedSession.goalSessionId,
1390
+ contextPacketId: contextSummary?.packetId,
1391
+ changedFiles: evidence.changedFiles,
1392
+ validationRefs: evidence.validationRefs,
1393
+ diffRefs: evidence.diffRefs,
1394
+ codeTrailRefs: evidence.codeTrailRefs,
1395
+ status
1396
+ })}`;
1397
+ const memoryCandidates = buildGoalLifecycleMemoryCandidatesV1({
1398
+ lifecycleId,
1399
+ stage,
1400
+ goal,
1401
+ goalSession: normalizedSession,
1402
+ status,
1403
+ observations: observations.visible,
1404
+ taskLinks,
1405
+ evidence
1406
+ });
1407
+ return removeUndefined2({
1408
+ kind: "rhei_code_goal_lifecycle",
1409
+ schemaVersion: 1,
1410
+ lifecycleId,
1411
+ stage,
1412
+ phase: stage,
1413
+ status: lifecycleStatusForStage(stage, status),
1414
+ goal,
1415
+ goalSession: normalizedSession,
1416
+ goalSessionId: normalizedSession.goalSessionId,
1417
+ activeGoalId: normalizedSession.activeGoalId,
1418
+ parentGoalId: normalizedSession.parentGoalId,
1419
+ supersedesGoalId: normalizedSession.supersedesGoalId,
1420
+ repoPath: cleanString3(args["repoPath"]),
1421
+ projectId: cleanString3(args["projectId"]),
1422
+ repoId: cleanString3(args["repoId"]),
1423
+ evidenceStatus: status,
1424
+ evidenceStatusDetail,
1425
+ evidenceStatusReasonCodes: evidenceStatusReasonCodes(status, evidence, contextSummary, codeTrailUse),
1426
+ taskLinks,
1427
+ contextPacket: contextSummary,
1428
+ codeTrailUse,
1429
+ finalClaimPolicy,
1430
+ observations: observations.visible,
1431
+ observationsOmitted: omittedAfterLimit2(observations.total, maxObservations),
1432
+ memoryCandidates: memoryCandidates.slice(0, MAX_MEMORY_CANDIDATES),
1433
+ memoryCandidatesOmitted: omittedAfterLimit2(memoryCandidates.length, MAX_MEMORY_CANDIDATES),
1434
+ rankingHints: rankingHints.slice(0, COMPACT_REF_LIMIT2),
1435
+ rankingHintsOmitted: omittedAfterLimit2(rankingHints.length, COMPACT_REF_LIMIT2),
1436
+ nextAction: nextActionForStatus(stage, status),
1437
+ feedbackLoops,
1438
+ generatedAt,
1439
+ ...buildGoalIntelligenceGuardrailsV1()
1440
+ });
1441
+ }
1442
+ function buildGoalStartLifecycleV1(args) {
1443
+ return buildGoalLifecycleV1({ ...args, stage: "start" });
1444
+ }
1445
+ function buildGoalCheckpointLifecycleV1(args) {
1446
+ return buildGoalLifecycleV1({ ...args, stage: "checkpoint" });
1447
+ }
1448
+ function buildGoalFinishLifecycleV1(args) {
1449
+ return buildGoalLifecycleV1({ ...args, stage: "finish" });
1450
+ }
1451
+ function buildGoalLifecycleCodeTrailUseV1(evidence) {
1452
+ if (evidence.hasUnsafePayload) {
1453
+ return {
1454
+ status: "blocked_unsafe_payload",
1455
+ codeTrailRefs: [],
1456
+ codeChangeStoryRefs: [],
1457
+ blockers: ["goal_lifecycle:blocked_unsafe_payload"],
1458
+ noAuthority: true
1459
+ };
1460
+ }
1461
+ if (evidence.codeTrailImportRefs.length > 0 || evidence.codeTrailRefs.length > 0) {
1462
+ return removeUndefined2({
1463
+ status: evidence.stageArgs["durableImportExplicit"] === true ? "imported_by_explicit_durable_path" : "linked_existing_import",
1464
+ importId: evidence.codeTrailImportRefs[0],
1465
+ codeTrailImportId: evidence.codeTrailImportRefs[0],
1466
+ trailHash: cleanString3(evidence.stageArgs["trailHash"]),
1467
+ sourceMcpRequestId: cleanString3(evidence.stageArgs["sourceMcpRequestId"]),
1468
+ sourceMcpRunId: cleanString3(evidence.stageArgs["sourceMcpRunId"]),
1469
+ codeTrailRefs: evidence.codeTrailRefs,
1470
+ codeChangeStoryRefs: evidence.codeChangeStoryRefs,
1471
+ blockers: [],
1472
+ noAuthority: true
1473
+ });
1474
+ }
1475
+ if (evidence.stage === "finish" && (evidence.diffRefs.length > 0 || evidence.changedFiles.length > 0) && (evidence.validationRefs.length > 0 || evidence.hasValidationResult || evidence.hasExecutionReceipt)) {
1476
+ const candidateRef = `code-trail-import-candidate:${stableHash2({
1477
+ changedFiles: evidence.changedFiles,
1478
+ validationRefs: evidence.validationRefs,
1479
+ diffRefs: evidence.diffRefs,
1480
+ receiptRefs: evidence.receiptRefs
1481
+ })}`;
1482
+ return {
1483
+ status: "import_candidate_emitted",
1484
+ codeTrailRefs: [],
1485
+ codeChangeStoryRefs: [],
1486
+ importCandidateRef: candidateRef,
1487
+ importCandidateSummary: {
1488
+ entryCount: Math.max(1, evidence.changedFiles.length + evidence.validationRefs.length),
1489
+ linkCount: evidence.evidenceRefs.length,
1490
+ gapCount: evidence.missingProofRefs.length,
1491
+ truncationCount: evidence.truncatedRefs.length,
1492
+ safeForImport: true
1493
+ },
1494
+ blockers: [],
1495
+ noAuthority: true
1496
+ };
1497
+ }
1498
+ return {
1499
+ status: "unavailable",
1500
+ codeTrailRefs: [],
1501
+ codeChangeStoryRefs: [],
1502
+ blockers: evidence.stage === "finish" ? ["goal_lifecycle:missing_code_trail_use"] : [],
1503
+ noAuthority: true
1504
+ };
1505
+ }
1506
+ function collectLifecycleEvidence(args) {
1507
+ const agentEditSession = asRecord2(args.stageArgs["agentEditSession"]) ?? asRecord2(args.args["agentEditSession"]) ?? asRecord2(args.args["agentEditSessionOutput"]);
1508
+ const validationResult = asRecord2(args.stageArgs["validationResult"]) ?? asRecord2(args.args["validationResult"]);
1509
+ const executionReceipt = asRecord2(args.stageArgs["executionReceipt"]) ?? asRecord2(args.args["executionReceipt"]);
1510
+ const changedFiles = uniqueStrings3([
1511
+ ...stringList3(args.args["changedFiles"]),
1512
+ ...stringList3(args.stageArgs["changedFiles"]),
1513
+ ...stringList3(agentEditSession?.["changedFiles"]),
1514
+ ...stringList3(agentEditSession?.["primaryEditFiles"])
1515
+ ]);
1516
+ const finalDiffRef = cleanString3(args.stageArgs["finalDiffRef"]) ?? cleanString3(args.args["finalDiffRef"]) ?? cleanString3(agentEditSession?.["finalDiffRef"]);
1517
+ const reverseDiffRef = cleanString3(args.stageArgs["reverseDiffRef"]) ?? cleanString3(args.args["reverseDiffRef"]) ?? cleanString3(agentEditSession?.["reverseDiffRef"]);
1518
+ const diffRefs = uniqueStrings3([
1519
+ ...stringList3(args.args["diffRefs"]),
1520
+ ...stringList3(args.stageArgs["diffRefs"]),
1521
+ ...stringList3(agentEditSession?.["diffRefs"]),
1522
+ finalDiffRef,
1523
+ reverseDiffRef
1524
+ ]);
1525
+ const validationRefs = uniqueStrings3([
1526
+ ...args.goalSession.validationRefs,
1527
+ ...stringList3(args.args["validationRefs"]),
1528
+ ...stringList3(args.stageArgs["validationRefs"]),
1529
+ ...stringList3(agentEditSession?.["validationRefs"]),
1530
+ cleanString3(validationResult?.["ref"]),
1531
+ cleanString3(validationResult?.["receiptRef"])
1532
+ ]);
1533
+ const codeTrailImportRefs = uniqueStrings3([
1534
+ cleanString3(args.args["codeTrailImportRef"]),
1535
+ cleanString3(args.stageArgs["codeTrailImportRef"]),
1536
+ cleanString3(agentEditSession?.["codeTrailImportRef"])
1537
+ ]);
1538
+ const codeTrailRefs = uniqueStrings3([
1539
+ ...args.goalSession.codeTrailRefs,
1540
+ ...stringList3(args.args["codeTrailRefs"]),
1541
+ ...stringList3(args.stageArgs["codeTrailRefs"]),
1542
+ ...stringList3(agentEditSession?.["codeTrailRefs"]),
1543
+ ...codeTrailImportRefs
1544
+ ]);
1545
+ const prReviewRefs = uniqueStrings3([
1546
+ ...args.goalSession.prReviewRefs,
1547
+ ...stringList3(args.args["prReviewRefs"]),
1548
+ ...stringList3(args.stageArgs["prReviewRefs"]),
1549
+ cleanString3(args.stageArgs["prSnapshotId"]),
1550
+ cleanString3(args.stageArgs["reviewRoomId"])
1551
+ ]);
1552
+ const receiptRefs = uniqueStrings3([
1553
+ ...stringList3(args.args["receiptRefs"]),
1554
+ ...stringList3(args.stageArgs["receiptRefs"]),
1555
+ cleanString3(executionReceipt?.["receiptId"]),
1556
+ cleanString3(executionReceipt?.["executionReceiptId"])
1557
+ ]);
1558
+ const staleRefs = uniqueStrings3([
1559
+ ...args.goalSession.staleRefs,
1560
+ ...stringList3(args.args["staleRefs"]),
1561
+ ...stringList3(args.stageArgs["staleRefs"])
1562
+ ]);
1563
+ const truncatedRefs = uniqueStrings3([
1564
+ ...stringList3(args.args["truncatedRefs"]),
1565
+ ...stringList3(args.stageArgs["truncatedRefs"]),
1566
+ ...stringList3(args.stageArgs["truncation"]),
1567
+ args.contextPacketSummary?.truncated ? args.contextPacketSummary.packetId : undefined
1568
+ ]);
1569
+ const fallbackStatus = fallbackStatusValue(cleanString3(args.stageArgs["fallbackStatus"]) ?? cleanString3(args.args["fallbackStatus"]));
1570
+ const evidenceRefs = uniqueStrings3([
1571
+ ...collectGoalEvidenceRefsV1(args.args, args.stageArgs),
1572
+ ...validationRefs,
1573
+ ...diffRefs,
1574
+ ...receiptRefs,
1575
+ ...codeTrailRefs,
1576
+ ...prReviewRefs,
1577
+ ...changedFiles
1578
+ ]);
1579
+ return {
1580
+ stage: args.stage,
1581
+ stageArgs: args.stageArgs,
1582
+ goalSession: args.goalSession,
1583
+ changedFiles,
1584
+ validationRefs,
1585
+ diffRefs,
1586
+ codeTrailRefs,
1587
+ codeTrailImportRefs,
1588
+ codeChangeStoryRefs: uniqueStrings3([
1589
+ ...stringList3(args.args["codeChangeStoryRefs"]),
1590
+ ...stringList3(args.stageArgs["codeChangeStoryRefs"])
1591
+ ]),
1592
+ prReviewRefs,
1593
+ receiptRefs,
1594
+ serviceConnectionIds: uniqueStrings3([
1595
+ ...args.serviceConnectionIds,
1596
+ ...args.goalSession.serviceConnectionIds,
1597
+ ...stringList3(args.stageArgs["serviceConnectionIds"])
1598
+ ]),
1599
+ staleRefs,
1600
+ truncatedRefs,
1601
+ missingProofRefs: uniqueStrings3([
1602
+ ...stringList3(args.args["missingProofRefs"]),
1603
+ ...stringList3(args.stageArgs["missingProofRefs"])
1604
+ ]),
1605
+ fallbackRefs: uniqueStrings3([
1606
+ ...stringList3(args.args["fallbackRefs"]),
1607
+ ...stringList3(args.stageArgs["fallbackRefs"])
1608
+ ]),
1609
+ fallbackStatus,
1610
+ hasValidationResult: Boolean(validationResult),
1611
+ hasExecutionReceipt: Boolean(executionReceipt),
1612
+ hasNoChangeProof: args.stageArgs["noChangeProof"] === true || args.args["noChangeProof"] === true,
1613
+ hasActiveEditSession: Boolean(agentEditSession && !["done", "completed", "failed", "blocked"].includes(cleanString3(agentEditSession["status"]) ?? "")),
1614
+ hasUnsafePayload: hasUnsafeLifecyclePayload(args.stageArgs) || hasUnsafeLifecyclePayload(args.args),
1615
+ evidenceRefs
1616
+ };
1617
+ }
1618
+ function evaluateEvidenceStatus(args) {
1619
+ if (args.evidence.hasUnsafePayload)
1620
+ return "blocked_unsafe_payload";
1621
+ if (args.stage === "start") {
1622
+ if ((args.contextSummary?.contentSliceCount ?? 0) > 0)
1623
+ return "context_ready";
1624
+ return "planning_only";
1625
+ }
1626
+ if (args.stage === "finish") {
1627
+ const hasValidation = args.evidence.validationRefs.length > 0 || args.evidence.hasValidationResult || args.evidence.hasExecutionReceipt;
1628
+ const hasChangeProof = args.evidence.changedFiles.length === 0 ? args.evidence.hasNoChangeProof || args.evidence.diffRefs.length > 0 : args.evidence.diffRefs.length > 0;
1629
+ const hasTrailUse = args.codeTrailUse.status === "linked_existing_import" || args.codeTrailUse.status === "import_candidate_emitted" || args.codeTrailUse.status === "imported_by_explicit_durable_path";
1630
+ if (!hasValidation || !hasChangeProof || !hasTrailUse || args.evidence.missingProofRefs.length > 0)
1631
+ return "blocked_missing_proof";
1632
+ if (args.evidence.staleRefs.length > 0 || args.evidence.truncatedRefs.length > 0)
1633
+ return "blocked_stale_or_truncated";
1634
+ return "finish_ready_report_only";
1635
+ }
1636
+ if (args.evidence.staleRefs.length > 0 || args.evidence.truncatedRefs.length > 0)
1637
+ return "blocked_stale_or_truncated";
1638
+ if (args.stage === "checkpoint") {
1639
+ if (args.evidence.validationRefs.length > 0 || args.evidence.hasValidationResult)
1640
+ return "validation_linked";
1641
+ if (args.evidence.hasActiveEditSession)
1642
+ return "work_in_progress";
1643
+ if (args.evidence.changedFiles.length > 0 || args.evidence.diffRefs.length > 0 || args.evidence.prReviewRefs.length > 0)
1644
+ return "partial_evidence";
1645
+ return "blocked_missing_proof";
1646
+ }
1647
+ return args.evidence.validationRefs.length > 0 ? "validation_linked" : "partial_evidence";
1648
+ }
1649
+ function buildFinalClaimPolicy(status, evidence) {
1650
+ const blockers = uniqueStrings3([
1651
+ status.startsWith("blocked_") ? status : undefined,
1652
+ ...evidence.missingProofRefs.map((ref) => `missing:${ref}`),
1653
+ ...evidence.staleRefs.map((ref) => `stale:${ref}`),
1654
+ ...evidence.truncatedRefs.map((ref) => `truncated:${ref}`)
1655
+ ]);
1656
+ const absenceProof = asRecord2(evidence.stageArgs["absenceProof"]);
1657
+ const canClaimAbsence = status === "finish_ready_report_only" && absenceProof?.["complete"] === true && evidence.staleRefs.length === 0 && evidence.truncatedRefs.length === 0;
1658
+ return {
1659
+ canClaimDone: status === "finish_ready_report_only",
1660
+ canClaimAbsence,
1661
+ blockers,
1662
+ staleRefs: evidence.staleRefs,
1663
+ truncatedRefs: evidence.truncatedRefs,
1664
+ missingProofRefs: evidence.missingProofRefs
1665
+ };
1666
+ }
1667
+ function buildEvidenceStatusDetail(args) {
1668
+ const blocked = args.status.startsWith("blocked_");
1669
+ const finalClaimsAllowed = args.finalClaimPolicy.canClaimDone;
1670
+ const validationRefs = args.evidence.validationRefs.slice(0, COMPACT_REF_LIMIT2);
1671
+ return {
1672
+ kind: "goal_lifecycle_evidence_status",
1673
+ schemaVersion: 1,
1674
+ status: blocked ? "blocked" : args.status === "planning_only" || args.status === "partial_evidence" ? "degraded" : "ready",
1675
+ runtimeFreshness: {
1676
+ status: args.evidence.staleRefs.length > 0 ? "stale" : "unknown",
1677
+ reasonCodes: args.evidence.staleRefs.length > 0 ? ["goal_lifecycle:stale_ref"] : ["goal_lifecycle:runtime_freshness_not_claimed"]
1678
+ },
1679
+ coverage: {
1680
+ status: args.contextSummary?.truncated || args.evidence.truncatedRefs.length > 0 ? "truncated" : args.status === "planning_only" || args.status === "partial_evidence" ? "partial" : "complete",
1681
+ selectedFileCount: args.contextSummary?.primaryEditFiles.length ?? args.evidence.changedFiles.length,
1682
+ omittedRangeCount: args.contextSummary?.truncated ? 1 : 0,
1683
+ truncated: Boolean(args.contextSummary?.truncated || args.evidence.truncatedRefs.length > 0),
1684
+ reasonCodes: evidenceCoverageReasonCodes(args.status, args.contextSummary, args.evidence)
1685
+ },
1686
+ proof: {
1687
+ status: blocked ? "blocked" : finalClaimsAllowed ? "proved" : args.evidence.validationRefs.length > 0 ? "evidence_only" : "not_proved",
1688
+ validationRefs,
1689
+ absenceClaimsAllowed: args.finalClaimPolicy.canClaimAbsence,
1690
+ finalClaimsAllowed,
1691
+ reasonCodes: evidenceProofReasonCodes(args.status, finalClaimsAllowed)
1692
+ },
1693
+ fallback: {
1694
+ status: args.evidence.fallbackStatus,
1695
+ fallbackRefs: args.evidence.fallbackRefs.slice(0, COMPACT_REF_LIMIT2),
1696
+ reasonCodes: args.evidence.fallbackRefs.length > 0 ? ["goal_lifecycle:fallback_refs_linked"] : ["goal_lifecycle:fallback_not_needed"]
1697
+ },
1698
+ agentTrust: {
1699
+ level: finalClaimsAllowed ? "bounded" : "advisory",
1700
+ basisRefs: uniqueStrings3([...args.evidence.validationRefs, ...args.evidence.codeTrailRefs, ...args.evidence.receiptRefs]).slice(0, COMPACT_REF_LIMIT2),
1701
+ reasonCodes: ["goal_lifecycle:report_only_no_authority"]
1702
+ },
1703
+ noAuthority: true
1704
+ };
1705
+ }
1706
+ function buildTaskLinks(evidence, goalSession) {
1707
+ const links = [];
1708
+ if (goalSession.goalSessionId) {
1709
+ links.push(taskLink("goal_session", goalSession.goalSessionId, "source", undefined, [], evidence.evidenceRefs));
1710
+ }
1711
+ for (const ref of evidence.validationRefs)
1712
+ links.push(taskLink("validation_receipt", ref, "validation", undefined, [], [ref]));
1713
+ for (const ref of evidence.prReviewRefs)
1714
+ links.push(taskLink(ref.includes("review-room") ? "review_room" : "pr_snapshot", ref, "review", undefined, [], [ref]));
1715
+ for (const ref of evidence.serviceConnectionIds)
1716
+ links.push(taskLink("service_connection", ref, "service", undefined, [], [ref]));
1717
+ const editSessionId = cleanString3(evidence.stageArgs["editSessionId"]) ?? cleanString3(evidence.stageArgs["agentEditSessionId"]) ?? cleanString3(asRecord2(evidence.stageArgs["agentEditSession"])?.["editSessionId"]) ?? cleanString3(asRecord2(evidence.stageArgs["agentEditSession"])?.["id"]);
1718
+ if (editSessionId) {
1719
+ links.push(taskLink("agent_edit_session", editSessionId, "work", cleanString3(asRecord2(evidence.stageArgs["agentEditSession"])?.["status"]), evidence.changedFiles, evidence.evidenceRefs));
1720
+ }
1721
+ const workroomRunId = cleanString3(evidence.stageArgs["workroomRunId"]);
1722
+ if (workroomRunId)
1723
+ links.push(taskLink("code_workroom_run", workroomRunId, "work", undefined, evidence.changedFiles, evidence.evidenceRefs));
1724
+ const patchRunId = cleanString3(evidence.stageArgs["patchRunId"]);
1725
+ if (patchRunId)
1726
+ links.push(taskLink("code_patch_run", patchRunId, "work", undefined, evidence.changedFiles, evidence.evidenceRefs));
1727
+ return uniqueTaskLinks(links);
1728
+ }
1729
+ function buildGoalLifecycleObservationsV1(args) {
1730
+ const candidates = [];
1731
+ const evidenceRefs = uniqueStrings3([
1732
+ ...args.evidence.evidenceRefs,
1733
+ ...args.codeTrailUse.codeTrailRefs,
1734
+ args.codeTrailUse.importCandidateRef
1735
+ ]);
1736
+ if ((args.evidence.changedFiles.length > 0 || evidenceRefs.length > 0) && args.evidence.stage !== "start") {
1737
+ candidates.push(observation({
1738
+ observationKind: "worktask_observation",
1739
+ title: `Goal ${args.evidence.stage} evidence`,
1740
+ summary: cleanString3(args.evidence.stageArgs["summary"]) ?? "Goal lifecycle evidence was captured as report-only task context.",
1741
+ targetRefs: evidenceRefs,
1742
+ filePaths: args.evidence.changedFiles,
1743
+ evidenceRefs,
1744
+ serviceConnectionIds: args.evidence.serviceConnectionIds,
1745
+ rank: observationRank(args.evidence, args.contextSummary, args.codeTrailUse),
1746
+ status: args.status,
1747
+ reasonCodes: [`goal_lifecycle:${args.evidence.stage}`, "goal_lifecycle:ranking_hint_only"]
1748
+ }));
1749
+ }
1750
+ const filePaths = uniqueStrings3([
1751
+ ...args.evidence.changedFiles,
1752
+ ...args.contextSummary?.primaryEditFiles ?? []
1753
+ ]).slice(0, MAX_FILE_OBSERVATION_CANDIDATES);
1754
+ for (const filePath of filePaths) {
1755
+ candidates.push(observation({
1756
+ observationKind: "file_observation",
1757
+ title: `File evidence: ${filePath}`,
1758
+ summary: "File participated in the goal lifecycle evidence set; use as a ranking hint only.",
1759
+ targetRefs: [filePath],
1760
+ filePaths: [filePath],
1761
+ evidenceRefs,
1762
+ serviceConnectionIds: args.evidence.serviceConnectionIds,
1763
+ rank: observationRank(args.evidence, args.contextSummary, args.codeTrailUse) + (args.contextSummary?.primaryEditFiles.includes(filePath) ? 10 : 0),
1764
+ status: args.status,
1765
+ reasonCodes: ["goal_lifecycle:file_observation", "goal_lifecycle:ranking_hint_only"]
1766
+ }));
1767
+ }
1768
+ if (args.evidence.validationRefs.length > 0 || args.evidence.hasValidationResult) {
1769
+ candidates.push(observation({
1770
+ observationKind: "validation_observation",
1771
+ title: "Validation evidence linked",
1772
+ summary: "Validation was linked to the lifecycle as evidence only.",
1773
+ targetRefs: args.evidence.validationRefs,
1774
+ filePaths: args.evidence.changedFiles,
1775
+ evidenceRefs,
1776
+ serviceConnectionIds: args.evidence.serviceConnectionIds,
1777
+ rank: observationRank(args.evidence, args.contextSummary, args.codeTrailUse) + 30,
1778
+ status: args.status,
1779
+ reasonCodes: ["goal_lifecycle:validation_observation", "goal_lifecycle:ranking_hint_only"]
1780
+ }));
1781
+ }
1782
+ if (args.status.startsWith("blocked_")) {
1783
+ candidates.push(observation({
1784
+ observationKind: "risk_observation",
1785
+ title: "Lifecycle proof blocked",
1786
+ summary: `Lifecycle evidence cannot support final claims: ${args.status}.`,
1787
+ targetRefs: uniqueStrings3([...args.evidence.staleRefs, ...args.evidence.truncatedRefs, ...args.evidence.missingProofRefs]),
1788
+ filePaths: args.evidence.changedFiles,
1789
+ evidenceRefs,
1790
+ serviceConnectionIds: args.evidence.serviceConnectionIds,
1791
+ rank: 20,
1792
+ status: args.status,
1793
+ reasonCodes: [`goal_lifecycle:${args.status}`, "goal_lifecycle:risk_observation"]
1794
+ }));
1795
+ }
1796
+ if (args.progressInputs) {
1797
+ candidates.push(...buildGoalProgressObservationsV1(args.progressInputs));
1798
+ }
1799
+ const sorted = candidates.sort((left, right) => right.rank - left.rank || left.observationId.localeCompare(right.observationId));
1800
+ return { visible: sorted.slice(0, args.maxObservations), total: sorted.length };
1801
+ }
1802
+ function buildGoalLifecycleMemoryCandidatesV1(args) {
1803
+ if (args.stage === "start")
1804
+ return [];
1805
+ const taskRefs = uniqueStrings3(args.taskLinks.map((link) => link.ref)).slice(0, COMPACT_REF_LIMIT2);
1806
+ return args.observations.filter((item) => item.observationKind === "file_observation" || item.observationKind === "worktask_observation" || item.observationKind === "validation_observation" || item.observationKind === "risk_observation").map((observation) => {
1807
+ const candidateKind = lifecycleMemoryCandidateKind(observation);
1808
+ const status = lifecycleMemoryCandidateStatus(args.stage, args.status, observation);
1809
+ const blockedReasons = observation.promotion.blockedReasons;
1810
+ const identity = buildGoalMemoryCandidateIdentityV1({
1811
+ sourceKind: "goal_lifecycle",
1812
+ candidateKind,
1813
+ title: observation.title,
1814
+ summary: observation.summary,
1815
+ normalizedRule: observation.summary,
1816
+ goal: args.goal,
1817
+ goalSessionId: args.goalSession.goalSessionId,
1818
+ activeGoalId: args.goalSession.activeGoalId,
1819
+ parentGoalId: args.goalSession.parentGoalId,
1820
+ supersedesGoalId: args.goalSession.supersedesGoalId,
1821
+ sourceEventId: observation.observationId,
1822
+ sourceIds: goalMemoryCandidateSourceIdsV1([[args.lifecycleId, observation.observationId], observation.evidenceRefs]),
1823
+ targetRefs: observation.targetRefs,
1824
+ filePaths: observation.filePaths,
1825
+ evidenceRefs: observation.evidenceRefs,
1826
+ observationRefs: [observation.observationId],
1827
+ taskRefs,
1828
+ serviceConnectionIds: observation.serviceConnectionIds
1829
+ });
1830
+ return removeUndefined2({
1831
+ kind: "memory_candidate",
1832
+ candidateKind,
1833
+ title: observation.title,
1834
+ summary: observation.summary,
1835
+ normalizedRule: observation.summary,
1836
+ goal: args.goal,
1837
+ evidenceRefs: observation.evidenceRefs.slice(0, COMPACT_REF_LIMIT2),
1838
+ serviceConnectionIds: observation.serviceConnectionIds.slice(0, COMPACT_REF_LIMIT2),
1839
+ ...identity,
1840
+ sourceKind: "goal_lifecycle",
1841
+ sourceIds: goalMemoryCandidateSourceIdsV1([[args.lifecycleId, observation.observationId], observation.evidenceRefs]),
1842
+ goalSessionId: args.goalSession.goalSessionId,
1843
+ activeGoalId: args.goalSession.activeGoalId,
1844
+ parentGoalId: args.goalSession.parentGoalId,
1845
+ supersedesGoalId: args.goalSession.supersedesGoalId,
1846
+ targetRefs: observation.targetRefs.slice(0, COMPACT_REF_LIMIT2),
1847
+ filePaths: observation.filePaths.slice(0, COMPACT_REF_LIMIT2),
1848
+ observationRefs: [observation.observationId],
1849
+ taskRefs,
1850
+ codeTrailRefs: args.evidence.codeTrailRefs.slice(0, COMPACT_REF_LIMIT2),
1851
+ prReviewRefs: args.evidence.prReviewRefs.slice(0, COMPACT_REF_LIMIT2),
1852
+ confidence: observation.confidence,
1853
+ rank: observation.rank,
1854
+ status,
1855
+ promotionStatus: status,
1856
+ promotionBlockers: blockedReasons,
1857
+ reasonCodes: uniqueStrings3([
1858
+ ...observation.reasonCodes,
1859
+ `goal_memory:${candidateKind}`,
1860
+ `goal_memory:status:${status}`
1861
+ ]),
1862
+ candidateOnly: true,
1863
+ rankingUseOnly: observation.promotion.rankingUseOnly,
1864
+ requiresUserConfirmation: true,
1865
+ requiresRepeatedEvidence: observation.promotion.requiresRepeatedEvidence || status !== "ready_for_review",
1866
+ requiresOmPolicyCheck: true,
1867
+ memoryWrite: false,
1868
+ truthWrite: false,
1869
+ noMemoryWrite: true,
1870
+ promotionRequired: true,
1871
+ writeAuthority: false,
1872
+ promotion: {
1873
+ candidateOnly: true,
1874
+ rankingUseOnly: observation.promotion.rankingUseOnly,
1875
+ status,
1876
+ eligibleForPromotionReview: observation.promotion.eligibleForPromotionReview,
1877
+ requiresUserConfirmation: true,
1878
+ requiresRepeatedEvidence: observation.promotion.requiresRepeatedEvidence || status !== "ready_for_review",
1879
+ requiresOmPolicyCheck: true,
1880
+ promotionRequired: true,
1881
+ writeAuthority: false,
1882
+ memoryWrite: false,
1883
+ truthWrite: false,
1884
+ noMemoryWrite: true,
1885
+ blockedReasons
1886
+ },
1887
+ ...buildGoalIntelligenceGuardrailsV1()
1888
+ });
1889
+ }).sort((left, right) => (right.rank ?? 0) - (left.rank ?? 0) || (left.candidateId ?? "").localeCompare(right.candidateId ?? ""));
1890
+ }
1891
+ function lifecycleMemoryCandidateKind(observation) {
1892
+ if (observation.observationKind === "file_observation")
1893
+ return "lifecycle_file_pattern";
1894
+ if (observation.observationKind === "worktask_observation")
1895
+ return "lifecycle_worktask_pattern";
1896
+ if (observation.observationKind === "validation_observation")
1897
+ return "validation_practice";
1898
+ if (observation.observationKind === "risk_observation")
1899
+ return "risk_pattern";
1900
+ return "lifecycle_worktask_pattern";
1901
+ }
1902
+ function lifecycleMemoryCandidateStatus(stage, status, observation) {
1903
+ if (status.startsWith("blocked_") || !observation.promotion.eligibleForPromotionReview)
1904
+ return "needs_more_evidence";
1905
+ if (stage === "finish" && (status === "finish_ready_report_only" || status === "validation_linked"))
1906
+ return "ready_for_review";
1907
+ return "candidate";
1908
+ }
1909
+ function buildObservationRankingHintsV1(observations) {
1910
+ return observations.flatMap((item) => item.targetRefs.map((targetRef) => ({
1911
+ kind: "goal_lifecycle_ranking_hint",
1912
+ targetRef,
1913
+ weight: item.rank,
1914
+ reasonCodes: item.reasonCodes,
1915
+ sourceObservationId: item.observationId,
1916
+ noAuthority: true
1917
+ })));
1918
+ }
1919
+ function observation(args) {
1920
+ const blockedReasons = promotionBlockedReasons(args.status, args.evidenceRefs, args.summary);
1921
+ const eligibleForPromotionReview = blockedReasons.length === 0;
1922
+ const boundedRank = Math.max(0, Math.min(100, Math.round(args.rank)));
1923
+ return {
1924
+ kind: "goal_lifecycle_observation",
1925
+ observationKind: args.observationKind,
1926
+ observationId: `goal-observation:${stableHash2({
1927
+ kind: args.observationKind,
1928
+ targetRefs: args.targetRefs,
1929
+ evidenceRefs: args.evidenceRefs,
1930
+ summary: args.summary
1931
+ })}`,
1932
+ title: args.title.slice(0, 120),
1933
+ summary: args.summary.slice(0, 360),
1934
+ targetRefs: uniqueStrings3(args.targetRefs).slice(0, COMPACT_REF_LIMIT2),
1935
+ filePaths: uniqueStrings3(args.filePaths).slice(0, COMPACT_REF_LIMIT2),
1936
+ evidenceRefs: uniqueStrings3(args.evidenceRefs).slice(0, COMPACT_REF_LIMIT2),
1937
+ serviceConnectionIds: uniqueStrings3(args.serviceConnectionIds).slice(0, COMPACT_REF_LIMIT2),
1938
+ confidence: Math.max(0, Math.min(1, Number((boundedRank / 100).toFixed(2)))),
1939
+ rank: boundedRank,
1940
+ reasonCodes: uniqueStrings3(args.reasonCodes),
1941
+ promotion: {
1942
+ candidateOnly: true,
1943
+ rankingUseOnly: true,
1944
+ eligibleForPromotionReview,
1945
+ requiresUserConfirmation: true,
1946
+ requiresRepeatedEvidence: true,
1947
+ requiresOmPolicyCheck: true,
1948
+ writeAuthority: false,
1949
+ memoryWrite: false,
1950
+ truthWrite: false,
1951
+ blockedReasons
1952
+ },
1953
+ noAuthority: true
1954
+ };
1955
+ }
1956
+ function observationRank(evidence, contextSummary, codeTrailUse) {
1957
+ let score = 0;
1958
+ if (evidence.validationRefs.length > 0 || evidence.hasValidationResult)
1959
+ score += 30;
1960
+ if (codeTrailUse.status !== "unavailable")
1961
+ score += 25;
1962
+ if (evidence.diffRefs.length > 0)
1963
+ score += 20;
1964
+ if (evidence.prReviewRefs.length > 0)
1965
+ score += 15;
1966
+ if ((contextSummary?.primaryEditFiles.length ?? 0) > 0)
1967
+ score += 10;
1968
+ if (evidence.stageArgs["repoIntelligence"] || evidence.stageArgs["repoIntelligenceStatus"])
1969
+ score += 5;
1970
+ if (evidence.staleRefs.length > 0)
1971
+ score -= 30;
1972
+ if (evidence.truncatedRefs.length > 0)
1973
+ score -= 30;
1974
+ if (evidence.missingProofRefs.length > 0)
1975
+ score -= 40;
1976
+ if (evidence.hasUnsafePayload)
1977
+ score -= 20;
1978
+ return Math.max(0, Math.min(100, score));
1979
+ }
1980
+ function summarizeContextPacket(packet) {
1981
+ const record = packet;
1982
+ const slices = objectArray(record["contextSlices"]);
1983
+ const primaryEditFiles = objectArray(record["primaryEditFiles"]).map((item) => cleanString3(item["path"])).filter((path) => Boolean(path));
1984
+ const contentSliceCount = slices.filter((slice) => Boolean(asRecord2(slice["content"])?.["text"])).length;
1985
+ const contentBudget = asRecord2(record["contentBudget"]);
1986
+ return {
1987
+ packetId: cleanString3(record["packetId"]),
1988
+ primaryEditFiles: uniqueStrings3(primaryEditFiles),
1989
+ contextSliceCount: slices.length,
1990
+ contentSliceCount,
1991
+ truncated: Boolean(cleanString3(contentBudget?.["overflowReason"]) || slices.some((slice) => asRecord2(slice["content"])?.["truncated"] === true)),
1992
+ sourceRefs: stringList3(record["sourceRefs"]).slice(0, COMPACT_REF_LIMIT2),
1993
+ evidenceRefs: stringList3(record["evidenceRefs"]).slice(0, COMPACT_REF_LIMIT2),
1994
+ receiptRefs: stringList3(record["receiptRefs"]).slice(0, COMPACT_REF_LIMIT2),
1995
+ noAuthority: true
1996
+ };
1997
+ }
1998
+ function lifecycleStageFromArgs(args) {
1999
+ const lifecycle = asRecord2(args["goalLifecycle"]) ?? asRecord2(args["lifecycle"]);
2000
+ const explicit = cleanString3(lifecycle?.["stage"]) ?? cleanString3(lifecycle?.["phase"]);
2001
+ if (explicit === "start" || explicit === "steer" || explicit === "checkpoint" || explicit === "finish")
2002
+ return explicit;
2003
+ if (asRecord2(args["start"]))
2004
+ return "start";
2005
+ if (asRecord2(args["checkpoint"]))
2006
+ return "checkpoint";
2007
+ if (asRecord2(args["finish"]))
2008
+ return "finish";
2009
+ return "start";
2010
+ }
2011
+ function lifecycleStageArgs(args, stage) {
2012
+ const lifecycle = asRecord2(args["goalLifecycle"]) ?? asRecord2(args["lifecycle"]) ?? {};
2013
+ return {
2014
+ ...asRecord2(lifecycle[stage]),
2015
+ ...asRecord2(args[stage]),
2016
+ ...lifecycle
2017
+ };
2018
+ }
2019
+ function lifecycleStatusForStage(stage, status) {
2020
+ if (status.startsWith("blocked_"))
2021
+ return "blocked";
2022
+ if (stage === "start")
2023
+ return "started";
2024
+ if (stage === "checkpoint")
2025
+ return "checkpointed";
2026
+ if (stage === "finish")
2027
+ return "finished";
2028
+ return "continued";
2029
+ }
2030
+ function evidenceStatusReasonCodes(status, evidence, contextSummary, codeTrailUse) {
2031
+ return uniqueStrings3([
2032
+ `goal_lifecycle:${evidence.stage}`,
2033
+ `goal_lifecycle:${status}`,
2034
+ contextSummary?.contentSliceCount ? "goal_lifecycle:context_content_linked" : undefined,
2035
+ codeTrailUse.status !== "unavailable" ? `goal_lifecycle:code_trail:${codeTrailUse.status}` : undefined,
2036
+ evidence.validationRefs.length > 0 ? "goal_lifecycle:validation_refs_linked" : undefined,
2037
+ evidence.diffRefs.length > 0 ? "goal_lifecycle:diff_refs_linked" : undefined,
2038
+ evidence.staleRefs.length > 0 ? "goal_lifecycle:stale_ref" : undefined,
2039
+ evidence.truncatedRefs.length > 0 ? "goal_lifecycle:truncated_coverage" : undefined,
2040
+ evidence.hasUnsafePayload ? "goal_lifecycle:unsafe_payload_withheld" : undefined
2041
+ ]);
2042
+ }
2043
+ function evidenceCoverageReasonCodes(status, contextSummary, evidence) {
2044
+ return uniqueStrings3([
2045
+ contextSummary ? "goal_lifecycle:context_packet_summary" : undefined,
2046
+ contextSummary?.truncated || evidence.truncatedRefs.length > 0 ? "goal_lifecycle:coverage_truncated" : undefined,
2047
+ status === "planning_only" ? "goal_lifecycle:planner_only" : undefined,
2048
+ status === "context_ready" ? "goal_lifecycle:context_ready" : undefined
2049
+ ]);
2050
+ }
2051
+ function evidenceProofReasonCodes(status, finalClaimsAllowed) {
2052
+ return uniqueStrings3([
2053
+ finalClaimsAllowed ? "goal_lifecycle:finish_ready_report_only" : "goal_lifecycle:no_final_claim",
2054
+ status === "blocked_missing_proof" ? "goal_lifecycle:missing_proof" : undefined,
2055
+ status === "blocked_stale_or_truncated" ? "goal_lifecycle:stale_or_truncated_blocks_claims" : undefined,
2056
+ status === "blocked_unsafe_payload" ? "goal_lifecycle:unsafe_payload_blocks_claims" : undefined
2057
+ ]);
2058
+ }
2059
+ function promotionBlockedReasons(status, evidenceRefs, summary) {
2060
+ return uniqueStrings3([
2061
+ status !== "finish_ready_report_only" && status !== "validation_linked" ? "promotion:requires_finish_or_validation_linked_status" : undefined,
2062
+ evidenceRefs.length === 0 ? "promotion:requires_validation_or_code_trail_evidence" : undefined,
2063
+ status.startsWith("blocked_") ? "promotion:blocked_lifecycle_status" : undefined,
2064
+ summary.length > 360 ? "promotion:summary_too_long" : undefined
2065
+ ]);
2066
+ }
2067
+ function nextActionForStatus(stage, status) {
2068
+ if (status === "finish_ready_report_only") {
2069
+ return {
2070
+ tool: "rhei_code_trail_export",
2071
+ mode: "trail",
2072
+ reason: "Finish evidence is report-ready; import or export CodeTrail only through the explicit durable path.",
2073
+ noAuthority: true
2074
+ };
2075
+ }
2076
+ if (status.startsWith("blocked_")) {
2077
+ return {
2078
+ tool: "rhei_code_goal",
2079
+ mode: stage === "finish" ? "checkpoint" : "verify",
2080
+ reason: "Lifecycle evidence is blocked; add validation, freshness, diff, or proof refs before claiming completion.",
2081
+ noAuthority: true
2082
+ };
2083
+ }
2084
+ return {
2085
+ tool: "rhei_code_goal",
2086
+ mode: stage === "start" ? "checkpoint" : "finish",
2087
+ reason: "Continue the report-only lifecycle with bounded evidence refs.",
2088
+ noAuthority: true
2089
+ };
2090
+ }
2091
+ function buildLifecycleFeedbackLoops(stage) {
2092
+ if (stage === "steer")
2093
+ return buildGoalFeedbackLoopsV1({ mode: "steer" });
2094
+ return buildGoalFeedbackLoopsV1({ mode: stage });
2095
+ }
2096
+ function taskLink(kind, ref, role, status, filePaths, evidenceRefs) {
2097
+ return removeUndefined2({
2098
+ kind,
2099
+ ref,
2100
+ role,
2101
+ status,
2102
+ filePaths: uniqueStrings3(filePaths).slice(0, COMPACT_REF_LIMIT2),
2103
+ evidenceRefs: uniqueStrings3(evidenceRefs).slice(0, COMPACT_REF_LIMIT2),
2104
+ noAuthority: true
2105
+ });
2106
+ }
2107
+ function uniqueTaskLinks(links) {
2108
+ const seen = new Set;
2109
+ return links.filter((link) => {
2110
+ const key = `${link.kind}:${link.ref}:${link.role}`;
2111
+ if (seen.has(key))
2112
+ return false;
2113
+ seen.add(key);
2114
+ return true;
2115
+ });
2116
+ }
2117
+ function fallbackStatusValue(value) {
2118
+ if (value === "used" || value === "available" || value === "missing" || value === "blocked")
2119
+ return value;
2120
+ return "not_needed";
2121
+ }
2122
+ function hasUnsafeLifecyclePayload(value, depth = 0) {
2123
+ if (depth > 5)
2124
+ return false;
2125
+ const record = asRecord2(value);
2126
+ if (!record)
2127
+ return false;
2128
+ for (const [key, child] of Object.entries(record)) {
2129
+ if (UNSAFE_KEY_PATTERN.test(key) && child !== undefined && child !== null)
2130
+ return true;
2131
+ if (typeof child === "object" && hasUnsafeLifecyclePayload(child, depth + 1))
2132
+ return true;
2133
+ }
2134
+ return false;
2135
+ }
2136
+ function asRecord2(value) {
2137
+ if (!value || typeof value !== "object" || Array.isArray(value))
2138
+ return;
2139
+ return value;
2140
+ }
2141
+ function objectArray(value) {
2142
+ if (!Array.isArray(value))
2143
+ return [];
2144
+ return value.map((item) => asRecord2(item)).filter((item) => Boolean(item));
2145
+ }
2146
+ function stringList3(value) {
2147
+ if (!Array.isArray(value))
2148
+ return [];
2149
+ return value.map((item) => cleanString3(item)).filter((item) => Boolean(item));
2150
+ }
2151
+ function uniqueStrings3(values) {
2152
+ return Array.from(new Set(values.map((value) => value?.trim()).filter((value) => Boolean(value))));
2153
+ }
2154
+ function cleanString3(value) {
2155
+ if (typeof value !== "string")
2156
+ return;
2157
+ const text = value.trim();
2158
+ return text.length > 0 ? text : undefined;
2159
+ }
2160
+ function removeUndefined2(value) {
2161
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
2162
+ }
2163
+ function omittedAfterLimit2(total, limit) {
2164
+ return total > limit ? total - limit : undefined;
2165
+ }
2166
+ function stableHash2(value) {
2167
+ const text = stableJson2(value);
2168
+ let hash = 2166136261;
2169
+ for (let index = 0;index < text.length; index += 1) {
2170
+ hash ^= text.charCodeAt(index);
2171
+ hash = Math.imul(hash, 16777619);
2172
+ }
2173
+ return (hash >>> 0).toString(16).padStart(8, "0").slice(0, 12);
2174
+ }
2175
+ function stableJson2(value) {
2176
+ if (Array.isArray(value))
2177
+ return `[${value.map(stableJson2).join(",")}]`;
2178
+ if (value && typeof value === "object") {
2179
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson2(value[key])}`).join(",")}}`;
2180
+ }
2181
+ return JSON.stringify(value);
2182
+ }
2183
+ export {
2184
+ normalizeGoalMemoryTextV1,
2185
+ goalSessionHasContinuityV1,
2186
+ goalMemoryCandidateSourceIdsV1,
2187
+ detectValidationStuckV1,
2188
+ detectSearchLoopV1,
2189
+ detectNoProgressCheckpointsV1,
2190
+ collectGoalServiceConnectionIdsV1,
2191
+ collectGoalMemoryFilePathsV1,
2192
+ collectGoalEvidenceRefsV1,
2193
+ buildServiceImpactV1,
2194
+ buildPreferenceReplayV1,
2195
+ buildGoalStewardDecisionV1,
2196
+ buildGoalStartLifecycleV1,
2197
+ buildGoalSessionV1,
2198
+ buildGoalResumeV1,
2199
+ buildGoalProgressObservationsV1,
2200
+ buildGoalOutcomeFeedbackV1,
2201
+ buildGoalMemoryCandidateIdentityV1,
2202
+ buildGoalLifecycleV1,
2203
+ buildGoalLifecycleCodeTrailUseV1,
2204
+ buildGoalIntelligenceGuardrailsV1,
2205
+ buildGoalIntelligenceCommitV1,
2206
+ buildGoalFinishLifecycleV1,
2207
+ buildGoalFeedbackLoopsV1,
2208
+ buildGoalContinuityPacketV1,
2209
+ buildGoalCheckpointLifecycleV1,
2210
+ buildDiagnosticClosureV1,
2211
+ GOAL_STEWARD_DECISION_VALUES,
2212
+ GOAL_MEMORY_CANDIDATE_STATUS_VALUES,
2213
+ GOAL_MEMORY_CANDIDATE_SOURCE_KIND_VALUES,
2214
+ GOAL_MEMORY_CANDIDATE_KIND_VALUES,
2215
+ GOAL_LIFECYCLE_SCHEMA_VERSION,
2216
+ GOAL_INTELLIGENCE_SCHEMA_VERSION,
2217
+ GOAL_INTELLIGENCE_COMPACT_REF_LIMIT
2218
+ };