@event4u/agent-config 9.34.0 → 9.36.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +64 -77
- package/CONTRIBUTING.md +23 -14
- package/dist/agent-src/commands/analyze/reference-repo.md +135 -42
- package/dist/agent-src/commands/roadmap/next.md +37 -5
- package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +53 -6
- package/dist/agent-src/rules/improve-before-implement.md +1 -1
- package/dist/agent-src/rules/ui-audit-gate.md +35 -0
- package/dist/agent-src/scripts/roadmap_gates.ts +119 -4
- package/dist/agent-src/skills/design-system-capture/SKILL.md +2 -2
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/SKILL.md +84 -12
- package/dist/agent-src/skills/fe-design/evals/triggers.json +11 -3
- package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +5 -5
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +24 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +29 -0
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +25 -0
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/memory_lookup.ts +1 -2
- package/dist/agent-src/templates/scripts/memory_signal.ts +2 -4
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +35 -5
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation.ts +252 -0
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation_store.ts +307 -0
- package/dist/cli/registry.js +2 -2
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-YPAWXXXR.js → chunk-55RI5UXK.js} +17 -0
- package/dist/cli-delegate/{chunk-UVKNIJH2.js → chunk-JP53LNVT.js} +12 -0
- package/dist/cli-delegate/{chunk-736JCWLM.js → chunk-M2DPGFZ4.js} +10 -0
- package/dist/cli-delegate/{chunk-MA4GFWDY.js → chunk-NR7HSN3P.js} +2 -2
- package/dist/cli-delegate/{chunk-REMEZSVP.js → chunk-SFGARMAB.js} +13 -3
- package/dist/cli-delegate/{chunk-DS6BLDMG.js → chunk-U7CMAIOC.js} +7 -2
- package/dist/cli-delegate/cmd_conformance.js +4 -4
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +3 -3
- package/dist/cli-delegate/cmd_refresh.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +8 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +3 -3
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +3 -3
- package/dist/cli-delegate/cmd_uninstall.js +3 -3
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +3 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +14 -14
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +789 -401
- package/dist/install/install.mjs +21 -4
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +99 -7
- package/dist/router.json +1 -1
- package/dist/server/schemas/settings.js +6 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +5 -2
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +46 -4
- package/package.json +2 -2
- package/src/agent-src/scripts/roadmap_gates.ts +119 -4
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/memory_lookup.ts +1 -2
- package/src/agent-src/templates/scripts/memory_signal.ts +2 -4
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +35 -5
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation.ts +252 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation_store.ts +307 -0
- package/src/config/agent-settings.template.yml +43 -2
- package/src/config/gate-coverage.yml +12 -0
- package/src/config/quorum-attendance-budget.json +10 -2
- package/src/scripts/_cli/cmd_doctor.ts +32 -0
- package/src/scripts/_cli/cmd_migrate.ts +26 -3
- package/src/scripts/_cli/cmd_refresh.ts +29 -0
- package/src/scripts/_cli/cmd_session_recycle.ts +40 -2
- package/src/scripts/_dispatch.bash +6 -2
- package/src/scripts/_lib/hook_settings.ts +79 -0
- package/src/scripts/_lib/session_register.ts +67 -1
- package/src/scripts/_lib/ui_surface.ts +97 -0
- package/src/scripts/ai_council/config.ts +60 -0
- package/src/scripts/ai_council/events_log.ts +103 -4
- package/src/scripts/ai_council/quorum.ts +83 -6
- package/src/scripts/capture_skill_catalogue.ts +483 -0
- package/src/scripts/council_cli.ts +36 -1
- package/src/scripts/hook_manifest.yaml +18 -3
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/design_slop_hook.ts +1 -1
- package/src/scripts/hooks/turn_end_gate_hook.ts +172 -11
- package/src/scripts/hooks/ui_route_nudge_hook.ts +250 -0
- package/src/scripts/lint_framework_leakage.ts +195 -28
- package/src/scripts/lint_framework_leakage_allowlist.json +94 -86
- package/src/scripts/lint_roadmap_complexity.ts +60 -0
- package/src/scripts/lint_rule_skill_pack_reach.ts +263 -0
- package/src/scripts/memory_lookup.ts +1 -2
- package/src/scripts/report_consultation_rate.ts +358 -0
- package/src/scripts/report_skill_activation.ts +5 -1
- package/src/scripts/schemas/command.schema.json +4 -0
- package/src/scripts/schemas/skill.schema.json +4 -0
- package/src/scripts/session_register_hook.ts +238 -18
- package/src/scripts/sessions_cli.ts +377 -12
- package/src/server/schemas/settings.ts +12 -0
- /package/dist/agent-src/skills/design-system-capture/{reference → references}/design-system-json.md +0 -0
- /package/dist/agent-src/skills/prediction-pool-optimizer/{reference → references}/ev-fixtures.md +0 -0
- /package/dist/agent-src/skills/prediction-pool-optimizer/{reference → references}/odds-and-bonus.md +0 -0
- /package/dist/agent-src/skills/react-shadcn-ui/{reference → references}/registry.md +0 -0
package/dist/hooks/dispatch.js
CHANGED
|
@@ -112,17 +112,17 @@ var require_visit = __commonJS({
|
|
|
112
112
|
visit.BREAK = BREAK;
|
|
113
113
|
visit.SKIP = SKIP;
|
|
114
114
|
visit.REMOVE = REMOVE;
|
|
115
|
-
function visit_(key, node, visitor,
|
|
116
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
115
|
+
function visit_(key, node, visitor, path69) {
|
|
116
|
+
const ctrl = callVisitor(key, node, visitor, path69);
|
|
117
117
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
118
|
-
replaceNode(key,
|
|
119
|
-
return visit_(key, ctrl, visitor,
|
|
118
|
+
replaceNode(key, path69, ctrl);
|
|
119
|
+
return visit_(key, ctrl, visitor, path69);
|
|
120
120
|
}
|
|
121
121
|
if (typeof ctrl !== "symbol") {
|
|
122
122
|
if (identity.isCollection(node)) {
|
|
123
|
-
|
|
123
|
+
path69 = Object.freeze(path69.concat(node));
|
|
124
124
|
for (let i = 0; i < node.items.length; ++i) {
|
|
125
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
125
|
+
const ci = visit_(i, node.items[i], visitor, path69);
|
|
126
126
|
if (typeof ci === "number")
|
|
127
127
|
i = ci - 1;
|
|
128
128
|
else if (ci === BREAK)
|
|
@@ -133,13 +133,13 @@ var require_visit = __commonJS({
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
} else if (identity.isPair(node)) {
|
|
136
|
-
|
|
137
|
-
const ck = visit_("key", node.key, visitor,
|
|
136
|
+
path69 = Object.freeze(path69.concat(node));
|
|
137
|
+
const ck = visit_("key", node.key, visitor, path69);
|
|
138
138
|
if (ck === BREAK)
|
|
139
139
|
return BREAK;
|
|
140
140
|
else if (ck === REMOVE)
|
|
141
141
|
node.key = null;
|
|
142
|
-
const cv = visit_("value", node.value, visitor,
|
|
142
|
+
const cv = visit_("value", node.value, visitor, path69);
|
|
143
143
|
if (cv === BREAK)
|
|
144
144
|
return BREAK;
|
|
145
145
|
else if (cv === REMOVE)
|
|
@@ -160,17 +160,17 @@ var require_visit = __commonJS({
|
|
|
160
160
|
visitAsync.BREAK = BREAK;
|
|
161
161
|
visitAsync.SKIP = SKIP;
|
|
162
162
|
visitAsync.REMOVE = REMOVE;
|
|
163
|
-
async function visitAsync_(key, node, visitor,
|
|
164
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
163
|
+
async function visitAsync_(key, node, visitor, path69) {
|
|
164
|
+
const ctrl = await callVisitor(key, node, visitor, path69);
|
|
165
165
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
166
|
-
replaceNode(key,
|
|
167
|
-
return visitAsync_(key, ctrl, visitor,
|
|
166
|
+
replaceNode(key, path69, ctrl);
|
|
167
|
+
return visitAsync_(key, ctrl, visitor, path69);
|
|
168
168
|
}
|
|
169
169
|
if (typeof ctrl !== "symbol") {
|
|
170
170
|
if (identity.isCollection(node)) {
|
|
171
|
-
|
|
171
|
+
path69 = Object.freeze(path69.concat(node));
|
|
172
172
|
for (let i = 0; i < node.items.length; ++i) {
|
|
173
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
173
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path69);
|
|
174
174
|
if (typeof ci === "number")
|
|
175
175
|
i = ci - 1;
|
|
176
176
|
else if (ci === BREAK)
|
|
@@ -181,13 +181,13 @@ var require_visit = __commonJS({
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
} else if (identity.isPair(node)) {
|
|
184
|
-
|
|
185
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
184
|
+
path69 = Object.freeze(path69.concat(node));
|
|
185
|
+
const ck = await visitAsync_("key", node.key, visitor, path69);
|
|
186
186
|
if (ck === BREAK)
|
|
187
187
|
return BREAK;
|
|
188
188
|
else if (ck === REMOVE)
|
|
189
189
|
node.key = null;
|
|
190
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
190
|
+
const cv = await visitAsync_("value", node.value, visitor, path69);
|
|
191
191
|
if (cv === BREAK)
|
|
192
192
|
return BREAK;
|
|
193
193
|
else if (cv === REMOVE)
|
|
@@ -214,23 +214,23 @@ var require_visit = __commonJS({
|
|
|
214
214
|
}
|
|
215
215
|
return visitor;
|
|
216
216
|
}
|
|
217
|
-
function callVisitor(key, node, visitor,
|
|
217
|
+
function callVisitor(key, node, visitor, path69) {
|
|
218
218
|
if (typeof visitor === "function")
|
|
219
|
-
return visitor(key, node,
|
|
219
|
+
return visitor(key, node, path69);
|
|
220
220
|
if (identity.isMap(node))
|
|
221
|
-
return visitor.Map?.(key, node,
|
|
221
|
+
return visitor.Map?.(key, node, path69);
|
|
222
222
|
if (identity.isSeq(node))
|
|
223
|
-
return visitor.Seq?.(key, node,
|
|
223
|
+
return visitor.Seq?.(key, node, path69);
|
|
224
224
|
if (identity.isPair(node))
|
|
225
|
-
return visitor.Pair?.(key, node,
|
|
225
|
+
return visitor.Pair?.(key, node, path69);
|
|
226
226
|
if (identity.isScalar(node))
|
|
227
|
-
return visitor.Scalar?.(key, node,
|
|
227
|
+
return visitor.Scalar?.(key, node, path69);
|
|
228
228
|
if (identity.isAlias(node))
|
|
229
|
-
return visitor.Alias?.(key, node,
|
|
229
|
+
return visitor.Alias?.(key, node, path69);
|
|
230
230
|
return void 0;
|
|
231
231
|
}
|
|
232
|
-
function replaceNode(key,
|
|
233
|
-
const parent =
|
|
232
|
+
function replaceNode(key, path69, node) {
|
|
233
|
+
const parent = path69[path69.length - 1];
|
|
234
234
|
if (identity.isCollection(parent)) {
|
|
235
235
|
parent.items[key] = node;
|
|
236
236
|
} else if (identity.isPair(parent)) {
|
|
@@ -840,10 +840,10 @@ var require_Collection = __commonJS({
|
|
|
840
840
|
var createNode = require_createNode();
|
|
841
841
|
var identity = require_identity();
|
|
842
842
|
var Node = require_Node();
|
|
843
|
-
function collectionFromPath(schema,
|
|
843
|
+
function collectionFromPath(schema, path69, value) {
|
|
844
844
|
let v = value;
|
|
845
|
-
for (let i =
|
|
846
|
-
const k =
|
|
845
|
+
for (let i = path69.length - 1; i >= 0; --i) {
|
|
846
|
+
const k = path69[i];
|
|
847
847
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
848
848
|
const a = [];
|
|
849
849
|
a[k] = v;
|
|
@@ -862,7 +862,7 @@ var require_Collection = __commonJS({
|
|
|
862
862
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
863
863
|
});
|
|
864
864
|
}
|
|
865
|
-
var isEmptyPath = (
|
|
865
|
+
var isEmptyPath = (path69) => path69 == null || typeof path69 === "object" && !!path69[Symbol.iterator]().next().done;
|
|
866
866
|
var Collection = class extends Node.NodeBase {
|
|
867
867
|
constructor(type, schema) {
|
|
868
868
|
super(type);
|
|
@@ -892,11 +892,11 @@ var require_Collection = __commonJS({
|
|
|
892
892
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
893
893
|
* that already exists in the map.
|
|
894
894
|
*/
|
|
895
|
-
addIn(
|
|
896
|
-
if (isEmptyPath(
|
|
895
|
+
addIn(path69, value) {
|
|
896
|
+
if (isEmptyPath(path69))
|
|
897
897
|
this.add(value);
|
|
898
898
|
else {
|
|
899
|
-
const [key, ...rest] =
|
|
899
|
+
const [key, ...rest] = path69;
|
|
900
900
|
const node = this.get(key, true);
|
|
901
901
|
if (identity.isCollection(node))
|
|
902
902
|
node.addIn(rest, value);
|
|
@@ -910,8 +910,8 @@ var require_Collection = __commonJS({
|
|
|
910
910
|
* Removes a value from the collection.
|
|
911
911
|
* @returns `true` if the item was found and removed.
|
|
912
912
|
*/
|
|
913
|
-
deleteIn(
|
|
914
|
-
const [key, ...rest] =
|
|
913
|
+
deleteIn(path69) {
|
|
914
|
+
const [key, ...rest] = path69;
|
|
915
915
|
if (rest.length === 0)
|
|
916
916
|
return this.delete(key);
|
|
917
917
|
const node = this.get(key, true);
|
|
@@ -925,8 +925,8 @@ var require_Collection = __commonJS({
|
|
|
925
925
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
926
926
|
* `true` (collections are always returned intact).
|
|
927
927
|
*/
|
|
928
|
-
getIn(
|
|
929
|
-
const [key, ...rest] =
|
|
928
|
+
getIn(path69, keepScalar) {
|
|
929
|
+
const [key, ...rest] = path69;
|
|
930
930
|
const node = this.get(key, true);
|
|
931
931
|
if (rest.length === 0)
|
|
932
932
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -944,8 +944,8 @@ var require_Collection = __commonJS({
|
|
|
944
944
|
/**
|
|
945
945
|
* Checks if the collection includes a value with the key `key`.
|
|
946
946
|
*/
|
|
947
|
-
hasIn(
|
|
948
|
-
const [key, ...rest] =
|
|
947
|
+
hasIn(path69) {
|
|
948
|
+
const [key, ...rest] = path69;
|
|
949
949
|
if (rest.length === 0)
|
|
950
950
|
return this.has(key);
|
|
951
951
|
const node = this.get(key, true);
|
|
@@ -955,8 +955,8 @@ var require_Collection = __commonJS({
|
|
|
955
955
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
956
956
|
* boolean to add/remove the item from the set.
|
|
957
957
|
*/
|
|
958
|
-
setIn(
|
|
959
|
-
const [key, ...rest] =
|
|
958
|
+
setIn(path69, value) {
|
|
959
|
+
const [key, ...rest] = path69;
|
|
960
960
|
if (rest.length === 0) {
|
|
961
961
|
this.set(key, value);
|
|
962
962
|
} else {
|
|
@@ -3471,9 +3471,9 @@ var require_Document = __commonJS({
|
|
|
3471
3471
|
this.contents.add(value);
|
|
3472
3472
|
}
|
|
3473
3473
|
/** Adds a value to the document. */
|
|
3474
|
-
addIn(
|
|
3474
|
+
addIn(path69, value) {
|
|
3475
3475
|
if (assertCollection(this.contents))
|
|
3476
|
-
this.contents.addIn(
|
|
3476
|
+
this.contents.addIn(path69, value);
|
|
3477
3477
|
}
|
|
3478
3478
|
/**
|
|
3479
3479
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -3548,14 +3548,14 @@ var require_Document = __commonJS({
|
|
|
3548
3548
|
* Removes a value from the document.
|
|
3549
3549
|
* @returns `true` if the item was found and removed.
|
|
3550
3550
|
*/
|
|
3551
|
-
deleteIn(
|
|
3552
|
-
if (Collection.isEmptyPath(
|
|
3551
|
+
deleteIn(path69) {
|
|
3552
|
+
if (Collection.isEmptyPath(path69)) {
|
|
3553
3553
|
if (this.contents == null)
|
|
3554
3554
|
return false;
|
|
3555
3555
|
this.contents = null;
|
|
3556
3556
|
return true;
|
|
3557
3557
|
}
|
|
3558
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
3558
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path69) : false;
|
|
3559
3559
|
}
|
|
3560
3560
|
/**
|
|
3561
3561
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -3570,10 +3570,10 @@ var require_Document = __commonJS({
|
|
|
3570
3570
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
3571
3571
|
* `true` (collections are always returned intact).
|
|
3572
3572
|
*/
|
|
3573
|
-
getIn(
|
|
3574
|
-
if (Collection.isEmptyPath(
|
|
3573
|
+
getIn(path69, keepScalar) {
|
|
3574
|
+
if (Collection.isEmptyPath(path69))
|
|
3575
3575
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
3576
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
3576
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path69, keepScalar) : void 0;
|
|
3577
3577
|
}
|
|
3578
3578
|
/**
|
|
3579
3579
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -3584,10 +3584,10 @@ var require_Document = __commonJS({
|
|
|
3584
3584
|
/**
|
|
3585
3585
|
* Checks if the document includes a value at `path`.
|
|
3586
3586
|
*/
|
|
3587
|
-
hasIn(
|
|
3588
|
-
if (Collection.isEmptyPath(
|
|
3587
|
+
hasIn(path69) {
|
|
3588
|
+
if (Collection.isEmptyPath(path69))
|
|
3589
3589
|
return this.contents !== void 0;
|
|
3590
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
3590
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path69) : false;
|
|
3591
3591
|
}
|
|
3592
3592
|
/**
|
|
3593
3593
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -3604,13 +3604,13 @@ var require_Document = __commonJS({
|
|
|
3604
3604
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
3605
3605
|
* boolean to add/remove the item from the set.
|
|
3606
3606
|
*/
|
|
3607
|
-
setIn(
|
|
3608
|
-
if (Collection.isEmptyPath(
|
|
3607
|
+
setIn(path69, value) {
|
|
3608
|
+
if (Collection.isEmptyPath(path69)) {
|
|
3609
3609
|
this.contents = value;
|
|
3610
3610
|
} else if (this.contents == null) {
|
|
3611
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
3611
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path69), value);
|
|
3612
3612
|
} else if (assertCollection(this.contents)) {
|
|
3613
|
-
this.contents.setIn(
|
|
3613
|
+
this.contents.setIn(path69, value);
|
|
3614
3614
|
}
|
|
3615
3615
|
}
|
|
3616
3616
|
/**
|
|
@@ -3996,10 +3996,10 @@ var require_resolve_block_map = __commonJS({
|
|
|
3996
3996
|
let offset = bm.offset;
|
|
3997
3997
|
let commentEnd = null;
|
|
3998
3998
|
for (const collItem of bm.items) {
|
|
3999
|
-
const { start, key, sep:
|
|
3999
|
+
const { start, key, sep: sep7, value } = collItem;
|
|
4000
4000
|
const keyProps = resolveProps.resolveProps(start, {
|
|
4001
4001
|
indicator: "explicit-key-ind",
|
|
4002
|
-
next: key ??
|
|
4002
|
+
next: key ?? sep7?.[0],
|
|
4003
4003
|
offset,
|
|
4004
4004
|
onError,
|
|
4005
4005
|
parentIndent: bm.indent,
|
|
@@ -4013,7 +4013,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4013
4013
|
else if ("indent" in key && key.indent !== bm.indent)
|
|
4014
4014
|
onError(offset, "BAD_INDENT", startColMsg);
|
|
4015
4015
|
}
|
|
4016
|
-
if (!keyProps.anchor && !keyProps.tag && !
|
|
4016
|
+
if (!keyProps.anchor && !keyProps.tag && !sep7) {
|
|
4017
4017
|
commentEnd = keyProps.end;
|
|
4018
4018
|
if (keyProps.comment) {
|
|
4019
4019
|
if (map.comment)
|
|
@@ -4037,7 +4037,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4037
4037
|
ctx.atKey = false;
|
|
4038
4038
|
if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
|
|
4039
4039
|
onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
|
|
4040
|
-
const valueProps = resolveProps.resolveProps(
|
|
4040
|
+
const valueProps = resolveProps.resolveProps(sep7 ?? [], {
|
|
4041
4041
|
indicator: "map-value-ind",
|
|
4042
4042
|
next: value,
|
|
4043
4043
|
offset: keyNode.range[2],
|
|
@@ -4053,7 +4053,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4053
4053
|
if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
|
|
4054
4054
|
onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
|
|
4055
4055
|
}
|
|
4056
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset,
|
|
4056
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep7, null, valueProps, onError);
|
|
4057
4057
|
if (ctx.schema.compat)
|
|
4058
4058
|
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
|
|
4059
4059
|
offset = valueNode.range[2];
|
|
@@ -4144,7 +4144,7 @@ var require_resolve_end = __commonJS({
|
|
|
4144
4144
|
let comment = "";
|
|
4145
4145
|
if (end) {
|
|
4146
4146
|
let hasSpace = false;
|
|
4147
|
-
let
|
|
4147
|
+
let sep7 = "";
|
|
4148
4148
|
for (const token of end) {
|
|
4149
4149
|
const { source, type } = token;
|
|
4150
4150
|
switch (type) {
|
|
@@ -4158,13 +4158,13 @@ var require_resolve_end = __commonJS({
|
|
|
4158
4158
|
if (!comment)
|
|
4159
4159
|
comment = cb;
|
|
4160
4160
|
else
|
|
4161
|
-
comment +=
|
|
4162
|
-
|
|
4161
|
+
comment += sep7 + cb;
|
|
4162
|
+
sep7 = "";
|
|
4163
4163
|
break;
|
|
4164
4164
|
}
|
|
4165
4165
|
case "newline":
|
|
4166
4166
|
if (comment)
|
|
4167
|
-
|
|
4167
|
+
sep7 += source;
|
|
4168
4168
|
hasSpace = true;
|
|
4169
4169
|
break;
|
|
4170
4170
|
default:
|
|
@@ -4207,18 +4207,18 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4207
4207
|
let offset = fc.offset + fc.start.source.length;
|
|
4208
4208
|
for (let i = 0; i < fc.items.length; ++i) {
|
|
4209
4209
|
const collItem = fc.items[i];
|
|
4210
|
-
const { start, key, sep:
|
|
4210
|
+
const { start, key, sep: sep7, value } = collItem;
|
|
4211
4211
|
const props = resolveProps.resolveProps(start, {
|
|
4212
4212
|
flow: fcName,
|
|
4213
4213
|
indicator: "explicit-key-ind",
|
|
4214
|
-
next: key ??
|
|
4214
|
+
next: key ?? sep7?.[0],
|
|
4215
4215
|
offset,
|
|
4216
4216
|
onError,
|
|
4217
4217
|
parentIndent: fc.indent,
|
|
4218
4218
|
startOnNewline: false
|
|
4219
4219
|
});
|
|
4220
4220
|
if (!props.found) {
|
|
4221
|
-
if (!props.anchor && !props.tag && !
|
|
4221
|
+
if (!props.anchor && !props.tag && !sep7 && !value) {
|
|
4222
4222
|
if (i === 0 && props.comma)
|
|
4223
4223
|
onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
|
|
4224
4224
|
else if (i < fc.items.length - 1)
|
|
@@ -4272,8 +4272,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4272
4272
|
}
|
|
4273
4273
|
}
|
|
4274
4274
|
}
|
|
4275
|
-
if (!isMap && !
|
|
4276
|
-
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end,
|
|
4275
|
+
if (!isMap && !sep7 && !props.found) {
|
|
4276
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep7, null, props, onError);
|
|
4277
4277
|
coll.items.push(valueNode);
|
|
4278
4278
|
offset = valueNode.range[2];
|
|
4279
4279
|
if (isBlock(value))
|
|
@@ -4285,7 +4285,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4285
4285
|
if (isBlock(key))
|
|
4286
4286
|
onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
4287
4287
|
ctx.atKey = false;
|
|
4288
|
-
const valueProps = resolveProps.resolveProps(
|
|
4288
|
+
const valueProps = resolveProps.resolveProps(sep7 ?? [], {
|
|
4289
4289
|
flow: fcName,
|
|
4290
4290
|
indicator: "map-value-ind",
|
|
4291
4291
|
next: value,
|
|
@@ -4296,8 +4296,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4296
4296
|
});
|
|
4297
4297
|
if (valueProps.found) {
|
|
4298
4298
|
if (!isMap && !props.found && ctx.options.strict) {
|
|
4299
|
-
if (
|
|
4300
|
-
for (const st of
|
|
4299
|
+
if (sep7)
|
|
4300
|
+
for (const st of sep7) {
|
|
4301
4301
|
if (st === valueProps.found)
|
|
4302
4302
|
break;
|
|
4303
4303
|
if (st.type === "newline") {
|
|
@@ -4314,7 +4314,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4314
4314
|
else
|
|
4315
4315
|
onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
|
|
4316
4316
|
}
|
|
4317
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end,
|
|
4317
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep7, null, valueProps, onError) : null;
|
|
4318
4318
|
if (valueNode) {
|
|
4319
4319
|
if (isBlock(value))
|
|
4320
4320
|
onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
@@ -4494,7 +4494,7 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
4494
4494
|
chompStart = i + 1;
|
|
4495
4495
|
}
|
|
4496
4496
|
let value = "";
|
|
4497
|
-
let
|
|
4497
|
+
let sep7 = "";
|
|
4498
4498
|
let prevMoreIndented = false;
|
|
4499
4499
|
for (let i = 0; i < contentStart; ++i)
|
|
4500
4500
|
value += lines[i][0].slice(trimIndent) + "\n";
|
|
@@ -4511,24 +4511,24 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
4511
4511
|
indent = "";
|
|
4512
4512
|
}
|
|
4513
4513
|
if (type === Scalar.Scalar.BLOCK_LITERAL) {
|
|
4514
|
-
value +=
|
|
4515
|
-
|
|
4514
|
+
value += sep7 + indent.slice(trimIndent) + content;
|
|
4515
|
+
sep7 = "\n";
|
|
4516
4516
|
} else if (indent.length > trimIndent || content[0] === " ") {
|
|
4517
|
-
if (
|
|
4518
|
-
|
|
4519
|
-
else if (!prevMoreIndented &&
|
|
4520
|
-
|
|
4521
|
-
value +=
|
|
4522
|
-
|
|
4517
|
+
if (sep7 === " ")
|
|
4518
|
+
sep7 = "\n";
|
|
4519
|
+
else if (!prevMoreIndented && sep7 === "\n")
|
|
4520
|
+
sep7 = "\n\n";
|
|
4521
|
+
value += sep7 + indent.slice(trimIndent) + content;
|
|
4522
|
+
sep7 = "\n";
|
|
4523
4523
|
prevMoreIndented = true;
|
|
4524
4524
|
} else if (content === "") {
|
|
4525
|
-
if (
|
|
4525
|
+
if (sep7 === "\n")
|
|
4526
4526
|
value += "\n";
|
|
4527
4527
|
else
|
|
4528
|
-
|
|
4528
|
+
sep7 = "\n";
|
|
4529
4529
|
} else {
|
|
4530
|
-
value +=
|
|
4531
|
-
|
|
4530
|
+
value += sep7 + content;
|
|
4531
|
+
sep7 = " ";
|
|
4532
4532
|
prevMoreIndented = false;
|
|
4533
4533
|
}
|
|
4534
4534
|
}
|
|
@@ -4710,25 +4710,25 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
4710
4710
|
if (!match)
|
|
4711
4711
|
return source;
|
|
4712
4712
|
let res = match[1];
|
|
4713
|
-
let
|
|
4713
|
+
let sep7 = " ";
|
|
4714
4714
|
let pos = first.lastIndex;
|
|
4715
4715
|
line.lastIndex = pos;
|
|
4716
4716
|
while (match = line.exec(source)) {
|
|
4717
4717
|
if (match[1] === "") {
|
|
4718
|
-
if (
|
|
4719
|
-
res +=
|
|
4718
|
+
if (sep7 === "\n")
|
|
4719
|
+
res += sep7;
|
|
4720
4720
|
else
|
|
4721
|
-
|
|
4721
|
+
sep7 = "\n";
|
|
4722
4722
|
} else {
|
|
4723
|
-
res +=
|
|
4724
|
-
|
|
4723
|
+
res += sep7 + match[1];
|
|
4724
|
+
sep7 = " ";
|
|
4725
4725
|
}
|
|
4726
4726
|
pos = line.lastIndex;
|
|
4727
4727
|
}
|
|
4728
4728
|
const last = /[ \t]*(.*)/sy;
|
|
4729
4729
|
last.lastIndex = pos;
|
|
4730
4730
|
match = last.exec(source);
|
|
4731
|
-
return res +
|
|
4731
|
+
return res + sep7 + (match?.[1] ?? "");
|
|
4732
4732
|
}
|
|
4733
4733
|
function doubleQuotedValue(source, onError) {
|
|
4734
4734
|
let res = "";
|
|
@@ -5538,14 +5538,14 @@ var require_cst_stringify = __commonJS({
|
|
|
5538
5538
|
}
|
|
5539
5539
|
}
|
|
5540
5540
|
}
|
|
5541
|
-
function stringifyItem({ start, key, sep:
|
|
5541
|
+
function stringifyItem({ start, key, sep: sep7, value }) {
|
|
5542
5542
|
let res = "";
|
|
5543
5543
|
for (const st of start)
|
|
5544
5544
|
res += st.source;
|
|
5545
5545
|
if (key)
|
|
5546
5546
|
res += stringifyToken(key);
|
|
5547
|
-
if (
|
|
5548
|
-
for (const st of
|
|
5547
|
+
if (sep7)
|
|
5548
|
+
for (const st of sep7)
|
|
5549
5549
|
res += st.source;
|
|
5550
5550
|
if (value)
|
|
5551
5551
|
res += stringifyToken(value);
|
|
@@ -5570,9 +5570,9 @@ var require_cst_visit = __commonJS({
|
|
|
5570
5570
|
visit.BREAK = BREAK;
|
|
5571
5571
|
visit.SKIP = SKIP;
|
|
5572
5572
|
visit.REMOVE = REMOVE;
|
|
5573
|
-
visit.itemAtPath = (cst,
|
|
5573
|
+
visit.itemAtPath = (cst, path69) => {
|
|
5574
5574
|
let item = cst;
|
|
5575
|
-
for (const [field, index] of
|
|
5575
|
+
for (const [field, index] of path69) {
|
|
5576
5576
|
const tok = item?.[field];
|
|
5577
5577
|
if (tok && "items" in tok) {
|
|
5578
5578
|
item = tok.items[index];
|
|
@@ -5581,23 +5581,23 @@ var require_cst_visit = __commonJS({
|
|
|
5581
5581
|
}
|
|
5582
5582
|
return item;
|
|
5583
5583
|
};
|
|
5584
|
-
visit.parentCollection = (cst,
|
|
5585
|
-
const parent = visit.itemAtPath(cst,
|
|
5586
|
-
const field =
|
|
5584
|
+
visit.parentCollection = (cst, path69) => {
|
|
5585
|
+
const parent = visit.itemAtPath(cst, path69.slice(0, -1));
|
|
5586
|
+
const field = path69[path69.length - 1][0];
|
|
5587
5587
|
const coll = parent?.[field];
|
|
5588
5588
|
if (coll && "items" in coll)
|
|
5589
5589
|
return coll;
|
|
5590
5590
|
throw new Error("Parent collection not found");
|
|
5591
5591
|
};
|
|
5592
|
-
function _visit(
|
|
5593
|
-
let ctrl = visitor(item,
|
|
5592
|
+
function _visit(path69, item, visitor) {
|
|
5593
|
+
let ctrl = visitor(item, path69);
|
|
5594
5594
|
if (typeof ctrl === "symbol")
|
|
5595
5595
|
return ctrl;
|
|
5596
5596
|
for (const field of ["key", "value"]) {
|
|
5597
5597
|
const token = item[field];
|
|
5598
5598
|
if (token && "items" in token) {
|
|
5599
5599
|
for (let i = 0; i < token.items.length; ++i) {
|
|
5600
|
-
const ci = _visit(Object.freeze(
|
|
5600
|
+
const ci = _visit(Object.freeze(path69.concat([[field, i]])), token.items[i], visitor);
|
|
5601
5601
|
if (typeof ci === "number")
|
|
5602
5602
|
i = ci - 1;
|
|
5603
5603
|
else if (ci === BREAK)
|
|
@@ -5608,10 +5608,10 @@ var require_cst_visit = __commonJS({
|
|
|
5608
5608
|
}
|
|
5609
5609
|
}
|
|
5610
5610
|
if (typeof ctrl === "function" && field === "key")
|
|
5611
|
-
ctrl = ctrl(item,
|
|
5611
|
+
ctrl = ctrl(item, path69);
|
|
5612
5612
|
}
|
|
5613
5613
|
}
|
|
5614
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
5614
|
+
return typeof ctrl === "function" ? ctrl(item, path69) : ctrl;
|
|
5615
5615
|
}
|
|
5616
5616
|
exports.visit = visit;
|
|
5617
5617
|
}
|
|
@@ -6712,18 +6712,18 @@ var require_parser = __commonJS({
|
|
|
6712
6712
|
if (this.type === "map-value-ind") {
|
|
6713
6713
|
const prev = getPrevProps(this.peek(2));
|
|
6714
6714
|
const start = getFirstKeyStartProps(prev);
|
|
6715
|
-
let
|
|
6715
|
+
let sep7;
|
|
6716
6716
|
if (scalar.end) {
|
|
6717
|
-
|
|
6718
|
-
|
|
6717
|
+
sep7 = scalar.end;
|
|
6718
|
+
sep7.push(this.sourceToken);
|
|
6719
6719
|
delete scalar.end;
|
|
6720
6720
|
} else
|
|
6721
|
-
|
|
6721
|
+
sep7 = [this.sourceToken];
|
|
6722
6722
|
const map = {
|
|
6723
6723
|
type: "block-map",
|
|
6724
6724
|
offset: scalar.offset,
|
|
6725
6725
|
indent: scalar.indent,
|
|
6726
|
-
items: [{ start, key: scalar, sep:
|
|
6726
|
+
items: [{ start, key: scalar, sep: sep7 }]
|
|
6727
6727
|
};
|
|
6728
6728
|
this.onKeyLine = true;
|
|
6729
6729
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -6876,15 +6876,15 @@ var require_parser = __commonJS({
|
|
|
6876
6876
|
} else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
|
|
6877
6877
|
const start2 = getFirstKeyStartProps(it.start);
|
|
6878
6878
|
const key = it.key;
|
|
6879
|
-
const
|
|
6880
|
-
|
|
6879
|
+
const sep7 = it.sep;
|
|
6880
|
+
sep7.push(this.sourceToken);
|
|
6881
6881
|
delete it.key;
|
|
6882
6882
|
delete it.sep;
|
|
6883
6883
|
this.stack.push({
|
|
6884
6884
|
type: "block-map",
|
|
6885
6885
|
offset: this.offset,
|
|
6886
6886
|
indent: this.indent,
|
|
6887
|
-
items: [{ start: start2, key, sep:
|
|
6887
|
+
items: [{ start: start2, key, sep: sep7 }]
|
|
6888
6888
|
});
|
|
6889
6889
|
} else if (start.length > 0) {
|
|
6890
6890
|
it.sep = it.sep.concat(start, this.sourceToken);
|
|
@@ -6913,14 +6913,14 @@ var require_parser = __commonJS({
|
|
|
6913
6913
|
case "scalar":
|
|
6914
6914
|
case "single-quoted-scalar":
|
|
6915
6915
|
case "double-quoted-scalar": {
|
|
6916
|
-
const
|
|
6916
|
+
const fs66 = this.flowScalar(this.type);
|
|
6917
6917
|
if (atNextItem || it.value) {
|
|
6918
|
-
map.items.push({ start, key:
|
|
6918
|
+
map.items.push({ start, key: fs66, sep: [] });
|
|
6919
6919
|
this.onKeyLine = true;
|
|
6920
6920
|
} else if (it.sep) {
|
|
6921
|
-
this.stack.push(
|
|
6921
|
+
this.stack.push(fs66);
|
|
6922
6922
|
} else {
|
|
6923
|
-
Object.assign(it, { key:
|
|
6923
|
+
Object.assign(it, { key: fs66, sep: [] });
|
|
6924
6924
|
this.onKeyLine = true;
|
|
6925
6925
|
}
|
|
6926
6926
|
return;
|
|
@@ -7048,13 +7048,13 @@ var require_parser = __commonJS({
|
|
|
7048
7048
|
case "scalar":
|
|
7049
7049
|
case "single-quoted-scalar":
|
|
7050
7050
|
case "double-quoted-scalar": {
|
|
7051
|
-
const
|
|
7051
|
+
const fs66 = this.flowScalar(this.type);
|
|
7052
7052
|
if (!it || it.value)
|
|
7053
|
-
fc.items.push({ start: [], key:
|
|
7053
|
+
fc.items.push({ start: [], key: fs66, sep: [] });
|
|
7054
7054
|
else if (it.sep)
|
|
7055
|
-
this.stack.push(
|
|
7055
|
+
this.stack.push(fs66);
|
|
7056
7056
|
else
|
|
7057
|
-
Object.assign(it, { key:
|
|
7057
|
+
Object.assign(it, { key: fs66, sep: [] });
|
|
7058
7058
|
return;
|
|
7059
7059
|
}
|
|
7060
7060
|
case "flow-map-end":
|
|
@@ -7078,13 +7078,13 @@ var require_parser = __commonJS({
|
|
|
7078
7078
|
const prev = getPrevProps(parent);
|
|
7079
7079
|
const start = getFirstKeyStartProps(prev);
|
|
7080
7080
|
fixFlowSeqItems(fc);
|
|
7081
|
-
const
|
|
7082
|
-
|
|
7081
|
+
const sep7 = fc.end.splice(1, fc.end.length);
|
|
7082
|
+
sep7.push(this.sourceToken);
|
|
7083
7083
|
const map = {
|
|
7084
7084
|
type: "block-map",
|
|
7085
7085
|
offset: fc.offset,
|
|
7086
7086
|
indent: fc.indent,
|
|
7087
|
-
items: [{ start, key: fc, sep:
|
|
7087
|
+
items: [{ start, key: fc, sep: sep7 }]
|
|
7088
7088
|
};
|
|
7089
7089
|
this.onKeyLine = true;
|
|
7090
7090
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -7363,15 +7363,15 @@ var require_dist = __commonJS({
|
|
|
7363
7363
|
});
|
|
7364
7364
|
|
|
7365
7365
|
// src/scripts/hooks/dispatch_entry.ts
|
|
7366
|
-
import * as
|
|
7367
|
-
import { fileURLToPath as
|
|
7366
|
+
import * as path68 from "node:path";
|
|
7367
|
+
import { fileURLToPath as fileURLToPath48 } from "node:url";
|
|
7368
7368
|
|
|
7369
7369
|
// src/scripts/hooks/dispatch_hook.ts
|
|
7370
7370
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
7371
7371
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
7372
|
-
import
|
|
7373
|
-
import
|
|
7374
|
-
import { fileURLToPath as
|
|
7372
|
+
import fs65 from "node:fs";
|
|
7373
|
+
import path67 from "node:path";
|
|
7374
|
+
import { fileURLToPath as fileURLToPath47, pathToFileURL as pathToFileURL41 } from "node:url";
|
|
7375
7375
|
|
|
7376
7376
|
// src/scripts/_lib/spawn_env.ts
|
|
7377
7377
|
var DENY_EXACT = /* @__PURE__ */ new Set([
|
|
@@ -14036,6 +14036,11 @@ var import_yaml3 = __toESM(require_dist(), 1);
|
|
|
14036
14036
|
import * as fs14 from "node:fs";
|
|
14037
14037
|
import * as os2 from "node:os";
|
|
14038
14038
|
import * as path13 from "node:path";
|
|
14039
|
+
|
|
14040
|
+
// src/scripts/ai_council/quorum.ts
|
|
14041
|
+
var SOLO_FLOOR_MIN_PRESENT = 2;
|
|
14042
|
+
|
|
14043
|
+
// src/scripts/ai_council/config.ts
|
|
14039
14044
|
var _VALID_PROVIDERS = /* @__PURE__ */ new Set([
|
|
14040
14045
|
"anthropic",
|
|
14041
14046
|
"openai",
|
|
@@ -14342,6 +14347,9 @@ function _build_config(raw, source_path) {
|
|
|
14342
14347
|
_asDict(_getOr(raw, "cli_call_budget", {}))
|
|
14343
14348
|
);
|
|
14344
14349
|
const quorum = _build_quorum(_get(raw, "quorum", "majority"));
|
|
14350
|
+
const quorum_min_present = _build_quorum_min_present(
|
|
14351
|
+
_get(raw, "quorum_min_present", SOLO_FLOOR_MIN_PRESENT)
|
|
14352
|
+
);
|
|
14345
14353
|
const necessity_classifier = _build_necessity_classifier(
|
|
14346
14354
|
_asDict(_getOr(raw, "necessity_classifier", {}))
|
|
14347
14355
|
);
|
|
@@ -14390,6 +14398,7 @@ function _build_config(raw, source_path) {
|
|
|
14390
14398
|
consensus_scoring: consensus,
|
|
14391
14399
|
cli_call_budget,
|
|
14392
14400
|
quorum,
|
|
14401
|
+
quorum_min_present,
|
|
14393
14402
|
necessity_classifier,
|
|
14394
14403
|
model_downgrade,
|
|
14395
14404
|
debate,
|
|
@@ -15217,6 +15226,14 @@ function _build_quorum(raw) {
|
|
|
15217
15226
|
`\`quorum\`=${_pyRepr3(raw)} must be 'majority' or an integer >= 1 (got ${_pyTypeName(raw)}).`
|
|
15218
15227
|
);
|
|
15219
15228
|
}
|
|
15229
|
+
function _build_quorum_min_present(raw) {
|
|
15230
|
+
if (_isInt(raw) && raw >= 1) {
|
|
15231
|
+
return raw;
|
|
15232
|
+
}
|
|
15233
|
+
throw new CouncilConfigError(
|
|
15234
|
+
`\`quorum_min_present\`=${_pyRepr3(raw)} must be an integer >= 1 (got ${_pyTypeName(raw)}).`
|
|
15235
|
+
);
|
|
15236
|
+
}
|
|
15220
15237
|
function _build_advisor(name, cfg) {
|
|
15221
15238
|
if (!_isDict(cfg)) {
|
|
15222
15239
|
throw new CouncilConfigError(`advisors.${name}: must be a mapping.`);
|
|
@@ -20494,35 +20511,109 @@ function foreign_live_records(dir, session_id, options = {}) {
|
|
|
20494
20511
|
const own = safe_stem(session_id);
|
|
20495
20512
|
return read_live_records(dir, options).filter((r) => safe_stem(r.session_id) !== own);
|
|
20496
20513
|
}
|
|
20514
|
+
function classify_collisions(others, here) {
|
|
20515
|
+
const out = [];
|
|
20516
|
+
for (const r of others) {
|
|
20517
|
+
if (here.roadmap_slug !== null && r.roadmap_slug !== null && r.roadmap_slug === here.roadmap_slug) {
|
|
20518
|
+
out.push({ kind: "roadmap", record: r });
|
|
20519
|
+
}
|
|
20520
|
+
}
|
|
20521
|
+
for (const r of others) {
|
|
20522
|
+
if (here.branch !== null && r.branch === here.branch) {
|
|
20523
|
+
out.push({ kind: "branch", record: r });
|
|
20524
|
+
}
|
|
20525
|
+
}
|
|
20526
|
+
return out;
|
|
20527
|
+
}
|
|
20497
20528
|
|
|
20498
20529
|
// src/scripts/session_register_hook.ts
|
|
20499
20530
|
var REPLAY_ENV_VAR6 = "AGENT_CONFIG_REPLAY";
|
|
20500
|
-
var
|
|
20531
|
+
var _STATE_REL = path42.join("agents", "runtime", "state");
|
|
20532
|
+
var ROADMAP_CLAIM_REL = path42.join(_STATE_REL, "roadmap-claim.json");
|
|
20533
|
+
function roadmap_claim_rel(session_id) {
|
|
20534
|
+
const id = String(session_id ?? "").trim();
|
|
20535
|
+
if (id === "") {
|
|
20536
|
+
return ROADMAP_CLAIM_REL;
|
|
20537
|
+
}
|
|
20538
|
+
const rel = path42.join(_STATE_REL, `roadmap-claim-${safe_stem(id)}.json`);
|
|
20539
|
+
const norm = path42.normalize(rel);
|
|
20540
|
+
if (!norm.startsWith(`${_STATE_REL}${path42.sep}`) || norm.includes("..")) {
|
|
20541
|
+
return ROADMAP_CLAIM_REL;
|
|
20542
|
+
}
|
|
20543
|
+
return norm;
|
|
20544
|
+
}
|
|
20501
20545
|
function _is_replay_mode4() {
|
|
20502
20546
|
return String(process9.env[REPLAY_ENV_VAR6] ?? "").trim() !== "";
|
|
20503
20547
|
}
|
|
20504
|
-
function
|
|
20548
|
+
function _read_claim_file(file) {
|
|
20505
20549
|
try {
|
|
20506
|
-
const
|
|
20507
|
-
|
|
20508
|
-
|
|
20509
|
-
const slug = parsed["slug"];
|
|
20510
|
-
if (typeof slug === "string" && slug.trim().length > 0) {
|
|
20511
|
-
return slug.trim();
|
|
20512
|
-
}
|
|
20550
|
+
const parsed = JSON.parse(fs41.readFileSync(file, "utf-8"));
|
|
20551
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
20552
|
+
return null;
|
|
20513
20553
|
}
|
|
20514
|
-
|
|
20554
|
+
const rec = parsed;
|
|
20555
|
+
const slug = rec["slug"];
|
|
20556
|
+
if (typeof slug !== "string" || slug.trim().length === 0) {
|
|
20557
|
+
return null;
|
|
20558
|
+
}
|
|
20559
|
+
const sid = rec["session_id"];
|
|
20560
|
+
return {
|
|
20561
|
+
slug: slug.trim(),
|
|
20562
|
+
...typeof sid === "string" && sid.trim() !== "" ? { session_id: sid.trim() } : {}
|
|
20563
|
+
};
|
|
20515
20564
|
} catch {
|
|
20516
20565
|
return null;
|
|
20517
20566
|
}
|
|
20518
20567
|
}
|
|
20568
|
+
function read_claimed_slug(workspace_root, session_id) {
|
|
20569
|
+
const own = roadmap_claim_rel(session_id);
|
|
20570
|
+
if (own !== ROADMAP_CLAIM_REL) {
|
|
20571
|
+
const mine = _read_claim_file(path42.join(workspace_root, own));
|
|
20572
|
+
if (mine !== null) {
|
|
20573
|
+
return mine.slug;
|
|
20574
|
+
}
|
|
20575
|
+
}
|
|
20576
|
+
const legacy = _read_claim_file(path42.join(workspace_root, ROADMAP_CLAIM_REL));
|
|
20577
|
+
if (legacy === null) {
|
|
20578
|
+
return null;
|
|
20579
|
+
}
|
|
20580
|
+
const id = String(session_id ?? "").trim();
|
|
20581
|
+
if (id !== "") {
|
|
20582
|
+
return null;
|
|
20583
|
+
}
|
|
20584
|
+
return legacy.slug;
|
|
20585
|
+
}
|
|
20586
|
+
function claim_is_stale(workspace_root, slug, peer_worktree) {
|
|
20587
|
+
if (slug === null || slug.trim() === "") {
|
|
20588
|
+
return false;
|
|
20589
|
+
}
|
|
20590
|
+
const base = slug.trim().replace(/\.md$/, "");
|
|
20591
|
+
const rel = path42.normalize(path42.join("agents", "roadmaps", `${base}.md`));
|
|
20592
|
+
const inside = rel.startsWith(`agents${path42.sep}roadmaps${path42.sep}`) && !rel.includes("..");
|
|
20593
|
+
if (!inside || path42.isAbsolute(base)) {
|
|
20594
|
+
return true;
|
|
20595
|
+
}
|
|
20596
|
+
const roots = [peer_worktree, workspace_root].filter(
|
|
20597
|
+
(r) => typeof r === "string" && r.trim() !== ""
|
|
20598
|
+
);
|
|
20599
|
+
for (const root of roots) {
|
|
20600
|
+
try {
|
|
20601
|
+
if (fs41.existsSync(path42.join(root, rel))) {
|
|
20602
|
+
return false;
|
|
20603
|
+
}
|
|
20604
|
+
} catch {
|
|
20605
|
+
return false;
|
|
20606
|
+
}
|
|
20607
|
+
}
|
|
20608
|
+
return true;
|
|
20609
|
+
}
|
|
20519
20610
|
function build_record(workspace_root, session_id, platform, started_at, now = /* @__PURE__ */ new Date()) {
|
|
20520
20611
|
return {
|
|
20521
20612
|
session_id,
|
|
20522
20613
|
platform,
|
|
20523
20614
|
worktree: workspace_root,
|
|
20524
20615
|
branch: current_branch(workspace_root),
|
|
20525
|
-
roadmap_slug: read_claimed_slug(workspace_root),
|
|
20616
|
+
roadmap_slug: read_claimed_slug(workspace_root, session_id),
|
|
20526
20617
|
started_at,
|
|
20527
20618
|
last_seen: iso_now(now)
|
|
20528
20619
|
};
|
|
@@ -20540,20 +20631,26 @@ function foreign_sessions_block(workspace_root, session_id, now = /* @__PURE__ *
|
|
|
20540
20631
|
const others = foreign_live_records(dir, session_id, { prune: true, now });
|
|
20541
20632
|
if (others.length === 0) return null;
|
|
20542
20633
|
const here = current_branch(workspace_root);
|
|
20634
|
+
const my_slug = read_claimed_slug(workspace_root, session_id);
|
|
20543
20635
|
const lines = [];
|
|
20544
|
-
|
|
20636
|
+
const live_others = [];
|
|
20545
20637
|
for (const r of others) {
|
|
20546
20638
|
const age_min = Math.max(0, Math.round((now.getTime() - Date.parse(r.last_seen)) / 6e4));
|
|
20547
|
-
const
|
|
20639
|
+
const stale = claim_is_stale(workspace_root, r.roadmap_slug, r.worktree);
|
|
20640
|
+
const slug = r.roadmap_slug === null ? "no roadmap claimed" : stale ? `roadmap: ${r.roadmap_slug} (STALE \u2014 no such open roadmap; treat as no claim)` : `roadmap: ${r.roadmap_slug}`;
|
|
20548
20641
|
const ttl_note = ttl_is_measured(r.platform) ? "" : ` \xB7 unmeasured host, TTL falls back to ${Math.round(ttl_seconds_for(r.platform) / 3600)}h`;
|
|
20549
20642
|
lines.push(
|
|
20550
20643
|
`- ${r.platform} \xB7 branch \`${r.branch ?? "detached"}\` \xB7 ${slug} \xB7 last seen ${age_min} min ago${ttl_note}
|
|
20551
20644
|
worktree: ${r.worktree}`
|
|
20552
20645
|
);
|
|
20553
|
-
|
|
20554
|
-
collision = r;
|
|
20555
|
-
}
|
|
20646
|
+
live_others.push(stale ? { ...r, roadmap_slug: null } : r);
|
|
20556
20647
|
}
|
|
20648
|
+
const collisions = classify_collisions(live_others, {
|
|
20649
|
+
branch: here,
|
|
20650
|
+
roadmap_slug: claim_is_stale(workspace_root, my_slug) ? null : my_slug
|
|
20651
|
+
});
|
|
20652
|
+
const roadmap_hits = collisions.filter((c) => c.kind === "roadmap");
|
|
20653
|
+
const branch_hit = collisions.find((c) => c.kind === "branch") ?? null;
|
|
20557
20654
|
const parts = [
|
|
20558
20655
|
"<session-register>",
|
|
20559
20656
|
"The following OTHER agent sessions are live on this repository right now.",
|
|
@@ -20561,7 +20658,23 @@ function foreign_sessions_block(workspace_root, session_id, now = /* @__PURE__ *
|
|
|
20561
20658
|
"",
|
|
20562
20659
|
...lines
|
|
20563
20660
|
];
|
|
20564
|
-
if (
|
|
20661
|
+
if (roadmap_hits.length > 0) {
|
|
20662
|
+
parts.push(
|
|
20663
|
+
"",
|
|
20664
|
+
`DUPLICATE WORK: ${roadmap_hits.length} other live session(s) claim the SAME roadmap \`${my_slug}\`.`,
|
|
20665
|
+
...roadmap_hits.map(
|
|
20666
|
+
(h) => ` \xB7 branch \`${h.record.branch ?? "detached"}\` in ${h.record.worktree}`
|
|
20667
|
+
),
|
|
20668
|
+
"A different branch name does NOT make this a different task \u2014 measured twice,",
|
|
20669
|
+
"two sessions built one roadmap phase under two branch names and one PR was wasted.",
|
|
20670
|
+
"STOP before writing code. Ask the user ONCE, as numbered options:",
|
|
20671
|
+
" 1. Take a different roadmap (`agent-config sessions:list` shows what is held)",
|
|
20672
|
+
" 2. Split the roadmap explicitly \u2014 name which phases are yours",
|
|
20673
|
+
" 3. Continue anyway, accepting that one of the two results is discarded",
|
|
20674
|
+
"Never decide silently, in either direction."
|
|
20675
|
+
);
|
|
20676
|
+
}
|
|
20677
|
+
if (branch_hit !== null) {
|
|
20565
20678
|
parts.push(
|
|
20566
20679
|
"",
|
|
20567
20680
|
`COLLISION: another live session already holds branch \`${here}\`.`,
|
|
@@ -20602,6 +20715,10 @@ function main25() {
|
|
|
20602
20715
|
if (event === "session_end" || event === "stop" && stop_means_session_end(platform)) {
|
|
20603
20716
|
const dir = register_dir(root);
|
|
20604
20717
|
if (dir !== null) delete_record(dir, session_id);
|
|
20718
|
+
try {
|
|
20719
|
+
fs41.unlinkSync(path42.join(root, roadmap_claim_rel(session_id)));
|
|
20720
|
+
} catch {
|
|
20721
|
+
}
|
|
20605
20722
|
return 0;
|
|
20606
20723
|
}
|
|
20607
20724
|
if (event === "session_start" || event === "user_prompt_submit" || event === "stop") {
|
|
@@ -22528,7 +22645,7 @@ import { fileURLToPath as fileURLToPath36, pathToFileURL as pathToFileURL29 } fr
|
|
|
22528
22645
|
|
|
22529
22646
|
// src/install/rtkDetection.ts
|
|
22530
22647
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
22531
|
-
import { existsSync as
|
|
22648
|
+
import { existsSync as existsSync9, statSync as statSync9, readFileSync as readFileSync19, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9 } from "node:fs";
|
|
22532
22649
|
import { homedir as homedir4 } from "node:os";
|
|
22533
22650
|
import { delimiter, join as join19, dirname as dirname9 } from "node:path";
|
|
22534
22651
|
var TOKEN_KILLER_GAIN_SIGNATURE = /RTK Token Savings/;
|
|
@@ -22541,7 +22658,7 @@ function resolveBinaryOnPath(name, pathEnv) {
|
|
|
22541
22658
|
if (dir.length === 0) continue;
|
|
22542
22659
|
for (const suffix of suffixes) {
|
|
22543
22660
|
const candidate = join19(dir, `${name}${suffix}`);
|
|
22544
|
-
if (
|
|
22661
|
+
if (existsSync9(candidate)) return candidate;
|
|
22545
22662
|
}
|
|
22546
22663
|
}
|
|
22547
22664
|
return null;
|
|
@@ -22878,6 +22995,44 @@ import fs51 from "node:fs";
|
|
|
22878
22995
|
import path52 from "node:path";
|
|
22879
22996
|
import { fileURLToPath as fileURLToPath37, pathToFileURL as pathToFileURL30 } from "node:url";
|
|
22880
22997
|
|
|
22998
|
+
// src/scripts/_lib/ui_surface.ts
|
|
22999
|
+
var UI_EXTENSIONS = [
|
|
23000
|
+
"html",
|
|
23001
|
+
"htm",
|
|
23002
|
+
"css",
|
|
23003
|
+
"scss",
|
|
23004
|
+
"sass",
|
|
23005
|
+
"less",
|
|
23006
|
+
"vue",
|
|
23007
|
+
"svelte",
|
|
23008
|
+
"astro",
|
|
23009
|
+
"jsx",
|
|
23010
|
+
"tsx"
|
|
23011
|
+
];
|
|
23012
|
+
var UI_COMPOUND_SUFFIXES = [".blade.php"];
|
|
23013
|
+
var UI_EXT = new RegExp(
|
|
23014
|
+
`(\\.(${UI_EXTENSIONS.join("|")})|${UI_COMPOUND_SUFFIXES.map((s) => s.replace(/\./g, "\\.")).join("|")})$`,
|
|
23015
|
+
"i"
|
|
23016
|
+
);
|
|
23017
|
+
function isUiPath(p) {
|
|
23018
|
+
return UI_EXT.test(p);
|
|
23019
|
+
}
|
|
23020
|
+
var UI_PATH_FRAGMENTS = [
|
|
23021
|
+
"resources/views/",
|
|
23022
|
+
"resources/js/",
|
|
23023
|
+
// `components/` already subsumes `src/components/` under substring
|
|
23024
|
+
// matching — listing both here would be dead weight. The rules' own
|
|
23025
|
+
// `path_prefix` list keeps both because matching there is anchored.
|
|
23026
|
+
"components/",
|
|
23027
|
+
"pages/"
|
|
23028
|
+
];
|
|
23029
|
+
var UI_TREE_EXCLUSIONS = ["pages/api/"];
|
|
23030
|
+
function isUiTreePath(p) {
|
|
23031
|
+
const normalized = p.replace(/\\/g, "/").toLowerCase();
|
|
23032
|
+
if (UI_TREE_EXCLUSIONS.some((fragment) => normalized.includes(fragment))) return false;
|
|
23033
|
+
return UI_PATH_FRAGMENTS.some((fragment) => normalized.includes(fragment));
|
|
23034
|
+
}
|
|
23035
|
+
|
|
22881
23036
|
// src/scripts/lint_design_slop.ts
|
|
22882
23037
|
import fs50 from "node:fs";
|
|
22883
23038
|
import path51 from "node:path";
|
|
@@ -23467,7 +23622,6 @@ var SETTINGS_FILE7 = ".agent-settings.yml";
|
|
|
23467
23622
|
var EXIT_ALLOW13 = 0;
|
|
23468
23623
|
var EXIT_WARN6 = 2;
|
|
23469
23624
|
var DEGRADE_AFTER = 3;
|
|
23470
|
-
var UI_EXT = /\.(html|htm|css|scss|sass|less|vue|svelte|astro|jsx|tsx)$/i;
|
|
23471
23625
|
function isObject2(v) {
|
|
23472
23626
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
23473
23627
|
}
|
|
@@ -23876,11 +24030,180 @@ function isCliEntry11() {
|
|
|
23876
24030
|
}
|
|
23877
24031
|
if (isCliEntry11()) process.exit(main36());
|
|
23878
24032
|
|
|
23879
|
-
// src/scripts/hooks/
|
|
23880
|
-
import * as crypto4 from "node:crypto";
|
|
24033
|
+
// src/scripts/hooks/ui_route_nudge_hook.ts
|
|
23881
24034
|
import * as fs55 from "node:fs";
|
|
23882
24035
|
import * as path56 from "node:path";
|
|
23883
|
-
import { fileURLToPath as fileURLToPath39, pathToFileURL as
|
|
24036
|
+
import { fileURLToPath as fileURLToPath39, pathToFileURL as pathToFileURL32 } from "node:url";
|
|
24037
|
+
|
|
24038
|
+
// src/scripts/_lib/hook_settings.ts
|
|
24039
|
+
import * as fs54 from "node:fs";
|
|
24040
|
+
import * as path55 from "node:path";
|
|
24041
|
+
var SETTINGS_FILE9 = ".agent-settings.yml";
|
|
24042
|
+
function hookSectionEnabled(root, section) {
|
|
24043
|
+
const file = path55.join(root, SETTINGS_FILE9);
|
|
24044
|
+
let text;
|
|
24045
|
+
try {
|
|
24046
|
+
if (!fs54.statSync(file).isFile()) return false;
|
|
24047
|
+
text = fs54.readFileSync(file, "utf-8");
|
|
24048
|
+
} catch {
|
|
24049
|
+
return false;
|
|
24050
|
+
}
|
|
24051
|
+
const escaped = section.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24052
|
+
const sectionPattern = new RegExp(`^(\\s+)${escaped}\\s*:\\s*$`);
|
|
24053
|
+
let inHooks = false;
|
|
24054
|
+
let sectionIndent = null;
|
|
24055
|
+
const indentOf = (line) => line.length - line.replace(/^\s+/, "").length;
|
|
24056
|
+
for (const raw of text.split(/\r\n|\r|\n/)) {
|
|
24057
|
+
const line = raw.replace(/\s+$/, "");
|
|
24058
|
+
if (!line || line.replace(/^\s+/, "").startsWith("#")) continue;
|
|
24059
|
+
if (!(line.startsWith(" ") || line.startsWith(" "))) {
|
|
24060
|
+
inHooks = /^hooks\s*:\s*$/.test(line);
|
|
24061
|
+
sectionIndent = null;
|
|
24062
|
+
continue;
|
|
24063
|
+
}
|
|
24064
|
+
if (inHooks) {
|
|
24065
|
+
const opened = sectionPattern.exec(line);
|
|
24066
|
+
if (opened) {
|
|
24067
|
+
sectionIndent = opened[1].length;
|
|
24068
|
+
continue;
|
|
24069
|
+
}
|
|
24070
|
+
if (sectionIndent !== null && indentOf(line) <= sectionIndent) {
|
|
24071
|
+
sectionIndent = null;
|
|
24072
|
+
}
|
|
24073
|
+
}
|
|
24074
|
+
if (sectionIndent !== null && /^\s+enabled\s*:\s*true\b/.test(line)) return true;
|
|
24075
|
+
}
|
|
24076
|
+
return false;
|
|
24077
|
+
}
|
|
24078
|
+
|
|
24079
|
+
// src/scripts/hooks/ui_route_nudge_hook.ts
|
|
24080
|
+
var EXIT_ALLOW15 = 0;
|
|
24081
|
+
var EXIT_WARN8 = 2;
|
|
24082
|
+
var MAX_NUDGES = 2;
|
|
24083
|
+
var DESIGN_SURFACES = [
|
|
24084
|
+
"fe-design",
|
|
24085
|
+
"existing-ui-audit",
|
|
24086
|
+
"design-review",
|
|
24087
|
+
"design-intelligence"
|
|
24088
|
+
];
|
|
24089
|
+
function isObject4(v) {
|
|
24090
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
24091
|
+
}
|
|
24092
|
+
function unwrap2(envelope) {
|
|
24093
|
+
const inner = envelope["payload"];
|
|
24094
|
+
return isObject4(inner) ? inner : envelope;
|
|
24095
|
+
}
|
|
24096
|
+
function extractEvent(outer) {
|
|
24097
|
+
const envelope = unwrap2(outer);
|
|
24098
|
+
const ti = envelope["tool_input"] ?? envelope["toolInput"] ?? envelope["input"];
|
|
24099
|
+
if (!isObject4(ti)) return null;
|
|
24100
|
+
const fileVal = ti["file_path"] ?? ti["path"] ?? ti["filePath"];
|
|
24101
|
+
const file = typeof fileVal === "string" ? fileVal : "";
|
|
24102
|
+
let isWrite = false;
|
|
24103
|
+
for (const key of ["content", "new_string", "new_str", "text", "newText"]) {
|
|
24104
|
+
if (typeof ti[key] === "string" && ti[key].length > 0) isWrite = true;
|
|
24105
|
+
}
|
|
24106
|
+
return { file, isWrite };
|
|
24107
|
+
}
|
|
24108
|
+
function isConsultation(event) {
|
|
24109
|
+
if (event.isWrite || !event.file) return false;
|
|
24110
|
+
const normalized = event.file.replace(/\\/g, "/").toLowerCase();
|
|
24111
|
+
return DESIGN_SURFACES.some((surface) => normalized.includes(`skills/${surface}/`));
|
|
24112
|
+
}
|
|
24113
|
+
function isUiWrite(event) {
|
|
24114
|
+
if (!event.isWrite || !event.file) return false;
|
|
24115
|
+
return isUiPath(event.file) || isUiTreePath(event.file);
|
|
24116
|
+
}
|
|
24117
|
+
function stateFile2(root) {
|
|
24118
|
+
return path56.join(root, "agents", "runtime", "state", "ui-route-nudge.json");
|
|
24119
|
+
}
|
|
24120
|
+
function readState2(root, session) {
|
|
24121
|
+
try {
|
|
24122
|
+
const all = JSON.parse(fs55.readFileSync(stateFile2(root), "utf-8"));
|
|
24123
|
+
const entry = all[session];
|
|
24124
|
+
if (entry && typeof entry.consulted === "boolean" && typeof entry.nudges === "number") {
|
|
24125
|
+
return entry;
|
|
24126
|
+
}
|
|
24127
|
+
} catch {
|
|
24128
|
+
}
|
|
24129
|
+
return { consulted: false, nudges: 0 };
|
|
24130
|
+
}
|
|
24131
|
+
var MAX_SESSIONS = 50;
|
|
24132
|
+
function pruneSessions(all, keep = MAX_SESSIONS) {
|
|
24133
|
+
const keys = Object.keys(all);
|
|
24134
|
+
if (keys.length <= keep) return all;
|
|
24135
|
+
const survivors = keys.slice(keys.length - keep);
|
|
24136
|
+
const pruned = {};
|
|
24137
|
+
for (const key of survivors) pruned[key] = all[key];
|
|
24138
|
+
return pruned;
|
|
24139
|
+
}
|
|
24140
|
+
function writeState2(root, session, state) {
|
|
24141
|
+
try {
|
|
24142
|
+
const file = stateFile2(root);
|
|
24143
|
+
let all = {};
|
|
24144
|
+
try {
|
|
24145
|
+
all = JSON.parse(fs55.readFileSync(file, "utf-8"));
|
|
24146
|
+
} catch {
|
|
24147
|
+
}
|
|
24148
|
+
if (typeof all !== "object" || all === null || Array.isArray(all)) all = {};
|
|
24149
|
+
all[session] = state;
|
|
24150
|
+
fs55.mkdirSync(path56.dirname(file), { recursive: true });
|
|
24151
|
+
fs55.writeFileSync(file, JSON.stringify(pruneSessions(all)));
|
|
24152
|
+
} catch {
|
|
24153
|
+
}
|
|
24154
|
+
}
|
|
24155
|
+
function decide4(event, state) {
|
|
24156
|
+
if (isConsultation(event)) {
|
|
24157
|
+
return { state: { ...state, consulted: true }, warn: false };
|
|
24158
|
+
}
|
|
24159
|
+
if (!isUiWrite(event)) return { state, warn: false };
|
|
24160
|
+
if (state.consulted) return { state, warn: false };
|
|
24161
|
+
if (state.nudges >= MAX_NUDGES) return { state, warn: false };
|
|
24162
|
+
return { state: { ...state, nudges: state.nudges + 1 }, warn: true };
|
|
24163
|
+
}
|
|
24164
|
+
function nudgeReason2(file) {
|
|
24165
|
+
return `Non-trivial UI write to ${file} with no design consultation this session. Run \`existing-ui-audit\` first, then the fe-design loop (brief \u2192 build \u2192 review). Skip only if this is ui-trivial: <=1 file, <=5 lines, no new component, no new state, no new dependency.`;
|
|
24166
|
+
}
|
|
24167
|
+
function main37() {
|
|
24168
|
+
let envelope;
|
|
24169
|
+
try {
|
|
24170
|
+
const raw = readHookStdin();
|
|
24171
|
+
if (!raw.trim()) return EXIT_ALLOW15;
|
|
24172
|
+
envelope = JSON.parse(raw);
|
|
24173
|
+
} catch {
|
|
24174
|
+
return EXIT_ALLOW15;
|
|
24175
|
+
}
|
|
24176
|
+
if (!isObject4(envelope)) return EXIT_ALLOW15;
|
|
24177
|
+
const rootVal = envelope["workspace_root"];
|
|
24178
|
+
const root = typeof rootVal === "string" && rootVal ? rootVal : process.cwd();
|
|
24179
|
+
if (!hookSectionEnabled(root, "ui_route_nudge")) return EXIT_ALLOW15;
|
|
24180
|
+
const sessionVal = envelope["session_id"];
|
|
24181
|
+
const session = typeof sessionVal === "string" && sessionVal ? sessionVal : "unknown";
|
|
24182
|
+
const event = extractEvent(envelope);
|
|
24183
|
+
if (!event) return EXIT_ALLOW15;
|
|
24184
|
+
const before = readState2(root, session);
|
|
24185
|
+
const { state, warn } = decide4(event, before);
|
|
24186
|
+
if (state.consulted !== before.consulted || state.nudges !== before.nudges) {
|
|
24187
|
+
writeState2(root, session, state);
|
|
24188
|
+
}
|
|
24189
|
+
if (!warn) return EXIT_ALLOW15;
|
|
24190
|
+
process.stdout.write(`${JSON.stringify({ reason: nudgeReason2(event.file) })}
|
|
24191
|
+
`);
|
|
24192
|
+
return EXIT_WARN8;
|
|
24193
|
+
}
|
|
24194
|
+
function isCliEntry12() {
|
|
24195
|
+
const entry = process.argv[1];
|
|
24196
|
+
if (!entry) return false;
|
|
24197
|
+
return pathToFileURL32(path56.resolve(entry)).href === import.meta.url;
|
|
24198
|
+
}
|
|
24199
|
+
if (isCliEntry12()) process.exit(main37());
|
|
24200
|
+
var _HOOK_FILE = fileURLToPath39(import.meta.url);
|
|
24201
|
+
|
|
24202
|
+
// src/scripts/hooks/orchestration_record_hook.ts
|
|
24203
|
+
import * as crypto4 from "node:crypto";
|
|
24204
|
+
import * as fs57 from "node:fs";
|
|
24205
|
+
import * as path58 from "node:path";
|
|
24206
|
+
import { fileURLToPath as fileURLToPath40, pathToFileURL as pathToFileURL34 } from "node:url";
|
|
23884
24207
|
|
|
23885
24208
|
// src/scripts/_lib/orchestration_record.ts
|
|
23886
24209
|
var DISPATCH_OUTCOMES = ["DONE", "DONE_WITH_CONCERNS", "NEEDS_CONTEXT", "BLOCKED", "killed"];
|
|
@@ -24076,9 +24399,9 @@ function buildOrchestrationLine(input) {
|
|
|
24076
24399
|
|
|
24077
24400
|
// src/scripts/orchestration_record.ts
|
|
24078
24401
|
import * as crypto3 from "node:crypto";
|
|
24079
|
-
import * as
|
|
24080
|
-
import * as
|
|
24081
|
-
import { pathToFileURL as
|
|
24402
|
+
import * as fs56 from "node:fs";
|
|
24403
|
+
import * as path57 from "node:path";
|
|
24404
|
+
import { pathToFileURL as pathToFileURL33 } from "node:url";
|
|
24082
24405
|
var DEFAULT_DIR = "agents/runtime/state/audit";
|
|
24083
24406
|
function parseFlags(argv) {
|
|
24084
24407
|
const flags = {};
|
|
@@ -24128,7 +24451,7 @@ function contentHashId(input) {
|
|
|
24128
24451
|
});
|
|
24129
24452
|
return crypto3.createHash("sha256").update(canonical).digest("hex").slice(0, 26).toUpperCase();
|
|
24130
24453
|
}
|
|
24131
|
-
function
|
|
24454
|
+
function main38(argv = process.argv.slice(2)) {
|
|
24132
24455
|
const flags = parseFlags(argv);
|
|
24133
24456
|
const dir = str2(flags, "dir") ?? DEFAULT_DIR;
|
|
24134
24457
|
const dryRun = flags["dry-run"] === true;
|
|
@@ -24189,27 +24512,27 @@ function main37(argv = process.argv.slice(2)) {
|
|
|
24189
24512
|
process.stdout.write(serialized + "\n");
|
|
24190
24513
|
return 0;
|
|
24191
24514
|
}
|
|
24192
|
-
|
|
24193
|
-
const file =
|
|
24194
|
-
|
|
24515
|
+
fs56.mkdirSync(dir, { recursive: true });
|
|
24516
|
+
const file = path57.join(dir, `${ts.slice(0, 7)}.jsonl`);
|
|
24517
|
+
fs56.appendFileSync(file, serialized + "\n", "utf8");
|
|
24195
24518
|
process.stdout.write(`orchestration telemetry recorded \u2192 ${file} (id ${line.id})
|
|
24196
24519
|
`);
|
|
24197
24520
|
return 0;
|
|
24198
24521
|
}
|
|
24199
24522
|
if (process.argv[1] !== void 0) {
|
|
24200
|
-
const invokedUrl =
|
|
24201
|
-
if (import.meta.url === invokedUrl) process.exit(
|
|
24523
|
+
const invokedUrl = pathToFileURL33(path57.resolve(process.argv[1])).href;
|
|
24524
|
+
if (import.meta.url === invokedUrl) process.exit(main38());
|
|
24202
24525
|
}
|
|
24203
24526
|
|
|
24204
24527
|
// src/scripts/hooks/orchestration_record_hook.ts
|
|
24205
|
-
var
|
|
24206
|
-
function
|
|
24528
|
+
var EXIT_ALLOW16 = 0;
|
|
24529
|
+
function isObject5(v) {
|
|
24207
24530
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
24208
24531
|
}
|
|
24209
24532
|
var DISPATCH_TOOL_NAMES = /* @__PURE__ */ new Set(["Agent", "Task"]);
|
|
24210
24533
|
function unwrapPayload(envelope) {
|
|
24211
24534
|
const inner = envelope["payload"];
|
|
24212
|
-
return
|
|
24535
|
+
return isObject5(inner) ? inner : envelope;
|
|
24213
24536
|
}
|
|
24214
24537
|
function extractToolName(payload) {
|
|
24215
24538
|
const v = payload["tool_name"] ?? payload["toolName"] ?? payload["tool"];
|
|
@@ -24217,12 +24540,12 @@ function extractToolName(payload) {
|
|
|
24217
24540
|
}
|
|
24218
24541
|
function extractToolInput(payload) {
|
|
24219
24542
|
const v = payload["tool_input"] ?? payload["toolInput"];
|
|
24220
|
-
return
|
|
24543
|
+
return isObject5(v) ? v : null;
|
|
24221
24544
|
}
|
|
24222
24545
|
function extractToolResult(payload) {
|
|
24223
24546
|
for (const key of ["tool_response", "toolResponse", "tool_result", "toolUseResult"]) {
|
|
24224
24547
|
const v = payload[key];
|
|
24225
|
-
if (
|
|
24548
|
+
if (isObject5(v)) return v;
|
|
24226
24549
|
}
|
|
24227
24550
|
return null;
|
|
24228
24551
|
}
|
|
@@ -24243,7 +24566,7 @@ function extractDispatchFacts(payload) {
|
|
|
24243
24566
|
const result = extractToolResult(payload);
|
|
24244
24567
|
const resolvedModel = result && typeof result["resolvedModel"] === "string" ? result["resolvedModel"] : null;
|
|
24245
24568
|
let totalTokens = result ? numOrNull(result["totalTokens"]) : null;
|
|
24246
|
-
if (totalTokens === null && result &&
|
|
24569
|
+
if (totalTokens === null && result && isObject5(result["usage"])) {
|
|
24247
24570
|
const usage = result["usage"];
|
|
24248
24571
|
const inTok = numOrNull(usage["input_tokens"]);
|
|
24249
24572
|
const outTok = numOrNull(usage["output_tokens"]);
|
|
@@ -24292,35 +24615,35 @@ function buildRecordInput(facts, ts, id) {
|
|
|
24292
24615
|
return input;
|
|
24293
24616
|
}
|
|
24294
24617
|
function auditFileFor(consumerRoot, ts) {
|
|
24295
|
-
return
|
|
24618
|
+
return path58.join(consumerRoot, DEFAULT_DIR, `${ts.slice(0, 7)}.jsonl`);
|
|
24296
24619
|
}
|
|
24297
24620
|
function appendLine(consumerRoot, ts, line) {
|
|
24298
24621
|
if (is_replay_mode()) return;
|
|
24299
24622
|
const file = auditFileFor(consumerRoot, ts);
|
|
24300
|
-
|
|
24301
|
-
|
|
24623
|
+
fs57.mkdirSync(path58.dirname(file), { recursive: true });
|
|
24624
|
+
fs57.appendFileSync(file, `${JSON.stringify(line)}
|
|
24302
24625
|
`, "utf8");
|
|
24303
24626
|
}
|
|
24304
24627
|
function processEnvelope(envelope, consumer_root) {
|
|
24305
24628
|
try {
|
|
24306
|
-
if (!
|
|
24629
|
+
if (!isObject5(envelope)) return EXIT_ALLOW16;
|
|
24307
24630
|
const payload = unwrapPayload(envelope);
|
|
24308
24631
|
const toolName = extractToolName(payload);
|
|
24309
|
-
if (toolName === null || !DISPATCH_TOOL_NAMES.has(toolName)) return
|
|
24632
|
+
if (toolName === null || !DISPATCH_TOOL_NAMES.has(toolName)) return EXIT_ALLOW16;
|
|
24310
24633
|
const facts = extractDispatchFacts(payload);
|
|
24311
24634
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
24312
24635
|
const id = crypto4.randomUUID();
|
|
24313
24636
|
const input = buildRecordInput(facts, ts, id);
|
|
24314
24637
|
const { line, errors } = buildOrchestrationLine(input);
|
|
24315
|
-
if (errors.length || line === null) return
|
|
24638
|
+
if (errors.length || line === null) return EXIT_ALLOW16;
|
|
24316
24639
|
appendLine(consumer_root, ts, line);
|
|
24317
24640
|
} catch {
|
|
24318
|
-
return
|
|
24641
|
+
return EXIT_ALLOW16;
|
|
24319
24642
|
}
|
|
24320
|
-
return
|
|
24643
|
+
return EXIT_ALLOW16;
|
|
24321
24644
|
}
|
|
24322
24645
|
function _resolveRoot(envelope) {
|
|
24323
|
-
if (
|
|
24646
|
+
if (isObject5(envelope)) {
|
|
24324
24647
|
const cwd = envelope["cwd"];
|
|
24325
24648
|
if (typeof cwd === "string" && cwd) return cwd;
|
|
24326
24649
|
const pr = envelope["workspace_root"] ?? envelope["project_root"];
|
|
@@ -24328,13 +24651,13 @@ function _resolveRoot(envelope) {
|
|
|
24328
24651
|
}
|
|
24329
24652
|
return process.cwd();
|
|
24330
24653
|
}
|
|
24331
|
-
function
|
|
24654
|
+
function main39() {
|
|
24332
24655
|
const raw = readHookStdin();
|
|
24333
24656
|
let envelope = {};
|
|
24334
24657
|
try {
|
|
24335
24658
|
envelope = raw.trim() ? JSON.parse(raw) : {};
|
|
24336
24659
|
} catch {
|
|
24337
|
-
return
|
|
24660
|
+
return EXIT_ALLOW16;
|
|
24338
24661
|
}
|
|
24339
24662
|
return processEnvelope(envelope, _resolveRoot(envelope));
|
|
24340
24663
|
}
|
|
@@ -24343,20 +24666,20 @@ function _isCliEntry29() {
|
|
|
24343
24666
|
return false;
|
|
24344
24667
|
}
|
|
24345
24668
|
if (process.argv[1] === void 0) return false;
|
|
24346
|
-
const argvUrl =
|
|
24669
|
+
const argvUrl = pathToFileURL34(path58.resolve(process.argv[1])).href;
|
|
24347
24670
|
if (import.meta.url === argvUrl) return true;
|
|
24348
24671
|
try {
|
|
24349
|
-
return
|
|
24672
|
+
return fs57.realpathSync(fileURLToPath40(import.meta.url)) === fs57.realpathSync(path58.resolve(process.argv[1]));
|
|
24350
24673
|
} catch {
|
|
24351
24674
|
return false;
|
|
24352
24675
|
}
|
|
24353
24676
|
}
|
|
24354
|
-
if (_isCliEntry29()) process.exit(
|
|
24677
|
+
if (_isCliEntry29()) process.exit(main39());
|
|
24355
24678
|
|
|
24356
24679
|
// src/scripts/hooks/delegation_nudge_hook.ts
|
|
24357
|
-
import
|
|
24358
|
-
import
|
|
24359
|
-
import { fileURLToPath as
|
|
24680
|
+
import fs58 from "node:fs";
|
|
24681
|
+
import path59 from "node:path";
|
|
24682
|
+
import { fileURLToPath as fileURLToPath41, pathToFileURL as pathToFileURL35 } from "node:url";
|
|
24360
24683
|
|
|
24361
24684
|
// src/scripts/_lib/host_capability.ts
|
|
24362
24685
|
import process10 from "node:process";
|
|
@@ -24691,8 +25014,8 @@ function resolveSubagentRouting(inp) {
|
|
|
24691
25014
|
}
|
|
24692
25015
|
|
|
24693
25016
|
// src/scripts/hooks/delegation_nudge_hook.ts
|
|
24694
|
-
var
|
|
24695
|
-
var
|
|
25017
|
+
var EXIT_ALLOW17 = 0;
|
|
25018
|
+
var EXIT_WARN9 = 2;
|
|
24696
25019
|
function _isObject13(v) {
|
|
24697
25020
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
24698
25021
|
}
|
|
@@ -24849,34 +25172,34 @@ function _workspaceRoot3(envelope) {
|
|
|
24849
25172
|
}
|
|
24850
25173
|
return process.cwd();
|
|
24851
25174
|
}
|
|
24852
|
-
function
|
|
25175
|
+
function main40() {
|
|
24853
25176
|
let envelope = {};
|
|
24854
25177
|
try {
|
|
24855
25178
|
const raw = readHookStdin();
|
|
24856
25179
|
envelope = raw.trim() ? JSON.parse(raw) : {};
|
|
24857
25180
|
} catch {
|
|
24858
|
-
return
|
|
25181
|
+
return EXIT_ALLOW17;
|
|
24859
25182
|
}
|
|
24860
25183
|
const env = _isObject13(envelope) ? envelope : {};
|
|
24861
25184
|
const event = env["event"];
|
|
24862
25185
|
const slot = typeof event === "string" && event !== "" ? event : "user_prompt_submit";
|
|
24863
25186
|
if (slot !== "user_prompt_submit") {
|
|
24864
|
-
return
|
|
25187
|
+
return EXIT_ALLOW17;
|
|
24865
25188
|
}
|
|
24866
25189
|
const payload = _isObject13(env["payload"]) ? env["payload"] : env;
|
|
24867
25190
|
const prompt = _extractPrompt2(payload);
|
|
24868
25191
|
if (!prompt) {
|
|
24869
|
-
return
|
|
25192
|
+
return EXIT_ALLOW17;
|
|
24870
25193
|
}
|
|
24871
25194
|
if (isSyntheticPrompt(prompt)) {
|
|
24872
|
-
return
|
|
25195
|
+
return EXIT_ALLOW17;
|
|
24873
25196
|
}
|
|
24874
25197
|
const root = _workspaceRoot3(env);
|
|
24875
25198
|
const platform = env["platform"];
|
|
24876
25199
|
const hostId = typeof platform === "string" && platform ? platform : null;
|
|
24877
25200
|
const result = classifyPrompt(prompt, root, hostId);
|
|
24878
25201
|
if (!result) {
|
|
24879
|
-
return
|
|
25202
|
+
return EXIT_ALLOW17;
|
|
24880
25203
|
}
|
|
24881
25204
|
process.stdout.write(
|
|
24882
25205
|
`${JSON.stringify({
|
|
@@ -24886,7 +25209,7 @@ function main39() {
|
|
|
24886
25209
|
})}
|
|
24887
25210
|
`
|
|
24888
25211
|
);
|
|
24889
|
-
return
|
|
25212
|
+
return EXIT_WARN9;
|
|
24890
25213
|
}
|
|
24891
25214
|
function _isCliEntry30() {
|
|
24892
25215
|
if (true) {
|
|
@@ -24895,29 +25218,29 @@ function _isCliEntry30() {
|
|
|
24895
25218
|
if (process.argv[1] === void 0) {
|
|
24896
25219
|
return false;
|
|
24897
25220
|
}
|
|
24898
|
-
const argvUrl =
|
|
25221
|
+
const argvUrl = pathToFileURL35(path59.resolve(process.argv[1])).href;
|
|
24899
25222
|
if (import.meta.url === argvUrl) {
|
|
24900
25223
|
return true;
|
|
24901
25224
|
}
|
|
24902
25225
|
try {
|
|
24903
|
-
const here =
|
|
24904
|
-
const argv =
|
|
25226
|
+
const here = fs58.realpathSync(fileURLToPath41(import.meta.url));
|
|
25227
|
+
const argv = fs58.realpathSync(path59.resolve(process.argv[1]));
|
|
24905
25228
|
return here === argv;
|
|
24906
25229
|
} catch {
|
|
24907
25230
|
return false;
|
|
24908
25231
|
}
|
|
24909
25232
|
}
|
|
24910
25233
|
if (_isCliEntry30()) {
|
|
24911
|
-
process.exit(
|
|
25234
|
+
process.exit(main40());
|
|
24912
25235
|
}
|
|
24913
25236
|
|
|
24914
25237
|
// src/scripts/hooks/end_review_nudge_hook.ts
|
|
24915
25238
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
24916
25239
|
import * as crypto5 from "node:crypto";
|
|
24917
|
-
import * as
|
|
25240
|
+
import * as fs59 from "node:fs";
|
|
24918
25241
|
import * as os6 from "node:os";
|
|
24919
|
-
import * as
|
|
24920
|
-
import { fileURLToPath as
|
|
25242
|
+
import * as path60 from "node:path";
|
|
25243
|
+
import { fileURLToPath as fileURLToPath42, pathToFileURL as pathToFileURL36 } from "node:url";
|
|
24921
25244
|
|
|
24922
25245
|
// src/scripts/_lib/review_skipped_record.ts
|
|
24923
25246
|
function isNonNegInt(n) {
|
|
@@ -24964,19 +25287,19 @@ function isSafeTranscriptPath(rawPath, opts = {}) {
|
|
|
24964
25287
|
const homeDir = opts.homeDir ?? os6.homedir();
|
|
24965
25288
|
const maxBytes = opts.maxBytes ?? TRANSCRIPT_SCAN_MAX_BYTES;
|
|
24966
25289
|
try {
|
|
24967
|
-
const realHome =
|
|
24968
|
-
const realPath =
|
|
24969
|
-
const relative9 =
|
|
24970
|
-
if (relative9 === "" || relative9.startsWith("..") ||
|
|
25290
|
+
const realHome = fs59.realpathSync(homeDir);
|
|
25291
|
+
const realPath = fs59.realpathSync(rawPath);
|
|
25292
|
+
const relative9 = path60.relative(realHome, realPath);
|
|
25293
|
+
if (relative9 === "" || relative9.startsWith("..") || path60.isAbsolute(relative9)) {
|
|
24971
25294
|
return false;
|
|
24972
25295
|
}
|
|
24973
|
-
const { size } =
|
|
25296
|
+
const { size } = fs59.statSync(realPath);
|
|
24974
25297
|
return size <= maxBytes;
|
|
24975
25298
|
} catch {
|
|
24976
25299
|
return false;
|
|
24977
25300
|
}
|
|
24978
25301
|
}
|
|
24979
|
-
var
|
|
25302
|
+
var EXIT_WARN10 = 2;
|
|
24980
25303
|
function parseNumstat(raw) {
|
|
24981
25304
|
const rows = [];
|
|
24982
25305
|
for (const line of raw.split("\n")) {
|
|
@@ -25049,7 +25372,7 @@ function totalNonDocMutatedLinesWithMeasure(cwd) {
|
|
|
25049
25372
|
);
|
|
25050
25373
|
return { lines: trackedLines + untrackedLines, measure: "exact" };
|
|
25051
25374
|
}
|
|
25052
|
-
function
|
|
25375
|
+
function isObject6(v) {
|
|
25053
25376
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
25054
25377
|
}
|
|
25055
25378
|
function str3(v) {
|
|
@@ -25069,16 +25392,16 @@ function scanTranscriptForReviewer(transcriptText) {
|
|
|
25069
25392
|
} catch {
|
|
25070
25393
|
continue;
|
|
25071
25394
|
}
|
|
25072
|
-
if (!
|
|
25395
|
+
if (!isObject6(obj) || obj["type"] !== "assistant") continue;
|
|
25073
25396
|
const msg = obj["message"];
|
|
25074
|
-
if (!
|
|
25397
|
+
if (!isObject6(msg)) continue;
|
|
25075
25398
|
const content = msg["content"];
|
|
25076
25399
|
if (!Array.isArray(content)) continue;
|
|
25077
25400
|
for (const blk of content) {
|
|
25078
|
-
if (!
|
|
25401
|
+
if (!isObject6(blk) || blk["type"] !== "tool_use") continue;
|
|
25079
25402
|
const name = str3(blk["name"]);
|
|
25080
25403
|
const input = blk["input"];
|
|
25081
|
-
const inputObj =
|
|
25404
|
+
const inputObj = isObject6(input) ? input : {};
|
|
25082
25405
|
if (DISPATCH_TOOL_RE.test(name)) {
|
|
25083
25406
|
const label = [
|
|
25084
25407
|
str3(inputObj["description"]),
|
|
@@ -25113,19 +25436,19 @@ function appendReviewSkippedTelemetry(workspaceRoot2, diffLines, mutationMeasure
|
|
|
25113
25436
|
});
|
|
25114
25437
|
if (errors.length || line === null) return;
|
|
25115
25438
|
try {
|
|
25116
|
-
const dir =
|
|
25117
|
-
|
|
25118
|
-
const file =
|
|
25119
|
-
|
|
25439
|
+
const dir = path60.join(workspaceRoot2, "agents", "runtime", "state", "audit");
|
|
25440
|
+
fs59.mkdirSync(dir, { recursive: true });
|
|
25441
|
+
const file = path60.join(dir, `${ts.slice(0, 7)}.jsonl`);
|
|
25442
|
+
fs59.appendFileSync(file, `${JSON.stringify(line)}
|
|
25120
25443
|
`, "utf8");
|
|
25121
25444
|
} catch {
|
|
25122
25445
|
}
|
|
25123
25446
|
}
|
|
25124
25447
|
function sessionStateDir(workspaceRoot2) {
|
|
25125
|
-
return
|
|
25448
|
+
return path60.join(workspaceRoot2, "agents", "runtime", "state", "end-review-nudge");
|
|
25126
25449
|
}
|
|
25127
25450
|
function sessionStateFile(workspaceRoot2, sessionKey) {
|
|
25128
|
-
return
|
|
25451
|
+
return path60.join(sessionStateDir(workspaceRoot2), `${sessionKey}.json`);
|
|
25129
25452
|
}
|
|
25130
25453
|
function deriveSessionKey(envelope, payload) {
|
|
25131
25454
|
const raw = str3(envelope["session_id"]) || str3(payload["transcript_path"] ?? payload["transcriptPath"]);
|
|
@@ -25134,7 +25457,7 @@ function deriveSessionKey(envelope, payload) {
|
|
|
25134
25457
|
}
|
|
25135
25458
|
function hasFiredThisSession(workspaceRoot2, sessionKey) {
|
|
25136
25459
|
try {
|
|
25137
|
-
return
|
|
25460
|
+
return fs59.existsSync(sessionStateFile(workspaceRoot2, sessionKey));
|
|
25138
25461
|
} catch {
|
|
25139
25462
|
return false;
|
|
25140
25463
|
}
|
|
@@ -25148,7 +25471,7 @@ function markFiredThisSession(workspaceRoot2, sessionKey, ts) {
|
|
|
25148
25471
|
function _read_stdin3() {
|
|
25149
25472
|
return readHookStdin();
|
|
25150
25473
|
}
|
|
25151
|
-
function
|
|
25474
|
+
function main41() {
|
|
25152
25475
|
const [envelope, payload] = unwrap(_read_stdin3(), "claude");
|
|
25153
25476
|
const event = String(envelope["event"] ?? "");
|
|
25154
25477
|
if (event !== "" && event !== "stop") {
|
|
@@ -25177,7 +25500,7 @@ function main40() {
|
|
|
25177
25500
|
let reviewerRan = false;
|
|
25178
25501
|
if (transcriptPath && isSafeTranscriptPath(transcriptPath)) {
|
|
25179
25502
|
try {
|
|
25180
|
-
reviewerRan = scanTranscriptForReviewer(
|
|
25503
|
+
reviewerRan = scanTranscriptForReviewer(fs59.readFileSync(transcriptPath, "utf-8"));
|
|
25181
25504
|
} catch {
|
|
25182
25505
|
reviewerRan = false;
|
|
25183
25506
|
}
|
|
@@ -25198,7 +25521,7 @@ function main40() {
|
|
|
25198
25521
|
})}
|
|
25199
25522
|
`
|
|
25200
25523
|
);
|
|
25201
|
-
return
|
|
25524
|
+
return EXIT_WARN10;
|
|
25202
25525
|
}
|
|
25203
25526
|
function _isCliEntry31() {
|
|
25204
25527
|
if (true) {
|
|
@@ -25207,29 +25530,29 @@ function _isCliEntry31() {
|
|
|
25207
25530
|
if (process.argv[1] === void 0) {
|
|
25208
25531
|
return false;
|
|
25209
25532
|
}
|
|
25210
|
-
const argvUrl =
|
|
25533
|
+
const argvUrl = pathToFileURL36(path60.resolve(process.argv[1])).href;
|
|
25211
25534
|
if (import.meta.url === argvUrl) {
|
|
25212
25535
|
return true;
|
|
25213
25536
|
}
|
|
25214
25537
|
try {
|
|
25215
|
-
const here =
|
|
25216
|
-
const argv =
|
|
25538
|
+
const here = fs59.realpathSync(fileURLToPath42(import.meta.url));
|
|
25539
|
+
const argv = fs59.realpathSync(path60.resolve(process.argv[1]));
|
|
25217
25540
|
return here === argv;
|
|
25218
25541
|
} catch {
|
|
25219
25542
|
return false;
|
|
25220
25543
|
}
|
|
25221
25544
|
}
|
|
25222
25545
|
if (_isCliEntry31()) {
|
|
25223
|
-
process.exit(
|
|
25546
|
+
process.exit(main41());
|
|
25224
25547
|
}
|
|
25225
25548
|
|
|
25226
25549
|
// src/scripts/hooks/turn_end_gate_hook.ts
|
|
25227
25550
|
import * as crypto6 from "node:crypto";
|
|
25228
|
-
import * as
|
|
25229
|
-
import * as
|
|
25230
|
-
import { fileURLToPath as
|
|
25551
|
+
import * as fs60 from "node:fs";
|
|
25552
|
+
import * as path61 from "node:path";
|
|
25553
|
+
import { fileURLToPath as fileURLToPath43, pathToFileURL as pathToFileURL37 } from "node:url";
|
|
25231
25554
|
var EXIT_BLOCK4 = 1;
|
|
25232
|
-
var
|
|
25555
|
+
var EXIT_ALLOW18 = 0;
|
|
25233
25556
|
var TRANSCRIPT_READ_MAX_BYTES = 8 * 1024 * 1024;
|
|
25234
25557
|
function stripFencedBlocks(text) {
|
|
25235
25558
|
const out = [];
|
|
@@ -25333,7 +25656,7 @@ function detectPromissory(reply) {
|
|
|
25333
25656
|
}
|
|
25334
25657
|
function readLanguagePin(workspaceRoot2) {
|
|
25335
25658
|
try {
|
|
25336
|
-
const raw =
|
|
25659
|
+
const raw = fs60.readFileSync(path61.join(workspaceRoot2, STATE_FILE5), "utf-8");
|
|
25337
25660
|
const decoded = JSON.parse(raw);
|
|
25338
25661
|
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
25339
25662
|
const lang = decoded["language"];
|
|
@@ -25355,18 +25678,44 @@ function detectLanguage(reply, pinned) {
|
|
|
25355
25678
|
reason: `the pinned reply language is "${pinned}" but the reply classifies as "${verdict.language}" (${verdict.de_markers} de / ${verdict.en_markers} en markers; code, quotes, tables, URLs and paths excluded, then scored lead-first by the same classifier that sets the pin)`
|
|
25356
25679
|
};
|
|
25357
25680
|
}
|
|
25681
|
+
var _EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
25682
|
+
var _VERIFY_RE = /\b(test|tests|vitest|jest|pytest|phpunit|pest|tsc|eslint|ruff|mypy|pyright|clippy|typecheck|lint|build|ci|preflight|smoke[-_:a-z]*|check[-_:a-z]*|validate[-_:a-z]*)\b|\b(task|npm|pnpm|yarn|composer|cargo|go|make|php artisan|bun)\s+(run\s+)?\S*(test|check|lint|build|ci|typecheck)/i;
|
|
25683
|
+
function isVerificationCommand(command) {
|
|
25684
|
+
return _VERIFY_RE.test(command);
|
|
25685
|
+
}
|
|
25686
|
+
function detectUnverifiedEdit(toolCalls) {
|
|
25687
|
+
let lastEdit = -1;
|
|
25688
|
+
for (let i = 0; i < toolCalls.length; i += 1) {
|
|
25689
|
+
if (_EDIT_TOOLS.has(toolCalls[i].name)) lastEdit = i;
|
|
25690
|
+
}
|
|
25691
|
+
if (lastEdit === -1) return null;
|
|
25692
|
+
for (let i = lastEdit + 1; i < toolCalls.length; i += 1) {
|
|
25693
|
+
const c = toolCalls[i];
|
|
25694
|
+
if (c.name === "Bash" && c.command !== void 0 && isVerificationCommand(c.command)) {
|
|
25695
|
+
return null;
|
|
25696
|
+
}
|
|
25697
|
+
}
|
|
25698
|
+
const edited = toolCalls[lastEdit].path;
|
|
25699
|
+
return {
|
|
25700
|
+
detector: "verification",
|
|
25701
|
+
// The path, never the diff: the evidence span is quoted into a refusal,
|
|
25702
|
+
// and `ToolCall` is shaped so a file body cannot reach it.
|
|
25703
|
+
evidence: edited ?? toolCalls[lastEdit].name,
|
|
25704
|
+
reason: "this turn changed a file and then ran no verification command \u2014 no test, type-check, lint or build call follows the last edit (verify-before-complete: a claim without a fresh run is unverified)"
|
|
25705
|
+
};
|
|
25706
|
+
}
|
|
25358
25707
|
function stateDir(workspaceRoot2) {
|
|
25359
|
-
return
|
|
25708
|
+
return path61.join(workspaceRoot2, "agents", "runtime", "state", "turn-end-gate");
|
|
25360
25709
|
}
|
|
25361
25710
|
function sessionStateFile2(workspaceRoot2, sessionKey) {
|
|
25362
|
-
return
|
|
25711
|
+
return path61.join(stateDir(workspaceRoot2), `${sessionKey}.json`);
|
|
25363
25712
|
}
|
|
25364
25713
|
function deriveSessionKey2(sessionId2) {
|
|
25365
25714
|
return crypto6.createHash("sha256").update(sessionId2).digest("hex").slice(0, 32);
|
|
25366
25715
|
}
|
|
25367
25716
|
function alreadyRefusedTurn(workspaceRoot2, sessionKey, turnOrdinal) {
|
|
25368
25717
|
try {
|
|
25369
|
-
const raw =
|
|
25718
|
+
const raw = fs60.readFileSync(sessionStateFile2(workspaceRoot2, sessionKey), "utf-8");
|
|
25370
25719
|
const decoded = JSON.parse(raw);
|
|
25371
25720
|
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
25372
25721
|
return decoded["refused_turn"] === turnOrdinal;
|
|
@@ -25387,19 +25736,20 @@ function markRefusedTurn(workspaceRoot2, sessionKey, turnOrdinal, detector) {
|
|
|
25387
25736
|
}
|
|
25388
25737
|
}
|
|
25389
25738
|
function readTranscriptTail(transcriptPath, opts = {}) {
|
|
25390
|
-
const empty = { lastAssistant: "", turnOrdinal: 0 };
|
|
25739
|
+
const empty = { lastAssistant: "", turnOrdinal: 0, toolCalls: [] };
|
|
25391
25740
|
if (!transcriptPath || !isSafeTranscriptPath(transcriptPath, opts)) return empty;
|
|
25392
25741
|
let lines;
|
|
25393
25742
|
try {
|
|
25394
|
-
if (opts.maxBytes !== void 0 &&
|
|
25743
|
+
if (opts.maxBytes !== void 0 && fs60.statSync(transcriptPath).size > opts.maxBytes) {
|
|
25395
25744
|
return empty;
|
|
25396
25745
|
}
|
|
25397
|
-
lines =
|
|
25746
|
+
lines = fs60.readFileSync(transcriptPath, "utf-8").split("\n");
|
|
25398
25747
|
} catch {
|
|
25399
25748
|
return empty;
|
|
25400
25749
|
}
|
|
25401
25750
|
let lastAssistant = "";
|
|
25402
25751
|
let turnOrdinal = 0;
|
|
25752
|
+
let toolCalls = [];
|
|
25403
25753
|
for (const rawLine of lines) {
|
|
25404
25754
|
const line = rawLine.trim();
|
|
25405
25755
|
if (!line) continue;
|
|
@@ -25416,15 +25766,42 @@ function readTranscriptTail(transcriptPath, opts = {}) {
|
|
|
25416
25766
|
if (role !== "assistant" && role !== "user") continue;
|
|
25417
25767
|
const msg = entry["message"];
|
|
25418
25768
|
if (typeof msg !== "object" || msg === null || Array.isArray(msg)) continue;
|
|
25419
|
-
const
|
|
25769
|
+
const content = msg["content"];
|
|
25770
|
+
if (role === "assistant") {
|
|
25771
|
+
toolCalls.push(..._toolCalls(content));
|
|
25772
|
+
}
|
|
25773
|
+
const text = _messageText(content);
|
|
25420
25774
|
if (text === null) continue;
|
|
25421
25775
|
if (role === "assistant") {
|
|
25422
25776
|
lastAssistant = text;
|
|
25423
25777
|
} else if (!isSyntheticPrompt(text)) {
|
|
25424
25778
|
turnOrdinal += 1;
|
|
25779
|
+
toolCalls = [];
|
|
25425
25780
|
}
|
|
25426
25781
|
}
|
|
25427
|
-
return { lastAssistant: lastAssistant.trim(), turnOrdinal };
|
|
25782
|
+
return { lastAssistant: lastAssistant.trim(), turnOrdinal, toolCalls };
|
|
25783
|
+
}
|
|
25784
|
+
function _toolCalls(content) {
|
|
25785
|
+
if (!Array.isArray(content)) return [];
|
|
25786
|
+
const out = [];
|
|
25787
|
+
for (const blk of content) {
|
|
25788
|
+
if (typeof blk !== "object" || blk === null || Array.isArray(blk)) continue;
|
|
25789
|
+
const b = blk;
|
|
25790
|
+
if (b["type"] !== "tool_use") continue;
|
|
25791
|
+
const name = b["name"];
|
|
25792
|
+
if (typeof name !== "string") continue;
|
|
25793
|
+
const input = b["input"];
|
|
25794
|
+
const call = { name };
|
|
25795
|
+
if (typeof input === "object" && input !== null && !Array.isArray(input)) {
|
|
25796
|
+
const inp = input;
|
|
25797
|
+
const cmd = inp["command"];
|
|
25798
|
+
if (typeof cmd === "string") call.command = cmd;
|
|
25799
|
+
const p = inp["file_path"] ?? inp["path"] ?? inp["notebook_path"];
|
|
25800
|
+
if (typeof p === "string") call.path = p;
|
|
25801
|
+
}
|
|
25802
|
+
out.push(call);
|
|
25803
|
+
}
|
|
25804
|
+
return out;
|
|
25428
25805
|
}
|
|
25429
25806
|
function _messageText(content) {
|
|
25430
25807
|
if (typeof content === "string") return content;
|
|
@@ -25448,7 +25825,12 @@ function _isOn(v) {
|
|
|
25448
25825
|
return null;
|
|
25449
25826
|
}
|
|
25450
25827
|
function readGateSettings(workspaceRoot2) {
|
|
25451
|
-
const off = {
|
|
25828
|
+
const off = {
|
|
25829
|
+
enabled: false,
|
|
25830
|
+
promissory: true,
|
|
25831
|
+
language: true,
|
|
25832
|
+
verification: true
|
|
25833
|
+
};
|
|
25452
25834
|
let settings;
|
|
25453
25835
|
try {
|
|
25454
25836
|
settings = load_agent_settings({ cwd: workspaceRoot2 });
|
|
@@ -25467,35 +25849,36 @@ function readGateSettings(workspaceRoot2) {
|
|
|
25467
25849
|
return {
|
|
25468
25850
|
enabled: flag("enabled", false),
|
|
25469
25851
|
promissory: flag("promissory", true),
|
|
25470
|
-
language: flag("language", true)
|
|
25852
|
+
language: flag("language", true),
|
|
25853
|
+
verification: flag("verification", true)
|
|
25471
25854
|
};
|
|
25472
25855
|
}
|
|
25473
25856
|
function str4(v) {
|
|
25474
25857
|
return typeof v === "string" ? v : "";
|
|
25475
25858
|
}
|
|
25476
|
-
function
|
|
25859
|
+
function main42() {
|
|
25477
25860
|
let envelope;
|
|
25478
25861
|
let payload;
|
|
25479
25862
|
try {
|
|
25480
25863
|
[envelope, payload] = unwrap(readHookStdin(), "claude");
|
|
25481
25864
|
} catch {
|
|
25482
|
-
return
|
|
25865
|
+
return EXIT_ALLOW18;
|
|
25483
25866
|
}
|
|
25484
|
-
if (payload["stop_hook_active"] === true) return
|
|
25867
|
+
if (payload["stop_hook_active"] === true) return EXIT_ALLOW18;
|
|
25485
25868
|
const workspaceRoot2 = str4(envelope["workspace_root"]) || process.cwd();
|
|
25486
25869
|
const settings = readGateSettings(workspaceRoot2);
|
|
25487
|
-
if (!settings.enabled) return
|
|
25870
|
+
if (!settings.enabled) return EXIT_ALLOW18;
|
|
25488
25871
|
const transcriptPath = str4(
|
|
25489
25872
|
payload["transcript_path"] ?? payload["transcriptPath"]
|
|
25490
25873
|
);
|
|
25491
|
-
const { lastAssistant, turnOrdinal } = readTranscriptTail(transcriptPath, {
|
|
25874
|
+
const { lastAssistant, turnOrdinal, toolCalls } = readTranscriptTail(transcriptPath, {
|
|
25492
25875
|
maxBytes: TRANSCRIPT_READ_MAX_BYTES
|
|
25493
25876
|
});
|
|
25494
|
-
if (!lastAssistant) return
|
|
25877
|
+
if (!lastAssistant) return EXIT_ALLOW18;
|
|
25495
25878
|
const sessionKey = deriveSessionKey2(
|
|
25496
25879
|
str4(envelope["session_id"]) || "unknown-session"
|
|
25497
25880
|
);
|
|
25498
|
-
if (alreadyRefusedTurn(workspaceRoot2, sessionKey, turnOrdinal)) return
|
|
25881
|
+
if (alreadyRefusedTurn(workspaceRoot2, sessionKey, turnOrdinal)) return EXIT_ALLOW18;
|
|
25499
25882
|
const findings = [];
|
|
25500
25883
|
if (settings.promissory) {
|
|
25501
25884
|
const f = detectPromissory(lastAssistant);
|
|
@@ -25505,7 +25888,11 @@ function main41() {
|
|
|
25505
25888
|
const f = detectLanguage(lastAssistant, readLanguagePin(workspaceRoot2));
|
|
25506
25889
|
if (f) findings.push(f);
|
|
25507
25890
|
}
|
|
25508
|
-
if (
|
|
25891
|
+
if (settings.verification) {
|
|
25892
|
+
const f = detectUnverifiedEdit(toolCalls);
|
|
25893
|
+
if (f) findings.push(f);
|
|
25894
|
+
}
|
|
25895
|
+
if (findings.length === 0) return EXIT_ALLOW18;
|
|
25509
25896
|
markRefusedTurn(workspaceRoot2, sessionKey, turnOrdinal, findings[0].detector);
|
|
25510
25897
|
const lines = findings.map(
|
|
25511
25898
|
(f) => ` \xB7 ${f.detector}: ${f.reason}
|
|
@@ -25514,7 +25901,7 @@ function main41() {
|
|
|
25514
25901
|
process.stderr.write(
|
|
25515
25902
|
`turn-end-gate: REFUSED \u2014 this turn is not finished.
|
|
25516
25903
|
${lines.join("\n")}
|
|
25517
|
-
Do the promised work now,
|
|
25904
|
+
Do the promised work now, correct the language, or run the verification the edit needs, then end the turn.
|
|
25518
25905
|
This turn will not be refused a second time.
|
|
25519
25906
|
Disable: hooks.turn_end_gate.enabled: false in .agent-settings.yml
|
|
25520
25907
|
`
|
|
@@ -25528,30 +25915,30 @@ function _isCliEntry32() {
|
|
|
25528
25915
|
if (process.argv[1] === void 0) {
|
|
25529
25916
|
return false;
|
|
25530
25917
|
}
|
|
25531
|
-
const argvUrl =
|
|
25918
|
+
const argvUrl = pathToFileURL37(path61.resolve(process.argv[1])).href;
|
|
25532
25919
|
if (import.meta.url === argvUrl) {
|
|
25533
25920
|
return true;
|
|
25534
25921
|
}
|
|
25535
25922
|
try {
|
|
25536
|
-
const here =
|
|
25537
|
-
const argv =
|
|
25923
|
+
const here = fs60.realpathSync(fileURLToPath43(import.meta.url));
|
|
25924
|
+
const argv = fs60.realpathSync(path61.resolve(process.argv[1]));
|
|
25538
25925
|
return here === argv;
|
|
25539
25926
|
} catch {
|
|
25540
25927
|
return false;
|
|
25541
25928
|
}
|
|
25542
25929
|
}
|
|
25543
25930
|
if (_isCliEntry32()) {
|
|
25544
|
-
process.exit(
|
|
25931
|
+
process.exit(main42());
|
|
25545
25932
|
}
|
|
25546
25933
|
|
|
25547
25934
|
// src/scripts/hooks/edit_shape_hook.ts
|
|
25548
25935
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
25549
25936
|
import * as crypto7 from "node:crypto";
|
|
25550
|
-
import * as
|
|
25551
|
-
import * as
|
|
25552
|
-
import { fileURLToPath as
|
|
25553
|
-
var
|
|
25554
|
-
var
|
|
25937
|
+
import * as fs61 from "node:fs";
|
|
25938
|
+
import * as path62 from "node:path";
|
|
25939
|
+
import { fileURLToPath as fileURLToPath44, pathToFileURL as pathToFileURL38 } from "node:url";
|
|
25940
|
+
var EXIT_ALLOW19 = 0;
|
|
25941
|
+
var EXIT_WARN11 = 2;
|
|
25555
25942
|
var MIN_FILE_LINES = 50;
|
|
25556
25943
|
var MAX_DIFF_RATIO = 0.2;
|
|
25557
25944
|
var EXEMPT_PATH_PATTERNS = [
|
|
@@ -25566,7 +25953,7 @@ var EXEMPT_PATH_PATTERNS = [
|
|
|
25566
25953
|
/(^|\/)agents\/runtime\//i
|
|
25567
25954
|
// agents/runtime/**
|
|
25568
25955
|
];
|
|
25569
|
-
function
|
|
25956
|
+
function isObject7(v) {
|
|
25570
25957
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
25571
25958
|
}
|
|
25572
25959
|
function str5(v) {
|
|
@@ -25602,7 +25989,7 @@ function effectiveDiffLines(cwd, relPath) {
|
|
|
25602
25989
|
}
|
|
25603
25990
|
function fileLineCount(absPath) {
|
|
25604
25991
|
try {
|
|
25605
|
-
const text =
|
|
25992
|
+
const text = fs61.readFileSync(absPath, "utf8");
|
|
25606
25993
|
if (text.length === 0) return 0;
|
|
25607
25994
|
return text.split("\n").length - (text.endsWith("\n") ? 1 : 0);
|
|
25608
25995
|
} catch {
|
|
@@ -25619,11 +26006,11 @@ function deriveSessionKey3(envelope, payload) {
|
|
|
25619
26006
|
return crypto7.createHash("sha256").update(material).digest("hex");
|
|
25620
26007
|
}
|
|
25621
26008
|
function sessionStateFile3(workspaceRoot2, sessionKey) {
|
|
25622
|
-
return
|
|
26009
|
+
return path62.join(workspaceRoot2, "agents", "runtime", "state", "edit-shape", `${sessionKey}.json`);
|
|
25623
26010
|
}
|
|
25624
26011
|
function hasFiredThisSession2(workspaceRoot2, sessionKey) {
|
|
25625
26012
|
try {
|
|
25626
|
-
return
|
|
26013
|
+
return fs61.existsSync(sessionStateFile3(workspaceRoot2, sessionKey));
|
|
25627
26014
|
} catch {
|
|
25628
26015
|
return false;
|
|
25629
26016
|
}
|
|
@@ -25641,29 +26028,29 @@ function extractToolName2(payload) {
|
|
|
25641
26028
|
}
|
|
25642
26029
|
function extractFilePath(payload) {
|
|
25643
26030
|
const ti = payload["tool_input"] ?? payload["toolInput"] ?? payload["input"];
|
|
25644
|
-
if (!
|
|
26031
|
+
if (!isObject7(ti)) return "";
|
|
25645
26032
|
return str5(ti["file_path"] ?? ti["path"] ?? ti["filePath"]);
|
|
25646
26033
|
}
|
|
25647
|
-
function
|
|
26034
|
+
function main43() {
|
|
25648
26035
|
try {
|
|
25649
26036
|
const [envelope, payload] = unwrap(readHookStdin(), "claude");
|
|
25650
26037
|
const event = str5(envelope["event"]);
|
|
25651
|
-
if (event !== "" && event !== "post_tool_use") return
|
|
26038
|
+
if (event !== "" && event !== "post_tool_use") return EXIT_ALLOW19;
|
|
25652
26039
|
const toolName = extractToolName2(payload);
|
|
25653
|
-
if (toolName !== "Write") return
|
|
26040
|
+
if (toolName !== "Write") return EXIT_ALLOW19;
|
|
25654
26041
|
const filePath = extractFilePath(payload);
|
|
25655
|
-
if (!filePath) return
|
|
26042
|
+
if (!filePath) return EXIT_ALLOW19;
|
|
25656
26043
|
const workspaceRoot2 = str5(envelope["workspace_root"]).trim() || process.cwd();
|
|
25657
|
-
const absPath =
|
|
25658
|
-
const relPath =
|
|
25659
|
-
if (isExemptPath(relPath) || isExemptPath(absPath)) return
|
|
26044
|
+
const absPath = path62.isAbsolute(filePath) ? filePath : path62.resolve(workspaceRoot2, filePath);
|
|
26045
|
+
const relPath = path62.relative(workspaceRoot2, absPath);
|
|
26046
|
+
if (isExemptPath(relPath) || isExemptPath(absPath)) return EXIT_ALLOW19;
|
|
25660
26047
|
const fileLines = fileLineCount(absPath);
|
|
25661
|
-
if (fileLines < MIN_FILE_LINES) return
|
|
26048
|
+
if (fileLines < MIN_FILE_LINES) return EXIT_ALLOW19;
|
|
25662
26049
|
const diffLines = effectiveDiffLines(workspaceRoot2, relPath.startsWith("..") ? absPath : relPath);
|
|
25663
|
-
if (diffLines === 0) return
|
|
25664
|
-
if (diffLines / fileLines > MAX_DIFF_RATIO) return
|
|
26050
|
+
if (diffLines === 0) return EXIT_ALLOW19;
|
|
26051
|
+
if (diffLines / fileLines > MAX_DIFF_RATIO) return EXIT_ALLOW19;
|
|
25665
26052
|
const sessionKey = deriveSessionKey3(envelope, payload);
|
|
25666
|
-
if (hasFiredThisSession2(workspaceRoot2, sessionKey)) return
|
|
26053
|
+
if (hasFiredThisSession2(workspaceRoot2, sessionKey)) return EXIT_ALLOW19;
|
|
25667
26054
|
markFiredThisSession2(workspaceRoot2, sessionKey);
|
|
25668
26055
|
process.stdout.write(
|
|
25669
26056
|
`${JSON.stringify({
|
|
@@ -25673,9 +26060,9 @@ function main42() {
|
|
|
25673
26060
|
})}
|
|
25674
26061
|
`
|
|
25675
26062
|
);
|
|
25676
|
-
return
|
|
26063
|
+
return EXIT_WARN11;
|
|
25677
26064
|
} catch {
|
|
25678
|
-
return
|
|
26065
|
+
return EXIT_ALLOW19;
|
|
25679
26066
|
}
|
|
25680
26067
|
}
|
|
25681
26068
|
function _isCliEntry33() {
|
|
@@ -25685,29 +26072,29 @@ function _isCliEntry33() {
|
|
|
25685
26072
|
if (process.argv[1] === void 0) {
|
|
25686
26073
|
return false;
|
|
25687
26074
|
}
|
|
25688
|
-
const argvUrl =
|
|
26075
|
+
const argvUrl = pathToFileURL38(path62.resolve(process.argv[1])).href;
|
|
25689
26076
|
if (import.meta.url === argvUrl) {
|
|
25690
26077
|
return true;
|
|
25691
26078
|
}
|
|
25692
26079
|
try {
|
|
25693
|
-
const here =
|
|
25694
|
-
const argv =
|
|
26080
|
+
const here = fs61.realpathSync(fileURLToPath44(import.meta.url));
|
|
26081
|
+
const argv = fs61.realpathSync(path62.resolve(process.argv[1]));
|
|
25695
26082
|
return here === argv;
|
|
25696
26083
|
} catch {
|
|
25697
26084
|
return false;
|
|
25698
26085
|
}
|
|
25699
26086
|
}
|
|
25700
26087
|
if (_isCliEntry33()) {
|
|
25701
|
-
process.exit(
|
|
26088
|
+
process.exit(main43());
|
|
25702
26089
|
}
|
|
25703
26090
|
|
|
25704
26091
|
// src/scripts/hooks/reread_guard_hook.ts
|
|
25705
26092
|
import * as crypto8 from "node:crypto";
|
|
25706
|
-
import * as
|
|
25707
|
-
import * as
|
|
25708
|
-
import { fileURLToPath as
|
|
25709
|
-
var
|
|
25710
|
-
var
|
|
26093
|
+
import * as fs62 from "node:fs";
|
|
26094
|
+
import * as path63 from "node:path";
|
|
26095
|
+
import { fileURLToPath as fileURLToPath45, pathToFileURL as pathToFileURL39 } from "node:url";
|
|
26096
|
+
var EXIT_ALLOW20 = 0;
|
|
26097
|
+
var EXIT_WARN12 = 2;
|
|
25711
26098
|
var EXEMPT_PATH_PATTERNS2 = [
|
|
25712
26099
|
/(^|\/)dist\//i,
|
|
25713
26100
|
// dist/**
|
|
@@ -25722,7 +26109,7 @@ var EXEMPT_PATH_PATTERNS2 = [
|
|
|
25722
26109
|
];
|
|
25723
26110
|
var READ_TOOLS = /* @__PURE__ */ new Set(["Read"]);
|
|
25724
26111
|
var WRITE_TOOLS2 = /* @__PURE__ */ new Set(["Edit", "Write"]);
|
|
25725
|
-
function
|
|
26112
|
+
function isObject8(v) {
|
|
25726
26113
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
25727
26114
|
}
|
|
25728
26115
|
function str6(v) {
|
|
@@ -25741,16 +26128,16 @@ function deriveSessionKey4(envelope, payload) {
|
|
|
25741
26128
|
return crypto8.createHash("sha256").update(material).digest("hex");
|
|
25742
26129
|
}
|
|
25743
26130
|
function ledgerFile(workspaceRoot2, sessionKey) {
|
|
25744
|
-
return
|
|
26131
|
+
return path63.join(workspaceRoot2, "agents", "runtime", "state", "reread-guard", `${sessionKey}.json`);
|
|
25745
26132
|
}
|
|
25746
26133
|
function readLedger(workspaceRoot2, sessionKey) {
|
|
25747
26134
|
try {
|
|
25748
|
-
const parsed = JSON.parse(
|
|
25749
|
-
if (!
|
|
26135
|
+
const parsed = JSON.parse(fs62.readFileSync(ledgerFile(workspaceRoot2, sessionKey), "utf8"));
|
|
26136
|
+
if (!isObject8(parsed)) return emptyLedger();
|
|
25750
26137
|
return {
|
|
25751
|
-
reads:
|
|
25752
|
-
writes:
|
|
25753
|
-
fired:
|
|
26138
|
+
reads: isObject8(parsed["reads"]) ? parsed["reads"] : {},
|
|
26139
|
+
writes: isObject8(parsed["writes"]) ? parsed["writes"] : {},
|
|
26140
|
+
fired: isObject8(parsed["fired"]) ? parsed["fired"] : {}
|
|
25754
26141
|
};
|
|
25755
26142
|
} catch {
|
|
25756
26143
|
return emptyLedger();
|
|
@@ -25767,7 +26154,7 @@ function extractToolName3(payload) {
|
|
|
25767
26154
|
}
|
|
25768
26155
|
function extractToolInput2(payload) {
|
|
25769
26156
|
const ti = payload["tool_input"] ?? payload["toolInput"] ?? payload["input"];
|
|
25770
|
-
return
|
|
26157
|
+
return isObject8(ti) ? ti : {};
|
|
25771
26158
|
}
|
|
25772
26159
|
function extractFilePath2(toolInput) {
|
|
25773
26160
|
return str6(toolInput["file_path"] ?? toolInput["path"] ?? toolInput["filePath"]);
|
|
@@ -25786,41 +26173,41 @@ function buildDuplicateReadLine(relPath, earlierTs) {
|
|
|
25786
26173
|
function buildPostEditReadLine(relPath) {
|
|
25787
26174
|
return `re-read guard: this session just edited ${relPath} \u2014 a full-file re-read re-pays for content you already have; a ranged Read (offset/limit) over the edited hunk is enough to verify the change.`;
|
|
25788
26175
|
}
|
|
25789
|
-
function
|
|
26176
|
+
function main44() {
|
|
25790
26177
|
try {
|
|
25791
26178
|
const [envelope, payload] = unwrap(readHookStdin(), "claude");
|
|
25792
26179
|
const event = str6(envelope["event"]);
|
|
25793
|
-
if (event !== "" && event !== "pre_tool_use") return
|
|
26180
|
+
if (event !== "" && event !== "pre_tool_use") return EXIT_ALLOW20;
|
|
25794
26181
|
const toolName = extractToolName3(payload);
|
|
25795
26182
|
const isRead = READ_TOOLS.has(toolName);
|
|
25796
26183
|
const isWrite = WRITE_TOOLS2.has(toolName);
|
|
25797
|
-
if (!isRead && !isWrite) return
|
|
26184
|
+
if (!isRead && !isWrite) return EXIT_ALLOW20;
|
|
25798
26185
|
const toolInput = extractToolInput2(payload);
|
|
25799
26186
|
const filePath = extractFilePath2(toolInput);
|
|
25800
|
-
if (!filePath) return
|
|
26187
|
+
if (!filePath) return EXIT_ALLOW20;
|
|
25801
26188
|
const workspaceRoot2 = str6(envelope["workspace_root"]).trim() || process.cwd();
|
|
25802
|
-
const absPath =
|
|
25803
|
-
const relPath =
|
|
25804
|
-
if (isExemptPath2(relPath) || isExemptPath2(absPath)) return
|
|
26189
|
+
const absPath = path63.isAbsolute(filePath) ? filePath : path63.resolve(workspaceRoot2, filePath);
|
|
26190
|
+
const relPath = path63.relative(workspaceRoot2, absPath);
|
|
26191
|
+
if (isExemptPath2(relPath) || isExemptPath2(absPath)) return EXIT_ALLOW20;
|
|
25805
26192
|
const sessionKey = deriveSessionKey4(envelope, payload);
|
|
25806
26193
|
const ledger = readLedger(workspaceRoot2, sessionKey);
|
|
25807
26194
|
const key = relPath.startsWith("..") ? absPath : relPath;
|
|
25808
26195
|
if (isWrite) {
|
|
25809
26196
|
ledger.writes[key] = Date.now();
|
|
25810
26197
|
writeLedger(workspaceRoot2, sessionKey, ledger);
|
|
25811
|
-
return
|
|
26198
|
+
return EXIT_ALLOW20;
|
|
25812
26199
|
}
|
|
25813
26200
|
if (isRangedRead(toolInput)) {
|
|
25814
|
-
return
|
|
26201
|
+
return EXIT_ALLOW20;
|
|
25815
26202
|
}
|
|
25816
26203
|
let mtime;
|
|
25817
26204
|
let size;
|
|
25818
26205
|
try {
|
|
25819
|
-
const st =
|
|
26206
|
+
const st = fs62.statSync(absPath);
|
|
25820
26207
|
mtime = st.mtimeMs;
|
|
25821
26208
|
size = st.size;
|
|
25822
26209
|
} catch {
|
|
25823
|
-
return
|
|
26210
|
+
return EXIT_ALLOW20;
|
|
25824
26211
|
}
|
|
25825
26212
|
const prior = ledger.reads[key];
|
|
25826
26213
|
const ownWrite = ledger.writes[key];
|
|
@@ -25835,7 +26222,7 @@ function main43() {
|
|
|
25835
26222
|
if (ownWrite !== void 0) delete ledger.writes[key];
|
|
25836
26223
|
if (advisory !== null) ledger.fired[key] = true;
|
|
25837
26224
|
writeLedger(workspaceRoot2, sessionKey, ledger);
|
|
25838
|
-
if (advisory === null) return
|
|
26225
|
+
if (advisory === null) return EXIT_ALLOW20;
|
|
25839
26226
|
process.stdout.write(
|
|
25840
26227
|
`${JSON.stringify({
|
|
25841
26228
|
decision: "warn",
|
|
@@ -25844,9 +26231,9 @@ function main43() {
|
|
|
25844
26231
|
})}
|
|
25845
26232
|
`
|
|
25846
26233
|
);
|
|
25847
|
-
return
|
|
26234
|
+
return EXIT_WARN12;
|
|
25848
26235
|
} catch {
|
|
25849
|
-
return
|
|
26236
|
+
return EXIT_ALLOW20;
|
|
25850
26237
|
}
|
|
25851
26238
|
}
|
|
25852
26239
|
function _isCliEntry34() {
|
|
@@ -25856,27 +26243,27 @@ function _isCliEntry34() {
|
|
|
25856
26243
|
if (process.argv[1] === void 0) {
|
|
25857
26244
|
return false;
|
|
25858
26245
|
}
|
|
25859
|
-
const argvUrl =
|
|
26246
|
+
const argvUrl = pathToFileURL39(path63.resolve(process.argv[1])).href;
|
|
25860
26247
|
if (import.meta.url === argvUrl) {
|
|
25861
26248
|
return true;
|
|
25862
26249
|
}
|
|
25863
26250
|
try {
|
|
25864
|
-
const here =
|
|
25865
|
-
const argv =
|
|
26251
|
+
const here = fs62.realpathSync(fileURLToPath45(import.meta.url));
|
|
26252
|
+
const argv = fs62.realpathSync(path63.resolve(process.argv[1]));
|
|
25866
26253
|
return here === argv;
|
|
25867
26254
|
} catch {
|
|
25868
26255
|
return false;
|
|
25869
26256
|
}
|
|
25870
26257
|
}
|
|
25871
26258
|
if (_isCliEntry34()) {
|
|
25872
|
-
process.exit(
|
|
26259
|
+
process.exit(main44());
|
|
25873
26260
|
}
|
|
25874
26261
|
|
|
25875
26262
|
// src/scripts/hooks/session_eol_hook.ts
|
|
25876
|
-
import * as
|
|
25877
|
-
import * as
|
|
26263
|
+
import * as fs64 from "node:fs";
|
|
26264
|
+
import * as path66 from "node:path";
|
|
25878
26265
|
import process11 from "node:process";
|
|
25879
|
-
import { fileURLToPath as
|
|
26266
|
+
import { fileURLToPath as fileURLToPath46, pathToFileURL as pathToFileURL40 } from "node:url";
|
|
25880
26267
|
|
|
25881
26268
|
// src/config/recycle-threshold-budget.json
|
|
25882
26269
|
var recycle_threshold_budget_default = {
|
|
@@ -25894,13 +26281,13 @@ var recycle_threshold_budget_default = {
|
|
|
25894
26281
|
|
|
25895
26282
|
// src/scripts/_lib/session_eol.ts
|
|
25896
26283
|
import * as crypto9 from "node:crypto";
|
|
25897
|
-
import * as
|
|
25898
|
-
import * as
|
|
26284
|
+
import * as fs63 from "node:fs";
|
|
26285
|
+
import * as path65 from "node:path";
|
|
25899
26286
|
|
|
25900
26287
|
// src/scripts/_lib/cc_transcript.ts
|
|
25901
|
-
import * as
|
|
26288
|
+
import * as path64 from "node:path";
|
|
25902
26289
|
import { homedir as homedir6 } from "node:os";
|
|
25903
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
26290
|
+
var DEFAULT_PROJECTS_ROOT = path64.join(homedir6(), ".claude", "projects");
|
|
25904
26291
|
function billableInputTokens(u) {
|
|
25905
26292
|
return u.input_tokens + u.cache_read_input_tokens + u.cache_creation_input_tokens;
|
|
25906
26293
|
}
|
|
@@ -26009,17 +26396,17 @@ function scanEolSlice(text, prior) {
|
|
|
26009
26396
|
return next;
|
|
26010
26397
|
}
|
|
26011
26398
|
function eolStateDir(workspaceRoot2) {
|
|
26012
|
-
return
|
|
26399
|
+
return path65.join(workspaceRoot2, "agents", "runtime", "state", "session-eol");
|
|
26013
26400
|
}
|
|
26014
26401
|
function eolStateFile(workspaceRoot2, sessionKey) {
|
|
26015
|
-
return
|
|
26402
|
+
return path65.join(eolStateDir(workspaceRoot2), `${sessionKey}.json`);
|
|
26016
26403
|
}
|
|
26017
26404
|
function eolSessionKey(raw) {
|
|
26018
26405
|
return crypto9.createHash("sha256").update(raw || "unknown-session").digest("hex");
|
|
26019
26406
|
}
|
|
26020
26407
|
function readNewCompleteLines(filePath, fromByte) {
|
|
26021
26408
|
try {
|
|
26022
|
-
const { size } =
|
|
26409
|
+
const { size } = fs63.statSync(filePath);
|
|
26023
26410
|
if (size < fromByte) {
|
|
26024
26411
|
return { text: "", nextOffset: 0, truncated: true };
|
|
26025
26412
|
}
|
|
@@ -26028,11 +26415,11 @@ function readNewCompleteLines(filePath, fromByte) {
|
|
|
26028
26415
|
}
|
|
26029
26416
|
const length = size - fromByte;
|
|
26030
26417
|
const buffer = Buffer.alloc(length);
|
|
26031
|
-
const fd =
|
|
26418
|
+
const fd = fs63.openSync(filePath, "r");
|
|
26032
26419
|
try {
|
|
26033
|
-
|
|
26420
|
+
fs63.readSync(fd, buffer, 0, length, fromByte);
|
|
26034
26421
|
} finally {
|
|
26035
|
-
|
|
26422
|
+
fs63.closeSync(fd);
|
|
26036
26423
|
}
|
|
26037
26424
|
const lastNewline = buffer.lastIndexOf(10);
|
|
26038
26425
|
if (lastNewline === -1) {
|
|
@@ -26049,21 +26436,21 @@ function readNewCompleteLines(filePath, fromByte) {
|
|
|
26049
26436
|
}
|
|
26050
26437
|
|
|
26051
26438
|
// src/scripts/hooks/session_eol_hook.ts
|
|
26052
|
-
var
|
|
26439
|
+
var EXIT_WARN13 = 2;
|
|
26053
26440
|
var THRESHOLD_OVERRIDE_ENV = "AGENT_RECYCLE_THRESHOLD_TOKENS";
|
|
26054
|
-
var CONTEXT_FILL_REL =
|
|
26441
|
+
var CONTEXT_FILL_REL = path66.join("agents", "runtime", "state", "context-fill.json");
|
|
26055
26442
|
function str7(value) {
|
|
26056
26443
|
return typeof value === "string" ? value : "";
|
|
26057
26444
|
}
|
|
26058
|
-
var
|
|
26445
|
+
var stateFile3 = eolStateFile;
|
|
26059
26446
|
function deriveSessionKey5(envelope, payload) {
|
|
26060
26447
|
return eolSessionKey(
|
|
26061
26448
|
str7(envelope["session_id"]) || str7(payload["transcript_path"] ?? payload["transcriptPath"])
|
|
26062
26449
|
);
|
|
26063
26450
|
}
|
|
26064
|
-
function
|
|
26451
|
+
function readState3(file) {
|
|
26065
26452
|
try {
|
|
26066
|
-
const parsed = JSON.parse(
|
|
26453
|
+
const parsed = JSON.parse(fs64.readFileSync(file, "utf-8"));
|
|
26067
26454
|
if (parsed && typeof parsed === "object" && parsed.schema_version === 1 && parsed.counters && typeof parsed.counters.scanned_bytes === "number") {
|
|
26068
26455
|
return {
|
|
26069
26456
|
schema_version: 1,
|
|
@@ -26095,7 +26482,7 @@ function buildAdvisoryLine3(tokens, threshold) {
|
|
|
26095
26482
|
}
|
|
26096
26483
|
function writeContextFill(workspaceRoot2, tokens, threshold, ts) {
|
|
26097
26484
|
try {
|
|
26098
|
-
atomic_write_json(
|
|
26485
|
+
atomic_write_json(path66.join(workspaceRoot2, CONTEXT_FILL_REL), {
|
|
26099
26486
|
schema_version: 1,
|
|
26100
26487
|
final_context_tokens: tokens,
|
|
26101
26488
|
recycle_threshold_tokens: threshold,
|
|
@@ -26105,7 +26492,7 @@ function writeContextFill(workspaceRoot2, tokens, threshold, ts) {
|
|
|
26105
26492
|
} catch {
|
|
26106
26493
|
}
|
|
26107
26494
|
}
|
|
26108
|
-
function
|
|
26495
|
+
function main45() {
|
|
26109
26496
|
const [envelope, payload] = unwrap(readHookStdin(), "claude");
|
|
26110
26497
|
const event = String(envelope["event"] ?? "");
|
|
26111
26498
|
if (event !== "" && event !== "stop") {
|
|
@@ -26122,8 +26509,8 @@ function main44() {
|
|
|
26122
26509
|
return 0;
|
|
26123
26510
|
}
|
|
26124
26511
|
const sessionKey = deriveSessionKey5(envelope, payload);
|
|
26125
|
-
const file =
|
|
26126
|
-
const state =
|
|
26512
|
+
const file = stateFile3(workspaceRoot2, sessionKey);
|
|
26513
|
+
const state = readState3(file);
|
|
26127
26514
|
let counters = state.counters;
|
|
26128
26515
|
const read = readNewCompleteLines(transcriptPath, counters.scanned_bytes);
|
|
26129
26516
|
if (read.truncated) {
|
|
@@ -26160,7 +26547,7 @@ function main44() {
|
|
|
26160
26547
|
})}
|
|
26161
26548
|
`
|
|
26162
26549
|
);
|
|
26163
|
-
return
|
|
26550
|
+
return EXIT_WARN13;
|
|
26164
26551
|
}
|
|
26165
26552
|
return 0;
|
|
26166
26553
|
}
|
|
@@ -26171,20 +26558,20 @@ function _isCliEntry35() {
|
|
|
26171
26558
|
if (process11.argv[1] === void 0) {
|
|
26172
26559
|
return false;
|
|
26173
26560
|
}
|
|
26174
|
-
const argvUrl =
|
|
26561
|
+
const argvUrl = pathToFileURL40(path66.resolve(process11.argv[1])).href;
|
|
26175
26562
|
if (import.meta.url === argvUrl) {
|
|
26176
26563
|
return true;
|
|
26177
26564
|
}
|
|
26178
26565
|
try {
|
|
26179
|
-
const here =
|
|
26180
|
-
const argv =
|
|
26566
|
+
const here = fs64.realpathSync(fileURLToPath46(import.meta.url));
|
|
26567
|
+
const argv = fs64.realpathSync(path66.resolve(process11.argv[1]));
|
|
26181
26568
|
return here === argv;
|
|
26182
26569
|
} catch {
|
|
26183
26570
|
return false;
|
|
26184
26571
|
}
|
|
26185
26572
|
}
|
|
26186
26573
|
if (_isCliEntry35()) {
|
|
26187
|
-
process11.exit(
|
|
26574
|
+
process11.exit(main45());
|
|
26188
26575
|
}
|
|
26189
26576
|
|
|
26190
26577
|
// src/scripts/hooks/concern_registry.ts
|
|
@@ -26219,13 +26606,14 @@ var CONCERN_REGISTRY = {
|
|
|
26219
26606
|
"src/scripts/hooks/rtk_wrap_hook.ts": main33,
|
|
26220
26607
|
"src/scripts/hooks/design_slop_hook.ts": main35,
|
|
26221
26608
|
"src/scripts/hooks/code_graph_nudge_hook.ts": main36,
|
|
26222
|
-
"src/scripts/hooks/
|
|
26223
|
-
"src/scripts/hooks/
|
|
26224
|
-
"src/scripts/hooks/
|
|
26225
|
-
"src/scripts/hooks/
|
|
26226
|
-
"src/scripts/hooks/
|
|
26227
|
-
"src/scripts/hooks/
|
|
26228
|
-
"src/scripts/hooks/
|
|
26609
|
+
"src/scripts/hooks/ui_route_nudge_hook.ts": main37,
|
|
26610
|
+
"src/scripts/hooks/orchestration_record_hook.ts": main39,
|
|
26611
|
+
"src/scripts/hooks/delegation_nudge_hook.ts": main40,
|
|
26612
|
+
"src/scripts/hooks/end_review_nudge_hook.ts": main41,
|
|
26613
|
+
"src/scripts/hooks/turn_end_gate_hook.ts": main42,
|
|
26614
|
+
"src/scripts/hooks/edit_shape_hook.ts": main43,
|
|
26615
|
+
"src/scripts/hooks/reread_guard_hook.ts": main44,
|
|
26616
|
+
"src/scripts/hooks/session_eol_hook.ts": main45
|
|
26229
26617
|
};
|
|
26230
26618
|
|
|
26231
26619
|
// src/scripts/hooks/host_semantics.ts
|
|
@@ -26279,14 +26667,14 @@ function emitFor(platform, event, severity, reasons, legacyExit) {
|
|
|
26279
26667
|
|
|
26280
26668
|
// src/scripts/hooks/dispatch_hook.ts
|
|
26281
26669
|
var _IN_BUNDLE = true;
|
|
26282
|
-
var REPO_ROOT =
|
|
26283
|
-
|
|
26670
|
+
var REPO_ROOT = path67.resolve(
|
|
26671
|
+
path67.dirname(fileURLToPath47(import.meta.url)),
|
|
26284
26672
|
..._IN_BUNDLE ? ["..", ".."] : ["..", "..", ".."]
|
|
26285
26673
|
);
|
|
26286
|
-
var MANIFEST_PATH =
|
|
26287
|
-
var
|
|
26674
|
+
var MANIFEST_PATH = path67.join(REPO_ROOT, "src", "scripts", "hook_manifest.yaml");
|
|
26675
|
+
var EXIT_ALLOW21 = 0;
|
|
26288
26676
|
var EXIT_BLOCK5 = 1;
|
|
26289
|
-
var
|
|
26677
|
+
var EXIT_WARN14 = 2;
|
|
26290
26678
|
var EVENT_VOCABULARY = /* @__PURE__ */ new Set([
|
|
26291
26679
|
"session_start",
|
|
26292
26680
|
"session_end",
|
|
@@ -26298,9 +26686,9 @@ var EVENT_VOCABULARY = /* @__PURE__ */ new Set([
|
|
|
26298
26686
|
"agent_error"
|
|
26299
26687
|
]);
|
|
26300
26688
|
var _SEVERITY_BY_EXIT = {
|
|
26301
|
-
[
|
|
26689
|
+
[EXIT_ALLOW21]: "allow",
|
|
26302
26690
|
[EXIT_BLOCK5]: "block",
|
|
26303
|
-
[
|
|
26691
|
+
[EXIT_WARN14]: "warn"
|
|
26304
26692
|
};
|
|
26305
26693
|
function _isObject14(v) {
|
|
26306
26694
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -26335,7 +26723,7 @@ function _parse_concern_stdout(stdout_text) {
|
|
|
26335
26723
|
return _isObject14(parsed) ? parsed : { _raw: parsed };
|
|
26336
26724
|
}
|
|
26337
26725
|
function _load_yaml3(p) {
|
|
26338
|
-
const text =
|
|
26726
|
+
const text = fs65.readFileSync(p, "utf-8");
|
|
26339
26727
|
const data = (0, import_yaml6.parse)(text, { version: "1.1" });
|
|
26340
26728
|
return _isObject14(data) ? data : {};
|
|
26341
26729
|
}
|
|
@@ -26492,7 +26880,7 @@ function _maybe_capture_payload(args, payload_text) {
|
|
|
26492
26880
|
}
|
|
26493
26881
|
try {
|
|
26494
26882
|
const target = _expanduser3(capture_dir);
|
|
26495
|
-
|
|
26883
|
+
fs65.mkdirSync(target, { recursive: true });
|
|
26496
26884
|
let payload;
|
|
26497
26885
|
try {
|
|
26498
26886
|
payload = payload_text.trim() ? JSON.parse(payload_text) : {};
|
|
@@ -26509,8 +26897,8 @@ function _maybe_capture_payload(args, payload_text) {
|
|
|
26509
26897
|
const ts = Date.now();
|
|
26510
26898
|
const native = (args.native_event || args.event).replace(/\//g, "_");
|
|
26511
26899
|
const fname = `${args.platform}__${native}__${ts}__${process.pid}.json`;
|
|
26512
|
-
|
|
26513
|
-
|
|
26900
|
+
fs65.writeFileSync(
|
|
26901
|
+
path67.join(target, fname),
|
|
26514
26902
|
_py_json_dumps2(record, 2) + "\n",
|
|
26515
26903
|
{ encoding: "utf-8" }
|
|
26516
26904
|
);
|
|
@@ -26521,7 +26909,7 @@ function _maybe_capture_payload(args, payload_text) {
|
|
|
26521
26909
|
function _expanduser3(p) {
|
|
26522
26910
|
if (p === "~" || p.startsWith("~/")) {
|
|
26523
26911
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "";
|
|
26524
|
-
return
|
|
26912
|
+
return path67.join(home, p.slice(1));
|
|
26525
26913
|
}
|
|
26526
26914
|
return p;
|
|
26527
26915
|
}
|
|
@@ -26553,25 +26941,25 @@ function _resolve_tsx_invocation2(scriptPath, scriptArgs) {
|
|
|
26553
26941
|
const walkUp = (start) => {
|
|
26554
26942
|
let dir = start;
|
|
26555
26943
|
for (; ; ) {
|
|
26556
|
-
const candidate =
|
|
26944
|
+
const candidate = path67.join(dir, "node_modules", ".bin", binName);
|
|
26557
26945
|
if (_isFile7(candidate)) {
|
|
26558
26946
|
return candidate;
|
|
26559
26947
|
}
|
|
26560
|
-
const parent =
|
|
26948
|
+
const parent = path67.dirname(dir);
|
|
26561
26949
|
if (parent === dir) {
|
|
26562
26950
|
return null;
|
|
26563
26951
|
}
|
|
26564
26952
|
dir = parent;
|
|
26565
26953
|
}
|
|
26566
26954
|
};
|
|
26567
|
-
const tsx = walkUp(
|
|
26955
|
+
const tsx = walkUp(path67.dirname(scriptPath)) ?? walkUp(path67.dirname(fileURLToPath47(import.meta.url)));
|
|
26568
26956
|
if (tsx !== null) {
|
|
26569
26957
|
return { command: tsx, args: [scriptPath, ...scriptArgs] };
|
|
26570
26958
|
}
|
|
26571
26959
|
return { command: "npx", args: ["tsx", scriptPath, ...scriptArgs] };
|
|
26572
26960
|
}
|
|
26573
26961
|
function _run_concern_inproc(main_fn, concern, envelope) {
|
|
26574
|
-
const scriptAbs =
|
|
26962
|
+
const scriptAbs = path67.join(REPO_ROOT, String(concern["script"]));
|
|
26575
26963
|
const argsList = Array.isArray(concern["args"]) ? concern["args"].map((a) => String(a)) : [];
|
|
26576
26964
|
argsList.push("--platform", String(envelope["platform"] || "generic"));
|
|
26577
26965
|
const workspace = String(envelope["workspace_root"] || process.cwd());
|
|
@@ -26648,7 +27036,7 @@ function _run_concern(concern, envelope) {
|
|
|
26648
27036
|
return _run_concern_inproc(inproc, concern, envelope);
|
|
26649
27037
|
}
|
|
26650
27038
|
}
|
|
26651
|
-
const script =
|
|
27039
|
+
const script = path67.join(REPO_ROOT, String(concern["script"]));
|
|
26652
27040
|
const argsList = Array.isArray(concern["args"]) ? concern["args"].map((a) => String(a)) : [];
|
|
26653
27041
|
const cmd = [script, ...argsList];
|
|
26654
27042
|
cmd.push("--platform", String(envelope["platform"] || "generic"));
|
|
@@ -26705,7 +27093,7 @@ function _run_concern(concern, envelope) {
|
|
|
26705
27093
|
}
|
|
26706
27094
|
function _isFile7(p) {
|
|
26707
27095
|
try {
|
|
26708
|
-
return
|
|
27096
|
+
return fs65.statSync(p).isFile();
|
|
26709
27097
|
} catch {
|
|
26710
27098
|
return false;
|
|
26711
27099
|
}
|
|
@@ -26717,20 +27105,20 @@ function _reduce(rcs) {
|
|
|
26717
27105
|
if (rcs.some((rc) => rc === EXIT_BLOCK5)) {
|
|
26718
27106
|
return EXIT_BLOCK5;
|
|
26719
27107
|
}
|
|
26720
|
-
if (rcs.some((rc) => rc ===
|
|
26721
|
-
return
|
|
27108
|
+
if (rcs.some((rc) => rc === EXIT_WARN14)) {
|
|
27109
|
+
return EXIT_WARN14;
|
|
26722
27110
|
}
|
|
26723
|
-
return
|
|
27111
|
+
return EXIT_ALLOW21;
|
|
26724
27112
|
}
|
|
26725
27113
|
function _write_feedback(envelope, session_id, entries, final_rc, started_at) {
|
|
26726
27114
|
if (is_replay_mode()) {
|
|
26727
27115
|
return;
|
|
26728
27116
|
}
|
|
26729
27117
|
const workspace = String(envelope["workspace_root"] || process.cwd());
|
|
26730
|
-
const state_root =
|
|
27118
|
+
const state_root = path67.join(workspace, "agents", "runtime", "state");
|
|
26731
27119
|
const fb_dir = feedback_dir(state_root, session_id);
|
|
26732
27120
|
try {
|
|
26733
|
-
|
|
27121
|
+
fs65.mkdirSync(fb_dir, { recursive: true });
|
|
26734
27122
|
} catch (exc) {
|
|
26735
27123
|
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
26736
27124
|
process.stderr.write(`dispatch_hook: feedback dir unavailable: ${msg}
|
|
@@ -26738,7 +27126,7 @@ function _write_feedback(envelope, session_id, entries, final_rc, started_at) {
|
|
|
26738
27126
|
return;
|
|
26739
27127
|
}
|
|
26740
27128
|
for (const entry of entries) {
|
|
26741
|
-
const target =
|
|
27129
|
+
const target = path67.join(fb_dir, `${entry["concern"]}.json`);
|
|
26742
27130
|
try {
|
|
26743
27131
|
atomic_write_json(target, entry);
|
|
26744
27132
|
} catch (exc) {
|
|
@@ -26778,7 +27166,7 @@ function _write_feedback(envelope, session_id, entries, final_rc, started_at) {
|
|
|
26778
27166
|
})
|
|
26779
27167
|
};
|
|
26780
27168
|
try {
|
|
26781
|
-
atomic_write_json(
|
|
27169
|
+
atomic_write_json(path67.join(fb_dir, "summary.json"), summary);
|
|
26782
27170
|
} catch (exc) {
|
|
26783
27171
|
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
26784
27172
|
process.stderr.write(`dispatch_hook: summary write failed: ${msg}
|
|
@@ -26788,17 +27176,17 @@ function _write_feedback(envelope, session_id, entries, final_rc, started_at) {
|
|
|
26788
27176
|
function _record_rule_trips(envelope, entries) {
|
|
26789
27177
|
if (is_replay_mode()) return;
|
|
26790
27178
|
const tripped = entries.filter(
|
|
26791
|
-
(e) => e["exit_code"] === EXIT_BLOCK5 || e["exit_code"] ===
|
|
27179
|
+
(e) => e["exit_code"] === EXIT_BLOCK5 || e["exit_code"] === EXIT_WARN14
|
|
26792
27180
|
);
|
|
26793
27181
|
if (tripped.length === 0) return;
|
|
26794
27182
|
try {
|
|
26795
27183
|
const workspace = String(envelope["workspace_root"] || process.cwd());
|
|
26796
|
-
const state_dir =
|
|
26797
|
-
const target =
|
|
26798
|
-
|
|
27184
|
+
const state_dir = path67.join(workspace, "agents", "runtime", "state");
|
|
27185
|
+
const target = path67.join(state_dir, "rule-trips.json");
|
|
27186
|
+
fs65.mkdirSync(state_dir, { recursive: true });
|
|
26799
27187
|
let doc = { schema_version: 1, concerns: {} };
|
|
26800
27188
|
try {
|
|
26801
|
-
const parsed = JSON.parse(
|
|
27189
|
+
const parsed = JSON.parse(fs65.readFileSync(target, "utf-8"));
|
|
26802
27190
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) doc = parsed;
|
|
26803
27191
|
} catch {
|
|
26804
27192
|
}
|
|
@@ -26809,7 +27197,7 @@ function _record_rule_trips(envelope, entries) {
|
|
|
26809
27197
|
const prev = concerns[name] ?? { block: 0, warn: 0 };
|
|
26810
27198
|
concerns[name] = {
|
|
26811
27199
|
block: (Number(prev["block"]) || 0) + (e["exit_code"] === EXIT_BLOCK5 ? 1 : 0),
|
|
26812
|
-
warn: (Number(prev["warn"]) || 0) + (e["exit_code"] ===
|
|
27200
|
+
warn: (Number(prev["warn"]) || 0) + (e["exit_code"] === EXIT_WARN14 ? 1 : 0),
|
|
26813
27201
|
last_trip: today
|
|
26814
27202
|
};
|
|
26815
27203
|
}
|
|
@@ -26897,7 +27285,7 @@ function _parse_args(argv) {
|
|
|
26897
27285
|
}
|
|
26898
27286
|
return args;
|
|
26899
27287
|
}
|
|
26900
|
-
function
|
|
27288
|
+
function main46(argv) {
|
|
26901
27289
|
const args = _parse_args(argv ?? process.argv.slice(2));
|
|
26902
27290
|
if (args.project_dir) {
|
|
26903
27291
|
const project_dir = _expanduser3(args.project_dir);
|
|
@@ -26915,13 +27303,13 @@ function main45(argv) {
|
|
|
26915
27303
|
`dispatch_hook: unknown event '${args.event}'; allowed: ${_sortedRepr(EVENT_VOCABULARY)}
|
|
26916
27304
|
`
|
|
26917
27305
|
);
|
|
26918
|
-
return
|
|
27306
|
+
return EXIT_ALLOW21;
|
|
26919
27307
|
}
|
|
26920
27308
|
const manifest_path = args.manifest;
|
|
26921
|
-
if (!
|
|
27309
|
+
if (!fs65.existsSync(manifest_path)) {
|
|
26922
27310
|
process.stderr.write(`dispatch_hook: manifest missing at ${manifest_path}
|
|
26923
27311
|
`);
|
|
26924
|
-
return
|
|
27312
|
+
return EXIT_ALLOW21;
|
|
26925
27313
|
}
|
|
26926
27314
|
const manifest = _load_yaml3(manifest_path);
|
|
26927
27315
|
if (args.min_version) {
|
|
@@ -26945,10 +27333,10 @@ function main45(argv) {
|
|
|
26945
27333
|
concerns: concerns.map((c) => c["name"])
|
|
26946
27334
|
};
|
|
26947
27335
|
process.stdout.write(_py_json_dumps2(plan, 2) + "\n");
|
|
26948
|
-
return
|
|
27336
|
+
return EXIT_ALLOW21;
|
|
26949
27337
|
}
|
|
26950
27338
|
if (concerns.length === 0) {
|
|
26951
|
-
return
|
|
27339
|
+
return EXIT_ALLOW21;
|
|
26952
27340
|
}
|
|
26953
27341
|
const envelope = _build_envelope(args, payload_text);
|
|
26954
27342
|
const session_id = _resolve_session_id(envelope);
|
|
@@ -26968,7 +27356,7 @@ function main45(argv) {
|
|
|
26968
27356
|
const raw_rc = rc;
|
|
26969
27357
|
if (rc >= 3) {
|
|
26970
27358
|
if (!concern["fail_closed"]) {
|
|
26971
|
-
rc =
|
|
27359
|
+
rc = EXIT_ALLOW21;
|
|
26972
27360
|
} else {
|
|
26973
27361
|
rc = EXIT_BLOCK5;
|
|
26974
27362
|
}
|
|
@@ -26981,7 +27369,7 @@ function main45(argv) {
|
|
|
26981
27369
|
`dispatch_hook: concern '${String(concern["name"])}' is declared severity: advisory but returned BLOCK \u2014 downgraded to warn.
|
|
26982
27370
|
`
|
|
26983
27371
|
);
|
|
26984
|
-
rc =
|
|
27372
|
+
rc = EXIT_WARN14;
|
|
26985
27373
|
}
|
|
26986
27374
|
rcs.push(rc);
|
|
26987
27375
|
const reply = _parse_concern_stdout(stdout_text);
|
|
@@ -26991,7 +27379,7 @@ function main45(argv) {
|
|
|
26991
27379
|
if (message) {
|
|
26992
27380
|
concern_messages.push({ rc, text: message });
|
|
26993
27381
|
}
|
|
26994
|
-
if (args.event === "session_start" && rc ===
|
|
27382
|
+
if (args.event === "session_start" && rc === EXIT_ALLOW21 && typeof reply["context"] === "string" && reply["context"].trim()) {
|
|
26995
27383
|
context_blocks.push(reply["context"].trim());
|
|
26996
27384
|
}
|
|
26997
27385
|
feedback_entries.push({
|
|
@@ -27010,7 +27398,7 @@ function main45(argv) {
|
|
|
27010
27398
|
const final_rc = _reduce(rcs);
|
|
27011
27399
|
_write_feedback(envelope, session_id, feedback_entries, final_rc, started_at);
|
|
27012
27400
|
_record_rule_trips(envelope, feedback_entries);
|
|
27013
|
-
if (context_blocks.length > 0 && final_rc ===
|
|
27401
|
+
if (context_blocks.length > 0 && final_rc === EXIT_ALLOW21) {
|
|
27014
27402
|
process.stdout.write(context_blocks.join("\n\n") + "\n");
|
|
27015
27403
|
}
|
|
27016
27404
|
const decidingReasons = concern_messages.filter((m) => m.rc === final_rc).map((m) => m.text);
|
|
@@ -27031,7 +27419,7 @@ function main45(argv) {
|
|
|
27031
27419
|
}
|
|
27032
27420
|
function _isDir4(p) {
|
|
27033
27421
|
try {
|
|
27034
|
-
return
|
|
27422
|
+
return fs65.statSync(p).isDirectory();
|
|
27035
27423
|
} catch {
|
|
27036
27424
|
return false;
|
|
27037
27425
|
}
|
|
@@ -27042,7 +27430,7 @@ function _sortedRepr(s) {
|
|
|
27042
27430
|
}
|
|
27043
27431
|
function _readStdin14() {
|
|
27044
27432
|
try {
|
|
27045
|
-
return
|
|
27433
|
+
return fs65.readFileSync(0, "utf-8");
|
|
27046
27434
|
} catch {
|
|
27047
27435
|
return "";
|
|
27048
27436
|
}
|
|
@@ -27054,29 +27442,29 @@ function _isCliEntry36() {
|
|
|
27054
27442
|
if (process.argv[1] === void 0) {
|
|
27055
27443
|
return false;
|
|
27056
27444
|
}
|
|
27057
|
-
const argvUrl =
|
|
27445
|
+
const argvUrl = pathToFileURL41(path67.resolve(process.argv[1])).href;
|
|
27058
27446
|
if (import.meta.url === argvUrl) {
|
|
27059
27447
|
return true;
|
|
27060
27448
|
}
|
|
27061
27449
|
try {
|
|
27062
|
-
const here =
|
|
27063
|
-
const argv =
|
|
27450
|
+
const here = fs65.realpathSync(fileURLToPath47(import.meta.url));
|
|
27451
|
+
const argv = fs65.realpathSync(path67.resolve(process.argv[1]));
|
|
27064
27452
|
return here === argv;
|
|
27065
27453
|
} catch {
|
|
27066
27454
|
return false;
|
|
27067
27455
|
}
|
|
27068
27456
|
}
|
|
27069
|
-
var
|
|
27070
|
-
if (
|
|
27071
|
-
process.exit(
|
|
27457
|
+
var isCliEntry13 = _isCliEntry36();
|
|
27458
|
+
if (isCliEntry13) {
|
|
27459
|
+
process.exit(main46(process.argv.slice(2)));
|
|
27072
27460
|
}
|
|
27073
27461
|
|
|
27074
27462
|
// src/scripts/hooks/dispatch_entry.ts
|
|
27075
|
-
var _selfPath =
|
|
27076
|
-
var _invokedDirectly2 = globalThis.__AC_HOOKS_BUNDLE_DIRECT === true || process.argv[1] !== void 0 &&
|
|
27463
|
+
var _selfPath = fileURLToPath48(import.meta.url);
|
|
27464
|
+
var _invokedDirectly2 = globalThis.__AC_HOOKS_BUNDLE_DIRECT === true || process.argv[1] !== void 0 && path68.resolve(process.argv[1]) === path68.resolve(_selfPath);
|
|
27077
27465
|
if (_invokedDirectly2) {
|
|
27078
|
-
process.exitCode =
|
|
27466
|
+
process.exitCode = main46(process.argv.slice(2));
|
|
27079
27467
|
}
|
|
27080
27468
|
export {
|
|
27081
|
-
|
|
27469
|
+
main46 as main
|
|
27082
27470
|
};
|