audit-tools 0.32.22 → 0.32.27

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 (126) hide show
  1. package/README.md +10 -4
  2. package/dist/audit/cli/conceptualDispatch.d.ts +11 -0
  3. package/dist/audit/cli/conceptualDispatch.d.ts.map +1 -1
  4. package/dist/audit/cli/conceptualDispatch.js +31 -1
  5. package/dist/audit/cli/conceptualDispatch.js.map +1 -1
  6. package/dist/audit/cli/nextStepHelpers.d.ts +46 -0
  7. package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
  8. package/dist/audit/cli/nextStepHelpers.js +14 -14
  9. package/dist/audit/cli/nextStepHelpers.js.map +1 -1
  10. package/dist/audit/contracts/workerSchemas.d.ts +4 -4
  11. package/dist/audit/contracts/wrapperResponse.d.ts +6 -6
  12. package/dist/audit/orchestrator/advance.d.ts +18 -19
  13. package/dist/audit/orchestrator/advance.d.ts.map +1 -1
  14. package/dist/audit/orchestrator/advance.js +32 -40
  15. package/dist/audit/orchestrator/advance.js.map +1 -1
  16. package/dist/audit/orchestrator/advanceTypes.d.ts +0 -17
  17. package/dist/audit/orchestrator/advanceTypes.d.ts.map +1 -1
  18. package/dist/audit/orchestrator/hostInputPause.d.ts +69 -0
  19. package/dist/audit/orchestrator/hostInputPause.d.ts.map +1 -0
  20. package/dist/audit/orchestrator/hostInputPause.js +90 -0
  21. package/dist/audit/orchestrator/hostInputPause.js.map +1 -0
  22. package/dist/audit/quota/index.d.ts +24 -24
  23. package/dist/audit/types.d.ts +2 -2
  24. package/dist/remediate/contractPipeline/artifactStore.d.ts +27 -0
  25. package/dist/remediate/contractPipeline/artifactStore.d.ts.map +1 -1
  26. package/dist/remediate/contractPipeline/artifactStore.js +34 -0
  27. package/dist/remediate/contractPipeline/artifactStore.js.map +1 -1
  28. package/dist/remediate/contractPipeline/changeClassification.d.ts +9 -3
  29. package/dist/remediate/contractPipeline/changeClassification.d.ts.map +1 -1
  30. package/dist/remediate/contractPipeline/changeClassification.js +25 -6
  31. package/dist/remediate/contractPipeline/changeClassification.js.map +1 -1
  32. package/dist/remediate/contractPipeline/derive.d.ts +42 -0
  33. package/dist/remediate/contractPipeline/derive.d.ts.map +1 -1
  34. package/dist/remediate/contractPipeline/derive.js +108 -0
  35. package/dist/remediate/contractPipeline/derive.js.map +1 -1
  36. package/dist/remediate/index.d.ts.map +1 -1
  37. package/dist/remediate/index.js +9 -1
  38. package/dist/remediate/index.js.map +1 -1
  39. package/dist/remediate/intake.d.ts +10 -0
  40. package/dist/remediate/intake.d.ts.map +1 -1
  41. package/dist/remediate/intake.js +20 -1
  42. package/dist/remediate/intake.js.map +1 -1
  43. package/dist/remediate/phases/grounding.d.ts +7 -4
  44. package/dist/remediate/phases/grounding.d.ts.map +1 -1
  45. package/dist/remediate/phases/grounding.js +52 -8
  46. package/dist/remediate/phases/grounding.js.map +1 -1
  47. package/dist/remediate/steps/contractPipelinePrompts.d.ts +1 -0
  48. package/dist/remediate/steps/contractPipelinePrompts.d.ts.map +1 -1
  49. package/dist/remediate/steps/contractPipelinePrompts.js +2 -2
  50. package/dist/remediate/steps/contractPipelinePrompts.js.map +1 -1
  51. package/dist/remediate/steps/dispatch/acceptNode.d.ts +25 -0
  52. package/dist/remediate/steps/dispatch/acceptNode.d.ts.map +1 -1
  53. package/dist/remediate/steps/dispatch/acceptNode.js +65 -7
  54. package/dist/remediate/steps/dispatch/acceptNode.js.map +1 -1
  55. package/dist/remediate/steps/dispatch/common.d.ts +11 -0
  56. package/dist/remediate/steps/dispatch/common.d.ts.map +1 -1
  57. package/dist/remediate/steps/dispatch/common.js +16 -0
  58. package/dist/remediate/steps/dispatch/common.js.map +1 -1
  59. package/dist/remediate/steps/dispatch/implementPrompt.d.ts +13 -0
  60. package/dist/remediate/steps/dispatch/implementPrompt.d.ts.map +1 -1
  61. package/dist/remediate/steps/dispatch/implementPrompt.js +33 -7
  62. package/dist/remediate/steps/dispatch/implementPrompt.js.map +1 -1
  63. package/dist/remediate/steps/dispatch/marshal.d.ts.map +1 -1
  64. package/dist/remediate/steps/dispatch/marshal.js +77 -9
  65. package/dist/remediate/steps/dispatch/marshal.js.map +1 -1
  66. package/dist/remediate/steps/dispatch/worktreeLifecycle.d.ts +55 -16
  67. package/dist/remediate/steps/dispatch/worktreeLifecycle.d.ts.map +1 -1
  68. package/dist/remediate/steps/dispatch/worktreeLifecycle.js +119 -16
  69. package/dist/remediate/steps/dispatch/worktreeLifecycle.js.map +1 -1
  70. package/dist/remediate/steps/dispatch.d.ts +2 -2
  71. package/dist/remediate/steps/dispatch.d.ts.map +1 -1
  72. package/dist/remediate/steps/dispatch.js +2 -2
  73. package/dist/remediate/steps/dispatch.js.map +1 -1
  74. package/dist/remediate/steps/nextStep.d.ts.map +1 -1
  75. package/dist/remediate/steps/nextStep.js +12 -1
  76. package/dist/remediate/steps/nextStep.js.map +1 -1
  77. package/dist/remediate/validation/artifacts.d.ts.map +1 -1
  78. package/dist/remediate/validation/artifacts.js +38 -1
  79. package/dist/remediate/validation/artifacts.js.map +1 -1
  80. package/dist/remediate/validation/contractPipeline.d.ts +1 -1
  81. package/dist/remediate/validation/contractPipeline.d.ts.map +1 -1
  82. package/dist/remediate/validation/contractPipeline.js +1 -1
  83. package/dist/remediate/validation/contractPipeline.js.map +1 -1
  84. package/dist/remediate/validation/contractPipelineGates.d.ts +15 -0
  85. package/dist/remediate/validation/contractPipelineGates.d.ts.map +1 -1
  86. package/dist/remediate/validation/contractPipelineGates.js +168 -2
  87. package/dist/remediate/validation/contractPipelineGates.js.map +1 -1
  88. package/dist/shared/dispatch/admissionLoop.d.ts +12 -12
  89. package/dist/shared/dispatch/costRank.d.ts +17 -1
  90. package/dist/shared/dispatch/costRank.d.ts.map +1 -1
  91. package/dist/shared/dispatch/costRank.js +8 -4
  92. package/dist/shared/dispatch/costRank.js.map +1 -1
  93. package/dist/shared/friction/captureFrictionEvent.d.ts +13 -0
  94. package/dist/shared/friction/captureFrictionEvent.d.ts.map +1 -1
  95. package/dist/shared/friction/captureFrictionEvent.js.map +1 -1
  96. package/dist/shared/friction/frictionRecord.d.ts +55 -1
  97. package/dist/shared/friction/frictionRecord.d.ts.map +1 -1
  98. package/dist/shared/friction/frictionRecord.js +40 -0
  99. package/dist/shared/friction/frictionRecord.js.map +1 -1
  100. package/dist/shared/friction/stepBoundaryCapture.d.ts +14 -0
  101. package/dist/shared/friction/stepBoundaryCapture.d.ts.map +1 -1
  102. package/dist/shared/friction/stepBoundaryCapture.js +47 -0
  103. package/dist/shared/friction/stepBoundaryCapture.js.map +1 -1
  104. package/dist/shared/friction/triage.d.ts +94 -14
  105. package/dist/shared/friction/triage.d.ts.map +1 -1
  106. package/dist/shared/friction/triage.js +0 -0
  107. package/dist/shared/friction/triage.js.map +1 -1
  108. package/dist/shared/index.d.ts +1 -1
  109. package/dist/shared/index.d.ts.map +1 -1
  110. package/dist/shared/index.js +1 -1
  111. package/dist/shared/index.js.map +1 -1
  112. package/dist/shared/quota/capacity.d.ts +4 -4
  113. package/dist/shared/quota/modelStatics.d.ts +15 -7
  114. package/dist/shared/quota/modelStatics.d.ts.map +1 -1
  115. package/dist/shared/quota/modelStatics.js +60 -13
  116. package/dist/shared/quota/modelStatics.js.map +1 -1
  117. package/dist/shared/quota/quotaSource.d.ts +2 -2
  118. package/dist/shared/validation/designFindingGrounding.d.ts.map +1 -1
  119. package/dist/shared/validation/designFindingGrounding.js +9 -3
  120. package/dist/shared/validation/designFindingGrounding.js.map +1 -1
  121. package/dist/shared/validation/findingGrounding.d.ts +40 -0
  122. package/dist/shared/validation/findingGrounding.d.ts.map +1 -1
  123. package/dist/shared/validation/findingGrounding.js +83 -0
  124. package/dist/shared/validation/findingGrounding.js.map +1 -1
  125. package/docs/audit-pkg/operator-guide.md +84 -0
  126. package/package.json +2 -2
@@ -39,14 +39,14 @@ export declare const AdmissionGrantSchema: z.ZodObject<{
39
39
  lease_id: z.ZodString;
40
40
  cost: z.ZodNumber;
41
41
  }, "strict", z.ZodTypeAny, {
42
- packet_id: string;
43
42
  cost: number;
43
+ packet_id: string;
44
44
  pool_id: string;
45
45
  resource_key: string;
46
46
  lease_id: string;
47
47
  }, {
48
- packet_id: string;
49
48
  cost: number;
49
+ packet_id: string;
50
50
  pool_id: string;
51
51
  resource_key: string;
52
52
  lease_id: string;
@@ -65,18 +65,18 @@ export declare const AdmissionExplainSchema: z.ZodObject<{
65
65
  cost: z.ZodNumber;
66
66
  }, "strict", z.ZodTypeAny, {
67
67
  reason: "admitted" | "no_capable_pool" | "budget_exhausted" | "cap_reached";
68
+ cost: number;
68
69
  admitted: boolean;
69
70
  packet_id: string;
70
- cost: number;
71
71
  pool_id: string | null;
72
72
  resource_key: string | null;
73
73
  headroom_before?: number | undefined;
74
74
  outstanding_before?: number | undefined;
75
75
  }, {
76
76
  reason: "admitted" | "no_capable_pool" | "budget_exhausted" | "cap_reached";
77
+ cost: number;
77
78
  admitted: boolean;
78
79
  packet_id: string;
79
- cost: number;
80
80
  pool_id: string | null;
81
81
  resource_key: string | null;
82
82
  headroom_before?: number | undefined;
@@ -101,14 +101,14 @@ export declare const DispatchAdmissionSchema: z.ZodObject<{
101
101
  lease_id: z.ZodString;
102
102
  cost: z.ZodNumber;
103
103
  }, "strict", z.ZodTypeAny, {
104
- packet_id: string;
105
104
  cost: number;
105
+ packet_id: string;
106
106
  pool_id: string;
107
107
  resource_key: string;
108
108
  lease_id: string;
109
109
  }, {
110
- packet_id: string;
111
110
  cost: number;
111
+ packet_id: string;
112
112
  pool_id: string;
113
113
  resource_key: string;
114
114
  lease_id: string;
@@ -126,18 +126,18 @@ export declare const DispatchAdmissionSchema: z.ZodObject<{
126
126
  cost: z.ZodNumber;
127
127
  }, "strict", z.ZodTypeAny, {
128
128
  reason: "admitted" | "no_capable_pool" | "budget_exhausted" | "cap_reached";
129
+ cost: number;
129
130
  admitted: boolean;
130
131
  packet_id: string;
131
- cost: number;
132
132
  pool_id: string | null;
133
133
  resource_key: string | null;
134
134
  headroom_before?: number | undefined;
135
135
  outstanding_before?: number | undefined;
136
136
  }, {
137
137
  reason: "admitted" | "no_capable_pool" | "budget_exhausted" | "cap_reached";
138
+ cost: number;
138
139
  admitted: boolean;
139
140
  packet_id: string;
140
- cost: number;
141
141
  pool_id: string | null;
142
142
  resource_key: string | null;
143
143
  headroom_before?: number | undefined;
@@ -145,8 +145,8 @@ export declare const DispatchAdmissionSchema: z.ZodObject<{
145
145
  }>, "many">;
146
146
  }, "strict", z.ZodTypeAny, {
147
147
  leases: {
148
- packet_id: string;
149
148
  cost: number;
149
+ packet_id: string;
150
150
  pool_id: string;
151
151
  resource_key: string;
152
152
  lease_id: string;
@@ -155,9 +155,9 @@ export declare const DispatchAdmissionSchema: z.ZodObject<{
155
155
  declared_cap: number | null;
156
156
  explains: {
157
157
  reason: "admitted" | "no_capable_pool" | "budget_exhausted" | "cap_reached";
158
+ cost: number;
158
159
  admitted: boolean;
159
160
  packet_id: string;
160
- cost: number;
161
161
  pool_id: string | null;
162
162
  resource_key: string | null;
163
163
  headroom_before?: number | undefined;
@@ -165,8 +165,8 @@ export declare const DispatchAdmissionSchema: z.ZodObject<{
165
165
  }[];
166
166
  }, {
167
167
  leases: {
168
- packet_id: string;
169
168
  cost: number;
169
+ packet_id: string;
170
170
  pool_id: string;
171
171
  resource_key: string;
172
172
  lease_id: string;
@@ -175,9 +175,9 @@ export declare const DispatchAdmissionSchema: z.ZodObject<{
175
175
  declared_cap: number | null;
176
176
  explains: {
177
177
  reason: "admitted" | "no_capable_pool" | "budget_exhausted" | "cap_reached";
178
+ cost: number;
178
179
  admitted: boolean;
179
180
  packet_id: string;
180
- cost: number;
181
181
  pool_id: string | null;
182
182
  resource_key: string | null;
183
183
  headroom_before?: number | undefined;
@@ -50,11 +50,22 @@ export declare function blendedPrice(price: ModelStatics["price"] | undefined):
50
50
  /**
51
51
  * Resolve a model id to its blended $/Mtok price via the vendored models.dev
52
52
  * snapshot, or `undefined` when the model is unknown / the dataset is empty.
53
+ *
54
+ * Optional `provider` pins the native (per-provider) price; omitting it takes the
55
+ * cheapest-collision default. Single-provider snapshots resolve identically
56
+ * either way.
53
57
  */
54
- export declare function resolveModelPrice(model: string | null | undefined): number | undefined;
58
+ export declare function resolveModelPrice(model: string | null | undefined, provider?: string | null): number | undefined;
55
59
  export interface CostRankInput {
56
60
  /** Model id for the price lookup (rung 2). `null`/unknown ⇒ falls through. */
57
61
  model: string | null | undefined;
62
+ /**
63
+ * Optional provider that owns this pool's model. When set, the price lookup
64
+ * pins that provider's native price on a cross-provider model-id collision;
65
+ * omitting it takes the cheapest-collision default. No effect on a
66
+ * single-provider snapshot.
67
+ */
68
+ provider?: string | null;
58
69
  /** Pool tier for the fallback ordinal (rung 3). */
59
70
  tier: DispatchModelTier | null | undefined;
60
71
  /**
@@ -75,6 +86,11 @@ export interface CostCandidate {
75
86
  /** Stable identifier for the candidate (provider name, or `provider/model`). */
76
87
  key: string;
77
88
  model?: string | null;
89
+ /**
90
+ * Optional owning provider; pins the native price on a cross-provider model-id
91
+ * collision. Omit for the cheapest-collision default.
92
+ */
93
+ provider?: string | null;
78
94
  tier?: DispatchModelTier | null;
79
95
  }
80
96
  /** A candidate with its resolved price + the tool's suggested position. */
@@ -1 +1 @@
1
- {"version":3,"file":"costRank.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/costRank.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,eAAe,UAAY,CAAC;AACzC,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAUzF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAEtF;AAED,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC,mDAAmD;IACnD,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAc3D;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACjC;AAED,2EAA2E;AAC3E,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,oBAAoB,EAAE,CAsBvF;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,EACjD,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAIf;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAClG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAcrB"}
1
+ {"version":3,"file":"costRank.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/costRank.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,eAAe,UAAY,CAAC;AACzC,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAUzF;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,GAAG,SAAS,CAEpB;AAED,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mDAAmD;IACnD,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAc3D;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACjC;AAED,2EAA2E;AAC3E,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,oBAAoB,EAAE,CAsBvF;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,EACjD,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAIf;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAClG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAcrB"}
@@ -63,9 +63,13 @@ export function blendedPrice(price) {
63
63
  /**
64
64
  * Resolve a model id to its blended $/Mtok price via the vendored models.dev
65
65
  * snapshot, or `undefined` when the model is unknown / the dataset is empty.
66
+ *
67
+ * Optional `provider` pins the native (per-provider) price; omitting it takes the
68
+ * cheapest-collision default. Single-provider snapshots resolve identically
69
+ * either way.
66
70
  */
67
- export function resolveModelPrice(model) {
68
- return blendedPrice(resolveModelStatics(model)?.price);
71
+ export function resolveModelPrice(model, provider) {
72
+ return blendedPrice(resolveModelStatics(model, provider)?.price);
69
73
  }
70
74
  /**
71
75
  * Derive a pool's `costRank` (LOWER = cheaper). Total order across all pools in a
@@ -79,7 +83,7 @@ export function deriveCostRank(input) {
79
83
  return CONFIRMED_ORDER_BAND_BASE + input.confirmedPosition;
80
84
  }
81
85
  // Rung 2 — real blended price when the dataset knows the model.
82
- const price = resolveModelPrice(input.model);
86
+ const price = resolveModelPrice(input.model, input.provider);
83
87
  if (price !== undefined)
84
88
  return PRICE_BAND_BASE + price;
85
89
  // Rung 3 — tier ordinal, offset above every priced pool (unknown = overflow).
@@ -94,7 +98,7 @@ export function deriveCostRank(input) {
94
98
  */
95
99
  export function suggestCostOrdering(candidates) {
96
100
  const priced = candidates.map((c) => {
97
- const price = resolveModelPrice(c.model);
101
+ const price = resolveModelPrice(c.model, c.provider);
98
102
  return { candidate: c, price };
99
103
  });
100
104
  const sorted = [...priced].sort((a, b) => {
@@ -1 +1 @@
1
- {"version":3,"file":"costRank.js","sourceRoot":"","sources":["../../../src/shared/dispatch/costRank.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"costRank.js","sourceRoot":"","sources":["../../../src/shared/dispatch/costRank.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { type FrictionCaptureArtifact, type FrictionItem } from "../io/frictionCapture.js";
2
+ import { type FrictionCategory } from "./frictionRecord.js";
2
3
  export type { CapturedFrictionItem } from "./frictionRecord.js";
3
4
  /**
4
5
  * The single mechanical-friction sink (FC-005). Mechanical seams (O3
@@ -40,6 +41,18 @@ export interface FrictionEvent extends FrictionItem {
40
41
  * already present in the run record is a no-op (per-event de-dup, INV-O1-6).
41
42
  */
42
43
  id: string;
44
+ /**
45
+ * The REAL close-out category (one of `FRICTION_CATEGORIES`) this event feeds.
46
+ * Carried through onto the persisted `CapturedFrictionItem` so the per-category
47
+ * friction walk keys on a real category, not the coarse `bug|trap|suggestion`
48
+ * origin hint. Optional so a bare `captureFrictionEvent` caller need not supply it.
49
+ */
50
+ frictionCategory?: FrictionCategory;
51
+ /**
52
+ * Optional artifact/subject key — the aggregation axis that collapses N
53
+ * same-artifact events into ONE derived observation.
54
+ */
55
+ artifact?: string;
43
56
  }
44
57
  /**
45
58
  * Append one mechanical friction event to the per-run record, best-effort.
@@ -1 +1 @@
1
- {"version":3,"file":"captureFrictionEvent.d.ts","sourceRoot":"","sources":["../../../src/shared/friction/captureFrictionEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAM3F,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,oEAAoE;AACpE,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,aAAa,EACpB,IAAI,GAAE,uBAAuB,CAAC,MAAM,CAAoB,GACvD,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
1
+ {"version":3,"file":"captureFrictionEvent.d.ts","sourceRoot":"","sources":["../../../src/shared/friction/captureFrictionEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,oEAAoE;AACpE,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,aAAa,EACpB,IAAI,GAAE,uBAAuB,CAAC,MAAM,CAAoB,GACvD,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
@@ -1 +1 @@
1
- {"version":3,"file":"captureFrictionEvent.js","sourceRoot":"","sources":["../../../src/shared/friction/captureFrictionEvent.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AA+C7B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,YAAoB,EACpB,KAAa,EACb,KAAoB,EACpB,OAAwC,gBAAgB;IAExD,IAAI,CAAC;QACH,MAAM,uBAAuB,CAC3B,YAAY,EACZ,KAAK,EACL,CAAC,MAAM,EAAE,EAAE;YACT,MAAM,SAAS,GAA2B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;gBACvE,CAAC,CAAC,MAAM,CAAC,SAAS;gBAClB,CAAC,CAAC,EAAE,CAAC;YACP,oEAAoE;YACpE,mEAAmE;YACnE,gEAAgE;YAChE,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnD,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,OAAO;gBACL,GAAG,MAAM;gBACT,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;gBACzB,SAAS,EAAE,CAAC,GAAG,SAAS,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC;aACxC,CAAC;QACJ,CAAC,EACD,IAAI,CACL,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;IAC/E,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"captureFrictionEvent.js","sourceRoot":"","sources":["../../../src/shared/friction/captureFrictionEvent.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AA2D7B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,YAAoB,EACpB,KAAa,EACb,KAAoB,EACpB,OAAwC,gBAAgB;IAExD,IAAI,CAAC;QACH,MAAM,uBAAuB,CAC3B,YAAY,EACZ,KAAK,EACL,CAAC,MAAM,EAAE,EAAE;YACT,MAAM,SAAS,GAA2B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;gBACvE,CAAC,CAAC,MAAM,CAAC,SAAS;gBAClB,CAAC,CAAC,EAAE,CAAC;YACP,oEAAoE;YACpE,mEAAmE;YACnE,gEAAgE;YAChE,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnD,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,OAAO;gBACL,GAAG,MAAM;gBACT,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;gBACzB,SAAS,EAAE,CAAC,GAAG,SAAS,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC;aACxC,CAAC;QACJ,CAAC,EACD,IAAI,CACL,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;IAC/E,CAAC;AACH,CAAC"}
@@ -17,10 +17,49 @@ import { type FrictionCaptureArtifact, type FrictionItem } from "../io/frictionC
17
17
  * (via `frictionCapturePath` / `sanitizeRunId`) — no platform-baked literal, so
18
18
  * the substrate is OS/path-agnostic (INV-O1-7).
19
19
  */
20
- /** A single captured mechanical friction event: a `FrictionItem` plus a stable id. */
20
+ /**
21
+ * The REQUIRED friction CATEGORIES — the coverage axis the blocking close-out
22
+ * enforces EVERY run. The host must, for EACH category, either record ≥1
23
+ * `open_observations[]` entry tagged with it OR an explicit
24
+ * `category_attestations[]` "nothing to report". A category can never be skipped
25
+ * by silence — that omission is exactly the failure the gate prevents.
26
+ *
27
+ * Single-sourced HERE in the substrate (not in `triage.ts`) so the mechanical
28
+ * capture layer (`stepBoundaryCapture.ts`) can stamp a captured event with a REAL
29
+ * category without importing the triage module — there is exactly ONE category
30
+ * vocabulary shared by capture, triage, and the render, and it can never drift.
31
+ */
32
+ export declare const FRICTION_CATEGORIES: readonly ["ambiguous_direction", "tool_should_decide", "inefficient_feeding"];
33
+ export type FrictionCategory = (typeof FRICTION_CATEGORIES)[number];
34
+ /** Whether a value is one of the required friction categories (contract check). */
35
+ export declare function isFrictionCategory(value: unknown): value is FrictionCategory;
36
+ /**
37
+ * A single captured mechanical friction event: a `FrictionItem` plus a stable id
38
+ * and the REAL friction category it belongs to (one of `FRICTION_CATEGORIES`).
39
+ */
21
40
  export interface CapturedFrictionItem extends FrictionItem {
22
41
  /** Stable distinct id; re-recording an event with this id is a no-op de-dup. */
23
42
  id: string;
43
+ /**
44
+ * The REAL close-out category (one of `FRICTION_CATEGORIES`) this mechanical
45
+ * event belongs to — what the per-category friction walk keys on. Distinct
46
+ * from the inherited `FrictionItem.category` (`bug|trap|suggestion`), which is
47
+ * only a coarse origin hint and is NEVER a close-out category. Optional only
48
+ * for back-compat with older records; a stamped event always carries it.
49
+ */
50
+ frictionCategory?: FrictionCategory;
51
+ /**
52
+ * Optional artifact/subject key this event concerns (e.g. the node id, the
53
+ * contract id) — the aggregation axis that collapses N same-artifact events
54
+ * into ONE derived observation. Falls back to `area` when unset.
55
+ */
56
+ artifact?: string;
57
+ /**
58
+ * Optional measured token cost this event incurred (best-effort — supplied only
59
+ * when the seam has a real measure). Summed into the aggregate's `tokens` cost
60
+ * signal; never fabricated when absent.
61
+ */
62
+ tokens?: number;
24
63
  }
25
64
  /** The host disposition vocabulary over a captured subject. */
26
65
  export type FrictionDisposition = "keep" | "discard" | "annotate";
@@ -46,6 +85,21 @@ export interface FrictionOpenObservation {
46
85
  dimension?: string;
47
86
  /** The host's observation note. */
48
87
  note: string;
88
+ /**
89
+ * When set, the aggregation subject (artifact/node/contract key) this
90
+ * observation summarizes. Present on TOOL-DERIVED observations (see `derived`)
91
+ * so a re-run can idempotently replace the derived set keyed on
92
+ * `(category, artifact)`; absent on host-authored observations.
93
+ */
94
+ artifact?: string;
95
+ /**
96
+ * True when the tool DERIVED this observation by aggregating mechanical
97
+ * step-boundary events (pre-populating the host's category walk), vs. a
98
+ * host-authored observation. The close-out counts a derived observation toward
99
+ * category coverage exactly like a host one; the flag only lets the derive step
100
+ * replace its own prior output without ever touching host-authored entries.
101
+ */
102
+ derived?: boolean;
49
103
  }
50
104
  /**
51
105
  * An explicit affirmation that a friction CATEGORY had nothing to report this
@@ -1 +1 @@
1
- {"version":3,"file":"frictionRecord.d.ts","sourceRoot":"","sources":["../../../src/shared/friction/frictionRecord.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EAKlB,MAAM,0BAA0B,CAAC;AAIlC;;;;;;;;;;;;;;;;;GAiBG;AAEH,sFAAsF;AACtF,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,gFAAgF;IAChF,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,+DAA+D;AAC/D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAElE,mFAAmF;AACnF,MAAM,WAAW,yBAAyB;IACxC,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,WAAW,EAAE,mBAAmB,CAAC;IACjC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,oFAAoF;AACpF,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,2BAA2B;IAC1C,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,qEAAqE;IACrE,YAAY,CAAC,EAAE,yBAAyB,EAAE,CAAC;IAC3C;yFACqF;IACrF,iBAAiB,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC9C,kFAAkF;IAClF,qBAAqB,CAAC,EAAE,2BAA2B,EAAE,CAAC;IACtD,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5E;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,uBAAuB,EACpE,IAAI,GAAE,uBAAuB,CAAC,MAAM,CAAoB,GACvD,OAAO,CAAC,uBAAuB,CAAC,CAUlC"}
1
+ {"version":3,"file":"frictionRecord.d.ts","sourceRoot":"","sources":["../../../src/shared/friction/frictionRecord.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EAKlB,MAAM,0BAA0B,CAAC;AAIlC;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,+EAItB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAK5E;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,gFAAgF;IAChF,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+DAA+D;AAC/D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAElE,mFAAmF;AACnF,MAAM,WAAW,yBAAyB;IACxC,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,WAAW,EAAE,mBAAmB,CAAC;IACjC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,oFAAoF;AACpF,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,2BAA2B;IAC1C,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,qEAAqE;IACrE,YAAY,CAAC,EAAE,yBAAyB,EAAE,CAAC;IAC3C;yFACqF;IACrF,iBAAiB,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC9C,kFAAkF;IAClF,qBAAqB,CAAC,EAAE,2BAA2B,EAAE,CAAC;IACtD,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5E;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,uBAAuB,EACpE,IAAI,GAAE,uBAAuB,CAAC,MAAM,CAAoB,GACvD,OAAO,CAAC,uBAAuB,CAAC,CAUlC"}
@@ -2,6 +2,46 @@ import { join } from "node:path";
2
2
  import { FRICTION_CAPTURE_SCHEMA_VERSION, frictionCaptureDir, frictionCapturePath, sanitizeRunId, } from "../io/frictionCapture.js";
3
3
  import { readOptionalJsonFile, writeJsonFile } from "../io/json.js";
4
4
  import { withFileLock } from "../quota/fileLock.js";
5
+ /**
6
+ * The shared per-run friction RECORD substrate (CE-004 / CE-010, the O1
7
+ * FRICTION-FOUNDATION layer). Single-sourced for BOTH orchestrators so the
8
+ * record shape, the lock path, and the locked read-merge-write append cannot
9
+ * drift between the two halves of the pipeline.
10
+ *
11
+ * `captureFrictionEvent` (the mechanical sink) and `recordFrictionDisposition` /
12
+ * `decideFrictionTriage` (the host triage path) BOTH route their record
13
+ * mutations through `appendFrictionUnderLock`, which rides ONE
14
+ * `withFileLock(frictionLockPath)` and reads-then-MERGEs the existing record —
15
+ * so a late mechanical emit never clobbers host `dispositions[]` /
16
+ * `open_observations[]` already written, and a host disposition never drops a
17
+ * concurrently-appended mechanical `frictions[]` entry (CE-010).
18
+ *
19
+ * Every path derives from `node:path` joins off the supplied artifacts dir
20
+ * (via `frictionCapturePath` / `sanitizeRunId`) — no platform-baked literal, so
21
+ * the substrate is OS/path-agnostic (INV-O1-7).
22
+ */
23
+ /**
24
+ * The REQUIRED friction CATEGORIES — the coverage axis the blocking close-out
25
+ * enforces EVERY run. The host must, for EACH category, either record ≥1
26
+ * `open_observations[]` entry tagged with it OR an explicit
27
+ * `category_attestations[]` "nothing to report". A category can never be skipped
28
+ * by silence — that omission is exactly the failure the gate prevents.
29
+ *
30
+ * Single-sourced HERE in the substrate (not in `triage.ts`) so the mechanical
31
+ * capture layer (`stepBoundaryCapture.ts`) can stamp a captured event with a REAL
32
+ * category without importing the triage module — there is exactly ONE category
33
+ * vocabulary shared by capture, triage, and the render, and it can never drift.
34
+ */
35
+ export const FRICTION_CATEGORIES = [
36
+ "ambiguous_direction", // direction/decision the tool or prompt left to the host that it should have resolved
37
+ "tool_should_decide", // the host had to remember / notice / enforce something the tool should guarantee
38
+ "inefficient_feeding", // redundant or wasteful work, poor context feeding, or a tool inefficiency
39
+ ];
40
+ /** Whether a value is one of the required friction categories (contract check). */
41
+ export function isFrictionCategory(value) {
42
+ return (typeof value === "string" &&
43
+ FRICTION_CATEGORIES.includes(value));
44
+ }
5
45
  /**
6
46
  * `<artifactsDir>/friction/<run_id>.lock` — the lock path guarding the per-run
7
47
  * record. Single-sourced so every record mutator (mechanical sink + host triage)
@@ -1 +1 @@
1
- {"version":3,"file":"frictionRecord.js","sourceRoot":"","sources":["../../../src/shared/friction/frictionRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAGL,+BAA+B,EAC/B,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAwFpD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,YAAoB,EAAE,KAAa;IAClE,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,iFAAiF;AACjF,SAAS,WAAW,CAClB,KAAa,EACb,IAAqC;IAErC,OAAO;QACL,cAAc,EAAE,+BAA+B;QAC/C,IAAI;QACJ,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,SAAS,EAAE,EAAE;KACd,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,YAAoB,EACpB,KAAa,EACb,MAAoE,EACpE,OAAwC,gBAAgB;IAExD,OAAO,YAAY,CAAC,gBAAgB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CACzC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,CACzC,CAAC;QACF,MAAM,IAAI,GAAG,QAAQ,IAAI,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,aAAa,CAAC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"frictionRecord.js","sourceRoot":"","sources":["../../../src/shared/friction/frictionRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAGL,+BAA+B,EAC/B,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,qBAAqB,EAAE,sFAAsF;IAC7G,oBAAoB,EAAE,kFAAkF;IACxG,qBAAqB,EAAE,2EAA2E;CAC1F,CAAC;AAGX,mFAAmF;AACnF,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACxB,mBAAyC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC3D,CAAC;AACJ,CAAC;AA2GD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,YAAoB,EAAE,KAAa;IAClE,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,iFAAiF;AACjF,SAAS,WAAW,CAClB,KAAa,EACb,IAAqC;IAErC,OAAO;QACL,cAAc,EAAE,+BAA+B;QAC/C,IAAI;QACJ,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,SAAS,EAAE,EAAE;KACd,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,YAAoB,EACpB,KAAa,EACb,MAAoE,EACpE,OAAwC,gBAAgB;IAExD,OAAO,YAAY,CAAC,gBAAgB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CACzC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,CACzC,CAAC;QACF,MAAM,IAAI,GAAG,QAAQ,IAAI,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,aAAa,CAAC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { FrictionItem } from "../io/frictionCapture.js";
2
2
  import type { FrictionCaptureArtifact } from "../io/frictionCapture.js";
3
+ import type { FrictionCategory } from "./frictionRecord.js";
3
4
  /**
4
5
  * CE-005 — the SINGLE shared backend-observed step-boundary chokepoint.
5
6
  *
@@ -48,6 +49,12 @@ import type { FrictionCaptureArtifact } from "../io/frictionCapture.js";
48
49
  * quarantine ref, NOT landed (discriminator: the node id).
49
50
  */
50
51
  export type StepBoundaryEventType = "phase_reemit" | "artifact_rejected" | "repair_round" | "post_repair_rederive" | "no_change_merge" | "intent_gate_fallback" | "quota_escalation" | "coverage_total_lines_mismatch" | "node_quarantine" | (string & {});
52
+ /**
53
+ * The REAL close-out friction category for a step-boundary fact kind. Total: an
54
+ * unknown event type degrades to `inefficient_feeding` so the mapping is never
55
+ * undefined and a captured event is ALWAYS tagged with a real category.
56
+ */
57
+ export declare function stepBoundaryFrictionCategory(eventType: StepBoundaryEventType): FrictionCategory;
51
58
  /**
52
59
  * Build the STRUCTURED, collision-free de-dup id for a step-boundary fact.
53
60
  * Components are individually percent-encoded then joined with `:` — a delimiter
@@ -70,6 +77,13 @@ export interface StepBoundaryFriction {
70
77
  severity?: FrictionItem["severity"];
71
78
  category?: FrictionItem["category"];
72
79
  area?: string;
80
+ /**
81
+ * Optional artifact/subject key this fact concerns (e.g. the node id, the
82
+ * contract id). The aggregation axis for the derived per-category observation:
83
+ * N facts on the SAME artifact collapse to one `inefficient_feeding` line.
84
+ * Falls back to `area`, then the discriminator, when unset.
85
+ */
86
+ artifact?: string;
73
87
  }
74
88
  /**
75
89
  * Route ONE backend-observed step-boundary fact through the single chokepoint.
@@ -1 +1 @@
1
- {"version":3,"file":"stepBoundaryCapture.d.ts","sourceRoot":"","sources":["../../../src/shared/friction/stepBoundaryCapture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAGxE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,qBAAqB,GAC7B,cAAc,GACd,mBAAmB,GACnB,cAAc,GACd,sBAAsB,GACtB,iBAAiB,GACjB,sBAAsB,GACtB,kBAAkB,GAClB,+BAA+B,GAC/B,iBAAiB,GACjB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAgBlB;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,qBAAqB,EAChC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,MAAM,CAIR;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,8EAA8E;IAC9E,SAAS,EAAE,qBAAqB,CAAC;IACjC;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,oBAAoB,EAC1B,IAAI,EAAE,uBAAuB,CAAC,MAAM,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CASf"}
1
+ {"version":3,"file":"stepBoundaryCapture.d.ts","sourceRoot":"","sources":["../../../src/shared/friction/stepBoundaryCapture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,qBAAqB,GAC7B,cAAc,GACd,mBAAmB,GACnB,cAAc,GACd,sBAAsB,GACtB,iBAAiB,GACjB,sBAAsB,GACtB,kBAAkB,GAClB,+BAA+B,GAC/B,iBAAiB,GACjB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAgClB;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,qBAAqB,GAC/B,gBAAgB,CAElB;AAgBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,qBAAqB,EAChC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,MAAM,CAIR;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,8EAA8E;IAC9E,SAAS,EAAE,qBAAqB,CAAC;IACjC;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,oBAAoB,EAC1B,IAAI,EAAE,uBAAuB,CAAC,MAAM,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAmBf"}
@@ -1,4 +1,41 @@
1
1
  import { captureFrictionEvent } from "./captureFrictionEvent.js";
2
+ /**
3
+ * Deterministic map from a backend step-boundary fact kind to the REAL close-out
4
+ * friction CATEGORY (one of `FRICTION_CATEGORIES`) it belongs to. This is what
5
+ * lets the auto-captured event feed the per-category friction walk directly:
6
+ * every backend fact is redundant/wasteful re-work or a something-the-tool-had-to
7
+ * -be-reminded-of, never the coarse `trap` bucket the sink used to stamp.
8
+ *
9
+ * - `inefficient_feeding` — redundant / wasteful re-work: phase re-emits, repair
10
+ * rounds, post-repair re-derives, no-change merges, quota escalations, and the
11
+ * coverage-line mismatch (a re-round-trip to fix a mechanical mismatch).
12
+ * - `tool_should_decide` — a fact where the tool fell back to host discretion or
13
+ * quarantined work the host must now shepherd: artifact rejection, the
14
+ * intent-gate lock-across-judge fallback, and a node quarantine.
15
+ *
16
+ * The named members are pinned; any UNKNOWN `event_type` degrades to
17
+ * `inefficient_feeding` (the safe "this was avoidable re-work" default) so a new
18
+ * backend fact always lands in a real category — never `trap`, never uncovered.
19
+ */
20
+ const STEP_BOUNDARY_CATEGORY = {
21
+ phase_reemit: "inefficient_feeding",
22
+ repair_round: "inefficient_feeding",
23
+ post_repair_rederive: "inefficient_feeding",
24
+ no_change_merge: "inefficient_feeding",
25
+ quota_escalation: "inefficient_feeding",
26
+ coverage_total_lines_mismatch: "inefficient_feeding",
27
+ artifact_rejected: "tool_should_decide",
28
+ intent_gate_fallback: "tool_should_decide",
29
+ node_quarantine: "tool_should_decide",
30
+ };
31
+ /**
32
+ * The REAL close-out friction category for a step-boundary fact kind. Total: an
33
+ * unknown event type degrades to `inefficient_feeding` so the mapping is never
34
+ * undefined and a captured event is ALWAYS tagged with a real category.
35
+ */
36
+ export function stepBoundaryFrictionCategory(eventType) {
37
+ return STEP_BOUNDARY_CATEGORY[eventType] ?? "inefficient_feeding";
38
+ }
2
39
  /**
3
40
  * Percent-encode a single id component so the join delimiter (`:`) cannot appear
4
41
  * inside it. `encodeURIComponent` already escapes `:` (and `/`, `\`, `%`, etc.),
@@ -33,7 +70,17 @@ export async function captureStepBoundaryFriction(artifactsDir, runId, fact, too
33
70
  id: stepBoundaryEventId(fact.eventType, runId, fact.discriminator),
34
71
  note: fact.note,
35
72
  severity: fact.severity,
73
+ // The inherited `FrictionItem.category` (`bug|trap|suggestion`) is only a
74
+ // coarse ORIGIN hint. It is NEVER the close-out category — the close-out keys
75
+ // on `frictionCategory` below. Default the origin hint to `trap` (a standing
76
+ // tooling fact) but ALWAYS stamp a REAL close-out category so the event feeds
77
+ // the per-category walk instead of the dead `trap` bucket it used to land in.
36
78
  category: fact.category ?? "trap",
79
+ frictionCategory: stepBoundaryFrictionCategory(fact.eventType),
80
+ // The aggregation axis: N same-artifact backend facts collapse to ONE derived
81
+ // observation. Prefer the caller's explicit `artifact`, then the fact's area,
82
+ // then the discriminator (which is per-instance but still a stable subject key).
83
+ artifact: fact.artifact ?? fact.area ?? fact.discriminator,
37
84
  area: fact.area,
38
85
  };
39
86
  await captureFrictionEvent(artifactsDir, runId, event, tool);
@@ -1 +1 @@
1
- {"version":3,"file":"stepBoundaryCapture.js","sourceRoot":"","sources":["../../../src/shared/friction/stepBoundaryCapture.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAsB,MAAM,2BAA2B,CAAC;AA8DrF;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,OAAO,CACtC,OAAO,EACP,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CACxD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAgC,EAChC,KAAa,EACb,aAAqB;IAErB,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC;SACrC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;SACtC,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAmBD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,YAAoB,EACpB,KAAa,EACb,IAA0B,EAC1B,IAAqC;IAErC,MAAM,KAAK,GAAkB;QAC3B,EAAE,EAAE,mBAAmB,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC;QAClE,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM;QACjC,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;IACF,MAAM,oBAAoB,CAAC,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAC/D,CAAC"}
1
+ {"version":3,"file":"stepBoundaryCapture.js","sourceRoot":"","sources":["../../../src/shared/friction/stepBoundaryCapture.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAsB,MAAM,2BAA2B,CAAC;AA+DrF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,sBAAsB,GAAqC;IAC/D,YAAY,EAAE,qBAAqB;IACnC,YAAY,EAAE,qBAAqB;IACnC,oBAAoB,EAAE,qBAAqB;IAC3C,eAAe,EAAE,qBAAqB;IACtC,gBAAgB,EAAE,qBAAqB;IACvC,6BAA6B,EAAE,qBAAqB;IACpD,iBAAiB,EAAE,oBAAoB;IACvC,oBAAoB,EAAE,oBAAoB;IAC1C,eAAe,EAAE,oBAAoB;CACtC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAC1C,SAAgC;IAEhC,OAAO,sBAAsB,CAAC,SAAS,CAAC,IAAI,qBAAqB,CAAC;AACpE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,OAAO,CACtC,OAAO,EACP,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CACxD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAgC,EAChC,KAAa,EACb,aAAqB;IAErB,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC;SACrC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;SACtC,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AA0BD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,YAAoB,EACpB,KAAa,EACb,IAA0B,EAC1B,IAAqC;IAErC,MAAM,KAAK,GAAkB;QAC3B,EAAE,EAAE,mBAAmB,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC;QAClE,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,0EAA0E;QAC1E,8EAA8E;QAC9E,6EAA6E;QAC7E,8EAA8E;QAC9E,8EAA8E;QAC9E,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM;QACjC,gBAAgB,EAAE,4BAA4B,CAAC,IAAI,CAAC,SAAS,CAAC;QAC9D,8EAA8E;QAC9E,8EAA8E;QAC9E,iFAAiF;QACjF,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa;QAC1D,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;IACF,MAAM,oBAAoB,CAAC,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAC/D,CAAC"}
@@ -1,8 +1,8 @@
1
1
  import { type FrictionCaptureArtifact } from '../io/frictionCapture.js';
2
2
  import { type AgentReflection } from '../agentReflections.js';
3
- import { type FrictionCategoryAttestation, type FrictionDisposition, type FrictionDispositionRecord, type FrictionOpenObservation, type TriagedFrictionArtifact } from './frictionRecord.js';
4
- export type { CapturedFrictionItem, FrictionCategoryAttestation, FrictionDisposition, FrictionDispositionRecord, FrictionOpenObservation, TriagedFrictionArtifact, } from './frictionRecord.js';
5
- export { appendFrictionUnderLock, frictionLockPath } from './frictionRecord.js';
3
+ import { type CapturedFrictionItem, type FrictionCategory, type FrictionCategoryAttestation, type FrictionDisposition, type FrictionDispositionRecord, type FrictionOpenObservation, type TriagedFrictionArtifact } from './frictionRecord.js';
4
+ export type { CapturedFrictionItem, FrictionCategory, FrictionCategoryAttestation, FrictionDisposition, FrictionDispositionRecord, FrictionOpenObservation, TriagedFrictionArtifact, } from './frictionRecord.js';
5
+ export { FRICTION_CATEGORIES, appendFrictionUnderLock, frictionLockPath, isFrictionCategory, } from './frictionRecord.js';
6
6
  /**
7
7
  * O1 end-of-run friction TRIAGE — single-sourced for BOTH orchestrators so the
8
8
  * triage step shape, the disposition vocabulary, the blocking semantics, and the
@@ -54,19 +54,99 @@ export interface TriageSubject {
54
54
  */
55
55
  export declare const FRICTION_NAMED_DIMENSIONS: readonly ["gate_reloops", "integration_guard_failures", "rescopes", "surprises", "manual_interventions", "other"];
56
56
  export type FrictionDimension = (typeof FRICTION_NAMED_DIMENSIONS)[number] | string;
57
- /**
58
- * The REQUIRED friction CATEGORIES — the coverage axis the blocking close-out
59
- * enforces EVERY run. The host must, for EACH category, either record ≥1
60
- * `open_observations[]` entry tagged with it OR an explicit
61
- * `category_attestations[]` "nothing to report". A category can never be skipped
62
- * by silence — that omission is exactly the failure this gate prevents.
63
- */
64
- export declare const FRICTION_CATEGORIES: readonly ["ambiguous_direction", "tool_should_decide", "inefficient_feeding"];
65
- export type FrictionCategory = (typeof FRICTION_CATEGORIES)[number];
66
57
  /** One-line human labels for each category, shown in the triage prompt. */
67
58
  export declare const FRICTION_CATEGORY_LABELS: Record<FrictionCategory, string>;
68
- /** Whether a value is one of the required friction categories (contract check). */
69
- export declare function isFrictionCategory(value: unknown): value is FrictionCategory;
59
+ /**
60
+ * Cost signals measured across an aggregate of same-category (and, where
61
+ * applicable, same-artifact) mechanical events. These are what let the walk say
62
+ * "this was expensive re-work" quantitatively, not just "something happened".
63
+ */
64
+ export interface FrictionCostSignals {
65
+ /**
66
+ * Round-trips: the number of aggregated mechanical events. Each backend
67
+ * step-boundary fact is one avoidable round-trip (a re-emit, a repair round, a
68
+ * re-derive, …), so the event count IS the round-trip count.
69
+ */
70
+ round_trips: number;
71
+ /**
72
+ * Verbatim re-authors: aggregated events whose subject artifact was touched by
73
+ * MORE THAN ONE event — i.e. the same artifact was re-worked repeatedly. This
74
+ * is the "we re-authored the same thing again" signal.
75
+ */
76
+ verbatim_re_authors: number;
77
+ /**
78
+ * Summed token cost across the aggregated events, when the events carried a
79
+ * `tokens` measure (0 when none did — token accounting stays best-effort and
80
+ * never fabricated).
81
+ */
82
+ tokens: number;
83
+ }
84
+ /**
85
+ * The threshold an aggregate must reach to SURFACE as a pre-populated,
86
+ * auto-covering observation. Below it, the aggregate is still reported (so the
87
+ * host sees it) but does NOT auto-cover its category — the host still walks it.
88
+ * "Below MUST NOT fire" is the contract: a single, cheap round-trip is noise, not
89
+ * a surfaced friction observation.
90
+ */
91
+ export declare const FRICTION_COST_SURFACE_THRESHOLD = 2;
92
+ /** Whether an aggregate's cost is at/above the surface threshold (fires). */
93
+ export declare function costSignalsSurface(signals: FrictionCostSignals): boolean;
94
+ /**
95
+ * ONE derived observation aggregated from N same-category mechanical events. This
96
+ * is the pre-populated close-out entry: N same-artifact backend facts collapse
97
+ * into a SINGLE `inefficient_feeding` (or other-category) observation with the
98
+ * measured cost signals and the covered event ids.
99
+ */
100
+ export interface DerivedFrictionObservation {
101
+ /** The real close-out category this aggregate covers. */
102
+ category: FrictionCategory;
103
+ /** The aggregation subject (the shared artifact key, or "(mixed)" when several). */
104
+ artifact: string;
105
+ /** The ids of the mechanical events folded into this observation. */
106
+ event_ids: string[];
107
+ /** The measured cost across the folded events. */
108
+ cost: FrictionCostSignals;
109
+ /**
110
+ * True when the aggregate's cost is at/above the surface threshold: only these
111
+ * pre-populate/auto-cover the category. A below-threshold aggregate is still
112
+ * listed for the host but never fires (never auto-covers).
113
+ */
114
+ surfaced: boolean;
115
+ /** A ready-to-paste observation note summarizing the aggregate + cost. */
116
+ note: string;
117
+ }
118
+ /**
119
+ * Measure the cost signals across an aggregate of mechanical events. Pure and
120
+ * deterministic — round_trips is the event count (each backend fact is one
121
+ * avoidable round-trip), verbatim_re_authors fires only when the SAME subject was
122
+ * touched by MORE THAN ONE event, and tokens sums the best-effort per-event
123
+ * measure (never fabricated: a missing/non-finite `tokens` contributes 0).
124
+ */
125
+ export declare function measureFrictionCost(items: readonly CapturedFrictionItem[]): FrictionCostSignals;
126
+ /**
127
+ * Aggregate the run's mechanical events into ONE derived observation per
128
+ * (real category, artifact) group — the pre-population source for the host's
129
+ * category walk. Pure and deterministic:
130
+ *
131
+ * - ONLY events carrying a REAL `frictionCategory` feed the walk; an untagged
132
+ * legacy event covers no category (it is a bare pending subject, not a walk
133
+ * contribution) so pre-population never invents coverage.
134
+ * - N same-artifact same-category events collapse to ONE observation carrying
135
+ * the measured cost (`measureFrictionCost`) and the covered event ids.
136
+ * - `surfaced` is the below/above threshold gate: a single cheap round-trip
137
+ * (round_trips < `FRICTION_COST_SURFACE_THRESHOLD`) is reported but does NOT
138
+ * fire (never auto-covers its category) — "below MUST NOT fire".
139
+ * - Output order is stable (canonical category order, then artifact) so a
140
+ * re-derive never churns the record.
141
+ */
142
+ export declare function deriveFrictionObservations(frictions: readonly CapturedFrictionItem[]): DerivedFrictionObservation[];
143
+ /**
144
+ * The SURFACED derived observations mapped into the persisted
145
+ * `open_observations[]` shape — the pre-populated entries the close-out gate (and
146
+ * the Stop-hook backstop) read for category coverage. Only aggregates at/above
147
+ * the surface threshold are emitted; below-threshold aggregates never fire.
148
+ */
149
+ export declare function prepopulatedObservations(derived: readonly DerivedFrictionObservation[]): FrictionOpenObservation[];
70
150
  /**
71
151
  * The mandatory blocking triage decision. `pending` means the close-out is NOT
72
152
  * satisfied. `action`: