token-harness 0.1.23 → 0.1.25
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/README.md +27 -0
- package/package.json +1 -1
- package/sbom.json +3 -3
- package/token-harness.mjs +1306 -117
package/token-harness.mjs
CHANGED
|
@@ -759,6 +759,27 @@ function parseBoundaryPolicy(value3) {
|
|
|
759
759
|
return void 0;
|
|
760
760
|
return { model, reasoningEffort, verbosity, verification: "config-only" };
|
|
761
761
|
}
|
|
762
|
+
function parseNativeRoutingObservation(value3) {
|
|
763
|
+
if (value3 === null)
|
|
764
|
+
return null;
|
|
765
|
+
const row2 = record(value3);
|
|
766
|
+
if (row2 === null)
|
|
767
|
+
return void 0;
|
|
768
|
+
const configured = row2["configured"];
|
|
769
|
+
const promptSubmissions = row2["promptSubmissions"];
|
|
770
|
+
const subagentsStarted = row2["subagentsStarted"];
|
|
771
|
+
const subagentsStopped = row2["subagentsStopped"];
|
|
772
|
+
const reportedModels = row2["reportedModels"];
|
|
773
|
+
if (!(configured === null || typeof configured === "boolean") || !Number.isSafeInteger(promptSubmissions) || typeof promptSubmissions !== "number" || promptSubmissions < 0 || !Number.isSafeInteger(subagentsStarted) || typeof subagentsStarted !== "number" || subagentsStarted < 0 || !Number.isSafeInteger(subagentsStopped) || typeof subagentsStopped !== "number" || subagentsStopped < 0 || !Array.isArray(reportedModels) || !reportedModels.every((model) => typeof model === "string" && model.length <= 80))
|
|
774
|
+
return void 0;
|
|
775
|
+
return {
|
|
776
|
+
configured,
|
|
777
|
+
promptSubmissions,
|
|
778
|
+
subagentsStarted,
|
|
779
|
+
subagentsStopped,
|
|
780
|
+
reportedModels: [...new Set(reportedModels)]
|
|
781
|
+
};
|
|
782
|
+
}
|
|
762
783
|
function parseTaskBenchmarkCapture(value3) {
|
|
763
784
|
const row2 = record(value3);
|
|
764
785
|
if (row2 === null) {
|
|
@@ -785,7 +806,9 @@ function parseTaskBenchmarkCapture(value3) {
|
|
|
785
806
|
const localSessionsBefore = parsedLocalSessions === void 0 ? null : parsedLocalSessions;
|
|
786
807
|
const hasContextAtStart = Object.hasOwn(row2, "contextAtStart");
|
|
787
808
|
const contextAtStart = hasContextAtStart ? parseTaskBenchmarkContextSnapshot(row2["contextAtStart"]) : void 0;
|
|
788
|
-
|
|
809
|
+
const hasNativeRoutingAtStart = Object.hasOwn(row2, "nativeRoutingAtStart");
|
|
810
|
+
const nativeRoutingAtStart = hasNativeRoutingAtStart ? parseNativeRoutingObservation(row2["nativeRoutingAtStart"]) : void 0;
|
|
811
|
+
if (typeof benchmarkId !== "string" || !isTaskBenchmarkId(benchmarkId) || typeof variant !== "string" || !isTaskBenchmarkVariant(variant) || typeof taskClass !== "string" || !isTaskClass(taskClass) || typeof harnessId2 !== "string" || !isHarnessId(harnessId2) || typeof projectId !== "string" || projectId === "" || model === void 0 || reasoningEffort === void 0 || verbosity === void 0 || !validInstant(startedAt) || usageBefore === null || parsedLocalSessions === void 0 || hasContextAtStart && contextAtStart === void 0 || hasNativeRoutingAtStart && nativeRoutingAtStart === void 0) {
|
|
789
812
|
return {
|
|
790
813
|
ok: false,
|
|
791
814
|
reason: "invalid-shape",
|
|
@@ -807,6 +830,7 @@ function parseTaskBenchmarkCapture(value3) {
|
|
|
807
830
|
startedAt,
|
|
808
831
|
usageBefore,
|
|
809
832
|
...hasContextAtStart ? { contextAtStart: contextAtStart ?? null } : {},
|
|
833
|
+
...hasNativeRoutingAtStart ? { nativeRoutingAtStart: nativeRoutingAtStart ?? null } : {},
|
|
810
834
|
localSessionsBefore
|
|
811
835
|
}
|
|
812
836
|
};
|
|
@@ -842,7 +866,11 @@ function parseTaskBenchmarkReceipt(value3) {
|
|
|
842
866
|
const contextAtStart = hasContextAtStart ? parseTaskBenchmarkContextSnapshot(row2["contextAtStart"]) : void 0;
|
|
843
867
|
const hasContextAtFinish = Object.hasOwn(row2, "contextAtFinish");
|
|
844
868
|
const contextAtFinish = hasContextAtFinish ? parseTaskBenchmarkContextSnapshot(row2["contextAtFinish"]) : void 0;
|
|
845
|
-
|
|
869
|
+
const hasNativeRoutingAtStart = Object.hasOwn(row2, "nativeRoutingAtStart");
|
|
870
|
+
const nativeRoutingAtStart = hasNativeRoutingAtStart ? parseNativeRoutingObservation(row2["nativeRoutingAtStart"]) : void 0;
|
|
871
|
+
const hasNativeRoutingAtFinish = Object.hasOwn(row2, "nativeRoutingAtFinish");
|
|
872
|
+
const nativeRoutingAtFinish = hasNativeRoutingAtFinish ? parseNativeRoutingObservation(row2["nativeRoutingAtFinish"]) : void 0;
|
|
873
|
+
if (typeof benchmarkId !== "string" || benchmarkId === "" || typeof variant !== "string" || !isTaskBenchmarkVariant(variant) || typeof taskClass !== "string" || !isTaskClass(taskClass) || typeof harnessId2 !== "string" || !isHarnessId(harnessId2) || model === void 0 || reasoningEffort === void 0 || verbosity === void 0 || !validInstant(startedAt) || !validInstant(completedAt) || Date.parse(completedAt) < Date.parse(startedAt) || usageBefore === null || usageAfter === null || localUsage === void 0 || outcome2 === null || hasBoundaryPolicy && policyAtFinish === void 0 || hasContextAtStart && contextAtStart === void 0 || hasContextAtFinish && contextAtFinish === void 0 || hasNativeRoutingAtStart && nativeRoutingAtStart === void 0 || hasNativeRoutingAtFinish && nativeRoutingAtFinish === void 0) {
|
|
846
874
|
return {
|
|
847
875
|
ok: false,
|
|
848
876
|
reason: "invalid-shape",
|
|
@@ -868,7 +896,9 @@ function parseTaskBenchmarkReceipt(value3) {
|
|
|
868
896
|
outcome: outcome2,
|
|
869
897
|
...hasContextAtStart ? { contextAtStart: contextAtStart ?? null } : {},
|
|
870
898
|
...hasContextAtFinish ? { contextAtFinish: contextAtFinish ?? null } : {},
|
|
871
|
-
...hasBoundaryPolicy ? { policyAtFinish: policyAtFinish ?? null } : {}
|
|
899
|
+
...hasBoundaryPolicy ? { policyAtFinish: policyAtFinish ?? null } : {},
|
|
900
|
+
...hasNativeRoutingAtStart ? { nativeRoutingAtStart: nativeRoutingAtStart ?? null } : {},
|
|
901
|
+
...hasNativeRoutingAtFinish ? { nativeRoutingAtFinish: nativeRoutingAtFinish ?? null } : {}
|
|
872
902
|
}
|
|
873
903
|
};
|
|
874
904
|
}
|
|
@@ -888,7 +918,9 @@ function completeTaskBenchmarkCapture(capture, input) {
|
|
|
888
918
|
usageAfter: input.usageAfter,
|
|
889
919
|
localUsage: input.localUsage ?? null,
|
|
890
920
|
...capture.contextAtStart !== void 0 ? { contextAtStart: capture.contextAtStart } : {},
|
|
921
|
+
...capture.nativeRoutingAtStart !== void 0 ? { nativeRoutingAtStart: capture.nativeRoutingAtStart } : {},
|
|
891
922
|
...input.contextAtFinish !== void 0 ? { contextAtFinish: input.contextAtFinish } : {},
|
|
923
|
+
...input.nativeRoutingAtFinish !== void 0 ? { nativeRoutingAtFinish: input.nativeRoutingAtFinish } : {},
|
|
892
924
|
...input.policyAtFinish !== void 0 ? { policyAtFinish: input.policyAtFinish } : {},
|
|
893
925
|
outcome: {
|
|
894
926
|
qualityGate: input.qualityGate,
|
|
@@ -1096,7 +1128,8 @@ function buildTaskBenchmarkMatrix(pairs, selection = {
|
|
|
1096
1128
|
baselineLocalTokens,
|
|
1097
1129
|
optimizedLocalTokens,
|
|
1098
1130
|
localTokenSavingPercent: !bothQualityPassed || baselineLocalTokens === null || optimizedLocalTokens === null ? null : roundedPercent(baselineLocalTokens - optimizedLocalTokens, baselineLocalTokens),
|
|
1099
|
-
quota: comparison.quota
|
|
1131
|
+
quota: comparison.quota,
|
|
1132
|
+
...nativeRoutingComparison(baseline, optimized)
|
|
1100
1133
|
};
|
|
1101
1134
|
}).sort((left, right) => TASK_CLASS_ORDER.indexOf(left.taskClass) - TASK_CLASS_ORDER.indexOf(right.taskClass) || left.benchmarkId.localeCompare(right.benchmarkId));
|
|
1102
1135
|
const byTaskClass = TASK_CLASS_ORDER.map((taskClass) => ({
|
|
@@ -1110,6 +1143,36 @@ function buildTaskBenchmarkMatrix(pairs, selection = {
|
|
|
1110
1143
|
selection
|
|
1111
1144
|
};
|
|
1112
1145
|
}
|
|
1146
|
+
function nativeRoutingComparison(baseline, optimized) {
|
|
1147
|
+
const bStart = baseline.nativeRoutingAtStart;
|
|
1148
|
+
const bFinish = baseline.nativeRoutingAtFinish;
|
|
1149
|
+
const oStart = optimized.nativeRoutingAtStart;
|
|
1150
|
+
const oFinish = optimized.nativeRoutingAtFinish;
|
|
1151
|
+
if (bStart === void 0 && bFinish === void 0 && oStart === void 0 && oFinish === void 0)
|
|
1152
|
+
return {};
|
|
1153
|
+
const qualityGatesPassed = baseline.outcome.qualityGate === "passed" && optimized.outcome.qualityGate === "passed";
|
|
1154
|
+
if (bStart == null || bFinish == null || oStart == null || oFinish == null || bStart.configured === null || oStart.configured === null) {
|
|
1155
|
+
return {
|
|
1156
|
+
nativeRouting: {
|
|
1157
|
+
verdict: "unknown",
|
|
1158
|
+
baselineSubagents: bFinish?.subagentsStarted ?? null,
|
|
1159
|
+
optimizedSubagents: oFinish?.subagentsStarted ?? null,
|
|
1160
|
+
optimizedReportedModels: oFinish?.reportedModels ?? [],
|
|
1161
|
+
qualityGatesPassed
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
const attributed = bStart.configured === false && bFinish.configured === false && bFinish.subagentsStarted === 0 && oStart.configured === true && oFinish.configured === true && oFinish.promptSubmissions > 0 && oFinish.subagentsStarted > 0;
|
|
1166
|
+
return {
|
|
1167
|
+
nativeRouting: {
|
|
1168
|
+
verdict: attributed ? "attributed" : "not-attributed",
|
|
1169
|
+
baselineSubagents: bFinish.subagentsStarted,
|
|
1170
|
+
optimizedSubagents: oFinish.subagentsStarted,
|
|
1171
|
+
optimizedReportedModels: [...oFinish.reportedModels],
|
|
1172
|
+
qualityGatesPassed
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1113
1176
|
var TASK_BENCHMARK_RECEIPT_SCHEMA_VERSION, TASK_BENCHMARK_CAPTURE_SCHEMA_VERSION, BENCHMARK_ID, WINDOW_SCOPES, WINDOW_SOURCES, WINDOW_CONFIDENCES, WINDOW_KINDS, QUOTA_SCOPE_PRIORITY, TASK_CLASS_ORDER;
|
|
1114
1177
|
var init_benchmark = __esm({
|
|
1115
1178
|
"packages/core/dist/src/domain/benchmark.js"() {
|
|
@@ -4144,11 +4207,19 @@ function findCompatibilityRule(rules, query) {
|
|
|
4144
4207
|
candidates.push(rule);
|
|
4145
4208
|
}
|
|
4146
4209
|
if (query.observedVersions !== void 0) {
|
|
4147
|
-
const matchesObservedTuple = (rule) =>
|
|
4210
|
+
const matchesObservedTuple = (rule) => {
|
|
4211
|
+
if (rule.providers.some((provider) => rule.testedVersions[provider] === void 0)) {
|
|
4212
|
+
return false;
|
|
4213
|
+
}
|
|
4214
|
+
const testedHarnessVersion = rule.testedHarnessVersions?.[query.harness];
|
|
4215
|
+
if (rule.outcome === "ordered" && testedHarnessVersion === void 0)
|
|
4216
|
+
return false;
|
|
4217
|
+
return Object.entries(rule.testedVersions).every(([provider, version3]) => query.observedVersions?.[provider] === version3) && (testedHarnessVersion === void 0 || query.observedHarnessVersions?.[query.harness] === testedHarnessVersion);
|
|
4218
|
+
};
|
|
4148
4219
|
const exact = candidates.find(matchesObservedTuple);
|
|
4149
4220
|
if (exact !== void 0)
|
|
4150
4221
|
return exact;
|
|
4151
|
-
const matchingDimensions = (rule) => Object.entries(rule.testedVersions).filter(([provider, version3]) => query.observedVersions?.[provider] === version3).length +
|
|
4222
|
+
const matchingDimensions = (rule) => Object.entries(rule.testedVersions).filter(([provider, version3]) => query.observedVersions?.[provider] === version3).length + (rule.testedHarnessVersions?.[query.harness] !== void 0 && query.observedHarnessVersions?.[query.harness] === rule.testedHarnessVersions[query.harness] ? 1 : 0);
|
|
4152
4223
|
candidates.sort((left, right) => matchingDimensions(right) - matchingDimensions(left));
|
|
4153
4224
|
}
|
|
4154
4225
|
return candidates[0] ?? null;
|
|
@@ -4160,26 +4231,24 @@ function coversVersion(recorded, observed) {
|
|
|
4160
4231
|
}
|
|
4161
4232
|
function staleRecordedVersions(rule, observed) {
|
|
4162
4233
|
const stale2 = [];
|
|
4163
|
-
for (const
|
|
4234
|
+
for (const provider of rule.providers) {
|
|
4235
|
+
const recorded = rule.testedVersions[provider];
|
|
4164
4236
|
const seen = observed[provider] ?? null;
|
|
4165
|
-
const recordedVersion = parseSemanticVersion(recorded);
|
|
4237
|
+
const recordedVersion = recorded === void 0 ? null : parseSemanticVersion(recorded);
|
|
4166
4238
|
const seenVersion = seen === null ? null : parseSemanticVersion(seen);
|
|
4167
4239
|
if (recordedVersion !== null && seenVersion !== null && coversVersion(recordedVersion, seenVersion)) {
|
|
4168
4240
|
continue;
|
|
4169
4241
|
}
|
|
4170
|
-
stale2.push({ provider, recorded, observed: seen });
|
|
4242
|
+
stale2.push({ provider, recorded: recorded ?? null, observed: seen });
|
|
4171
4243
|
}
|
|
4172
4244
|
return stale2;
|
|
4173
4245
|
}
|
|
4174
|
-
function staleRecordedHarnessVersions(rule, observed) {
|
|
4175
|
-
const
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
stale2.push({ harness, recorded, observed: seen });
|
|
4181
|
-
}
|
|
4182
|
-
return stale2;
|
|
4246
|
+
function staleRecordedHarnessVersions(rule, observed, harness) {
|
|
4247
|
+
const recorded = rule.testedHarnessVersions?.[harness];
|
|
4248
|
+
if (recorded === void 0 && rule.outcome !== "ordered")
|
|
4249
|
+
return [];
|
|
4250
|
+
const seen = observed[harness] ?? null;
|
|
4251
|
+
return recorded !== void 0 && seen === recorded ? [] : [{ harness, recorded: recorded ?? null, observed: seen }];
|
|
4183
4252
|
}
|
|
4184
4253
|
var init_compatibility = __esm({
|
|
4185
4254
|
"packages/core/dist/src/domain/compatibility.js"() {
|
|
@@ -4606,35 +4675,36 @@ function detectUnownedEntries(input) {
|
|
|
4606
4675
|
});
|
|
4607
4676
|
}
|
|
4608
4677
|
for (const config of input.configs) {
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4678
|
+
const observedHooks = config.hookCommands === void 0 ? config.interceptionPoints.flatMap((interceptionPoint) => config.matchers.flatMap((toolFamily) => config.commands.map((command) => ({
|
|
4679
|
+
interceptionPoint,
|
|
4680
|
+
toolFamilies: [toolFamily],
|
|
4681
|
+
command
|
|
4682
|
+
})))) : config.hookCommands;
|
|
4683
|
+
for (const hook of observedHooks) {
|
|
4684
|
+
for (const [key, resolved] of exclusiveOwners) {
|
|
4685
|
+
if (resolved.scope.harness !== config.harnessId)
|
|
4686
|
+
continue;
|
|
4687
|
+
if (resolved.scope.interceptionPoint !== hook.interceptionPoint)
|
|
4688
|
+
continue;
|
|
4689
|
+
if (!hook.toolFamilies.includes(resolved.scope.toolFamily))
|
|
4690
|
+
continue;
|
|
4691
|
+
const belongsTo = input.identify(hook.command);
|
|
4692
|
+
if (belongsTo === resolved.owner)
|
|
4693
|
+
continue;
|
|
4694
|
+
findings.push({
|
|
4695
|
+
code: "unowned-entry-on-exclusive-scope",
|
|
4696
|
+
scope: key,
|
|
4697
|
+
expectedOwner: resolved.owner,
|
|
4698
|
+
configPath: config.configPath,
|
|
4699
|
+
matcher: resolved.scope.toolFamily,
|
|
4700
|
+
command: hook.command,
|
|
4701
|
+
detail: [
|
|
4702
|
+
`${key} is an exclusive scope owned by ${resolved.owner}`,
|
|
4703
|
+
belongsTo === null ? "An entry here invokes a command Token Harness does not recognise" : `An entry here invokes ${belongsTo}`,
|
|
4704
|
+
"The harness runs every matching hook rather than only the first, so both would transform the same payload and the saving would be counted twice"
|
|
4705
|
+
],
|
|
4706
|
+
remediation: "Remove the competing entry, or assign the scope to it explicitly with `profile: custom`. Token Harness will not remove a third party\u2019s entry."
|
|
4707
|
+
});
|
|
4638
4708
|
}
|
|
4639
4709
|
}
|
|
4640
4710
|
}
|
|
@@ -4808,7 +4878,7 @@ function narrowChannelOverlaps(context) {
|
|
|
4808
4878
|
...input.observedHarnessVersions === void 0 ? {} : { observedHarnessVersions: input.observedHarnessVersions }
|
|
4809
4879
|
});
|
|
4810
4880
|
const staleProviders = found === null ? [] : staleRecordedVersions(found, input.observedVersions);
|
|
4811
|
-
const staleHarnesses = found === null ? [] : staleRecordedHarnessVersions(found, input.observedHarnessVersions ?? {});
|
|
4881
|
+
const staleHarnesses = found === null ? [] : staleRecordedHarnessVersions(found, input.observedHarnessVersions ?? {}, harness);
|
|
4812
4882
|
const stale2 = [...staleProviders, ...staleHarnesses];
|
|
4813
4883
|
const rule = stale2.length > 0 ? null : found;
|
|
4814
4884
|
if (found !== null && stale2.length > 0) {
|
|
@@ -4819,8 +4889,8 @@ function narrowChannelOverlaps(context) {
|
|
|
4819
4889
|
detail: [
|
|
4820
4890
|
`${owners.join(" and ")} both use ${capability} on ${harness}/${toolFamily} at different interception points`,
|
|
4821
4891
|
`Rule ${found.id} was tested at ${[
|
|
4822
|
-
...staleProviders.map((entry) => `${entry.provider} ${entry.recorded}`),
|
|
4823
|
-
...staleHarnesses.map((entry) => `${entry.harness} ${entry.recorded}`)
|
|
4892
|
+
...staleProviders.map((entry) => `${entry.provider} ${entry.recorded ?? "not recorded"}`),
|
|
4893
|
+
...staleHarnesses.map((entry) => `${entry.harness} ${entry.recorded ?? "not recorded"}`)
|
|
4824
4894
|
].join(", ")}`,
|
|
4825
4895
|
`Installed now: ${[
|
|
4826
4896
|
...staleProviders.map((entry) => `${entry.provider} ${entry.observed ?? "unknown"}`),
|
|
@@ -4921,7 +4991,9 @@ function resolveContested(context) {
|
|
|
4921
4991
|
...input.observedHarnessVersions === void 0 ? {} : { observedHarnessVersions: input.observedHarnessVersions }
|
|
4922
4992
|
});
|
|
4923
4993
|
const stale2 = found === null ? [] : staleRecordedVersions(found, input.observedVersions);
|
|
4924
|
-
const
|
|
4994
|
+
const staleHarnesses = found === null ? [] : staleRecordedHarnessVersions(found, input.observedHarnessVersions ?? {}, scope.harness);
|
|
4995
|
+
const staleAll = [...stale2, ...staleHarnesses];
|
|
4996
|
+
const rule = staleAll.length > 0 ? null : found;
|
|
4925
4997
|
if (rule === null) {
|
|
4926
4998
|
if (found !== null) {
|
|
4927
4999
|
conflicts.push({
|
|
@@ -4930,11 +5002,17 @@ function resolveContested(context) {
|
|
|
4930
5002
|
claimants,
|
|
4931
5003
|
detail: [
|
|
4932
5004
|
`${claimants.join(" and ")} both claim ${capability} on ${formatCapabilityScope(scope)}`,
|
|
4933
|
-
`Rule ${found.id} was tested at ${
|
|
4934
|
-
|
|
5005
|
+
`Rule ${found.id} was tested at ${[
|
|
5006
|
+
...stale2.map((entry) => `${entry.provider} ${entry.recorded ?? "not recorded"}`),
|
|
5007
|
+
...staleHarnesses.map((entry) => `${entry.harness} ${entry.recorded ?? "not recorded"}`)
|
|
5008
|
+
].join(", ")}`,
|
|
5009
|
+
`Installed now: ${[
|
|
5010
|
+
...stale2.map((entry) => `${entry.provider} ${entry.observed ?? "unknown"}`),
|
|
5011
|
+
...staleHarnesses.map((entry) => `${entry.harness} ${entry.observed ?? "unknown"}`)
|
|
5012
|
+
].join(", ")}`,
|
|
4935
5013
|
"A compatibility result covers the versions it records, so this one is withdrawn rather than applied outside them"
|
|
4936
5014
|
],
|
|
4937
|
-
remediation: `Re-test ${found.id} against the installed
|
|
5015
|
+
remediation: `Re-test ${found.id} against the installed provider and harness versions, record the evidence for ${scope.harness}, or assign the scope explicitly with \`profile: custom\``
|
|
4938
5016
|
});
|
|
4939
5017
|
return;
|
|
4940
5018
|
}
|
|
@@ -9784,7 +9862,7 @@ var TOOL_VERSION;
|
|
|
9784
9862
|
var init_version2 = __esm({
|
|
9785
9863
|
"apps/cli/dist/src/version.js"() {
|
|
9786
9864
|
"use strict";
|
|
9787
|
-
TOOL_VERSION = "0.1.
|
|
9865
|
+
TOOL_VERSION = "0.1.25";
|
|
9788
9866
|
}
|
|
9789
9867
|
});
|
|
9790
9868
|
|
|
@@ -14138,7 +14216,9 @@ function readHooks(document2) {
|
|
|
14138
14216
|
return [
|
|
14139
14217
|
{
|
|
14140
14218
|
eventName: point.eventName,
|
|
14219
|
+
interceptionPoint: point.scopeId,
|
|
14141
14220
|
matcher: typeof matcher === "string" ? matcher : null,
|
|
14221
|
+
toolFamilies: typeof matcher !== "string" ? MANIFEST.toolFamilies.map((family) => family.id) : MANIFEST.toolFamilies.filter((family) => matcherCoversFamily(matcher, family.id)).map((family) => family.id),
|
|
14142
14222
|
command: hook["command"],
|
|
14143
14223
|
entryPointer,
|
|
14144
14224
|
commandPointer: `${entryPointer}.hooks.${String(hookIndex)}.command`
|
|
@@ -14677,7 +14757,10 @@ var init_claude = __esm({
|
|
|
14677
14757
|
versionCommand: { executable: "claude", args: ["--version"] },
|
|
14678
14758
|
interceptionPoints: [
|
|
14679
14759
|
{ scopeId: "pre-tool-use", eventName: "PreToolUse" },
|
|
14680
|
-
{ scopeId: "post-tool-use", eventName: "PostToolUse" }
|
|
14760
|
+
{ scopeId: "post-tool-use", eventName: "PostToolUse" },
|
|
14761
|
+
{ scopeId: "user-prompt-submit", eventName: "UserPromptSubmit" },
|
|
14762
|
+
{ scopeId: "subagent-start", eventName: "SubagentStart" },
|
|
14763
|
+
{ scopeId: "subagent-stop", eventName: "SubagentStop" }
|
|
14681
14764
|
],
|
|
14682
14765
|
configFiles: [
|
|
14683
14766
|
{
|
|
@@ -14686,7 +14769,13 @@ var init_claude = __esm({
|
|
|
14686
14769
|
parser: "json",
|
|
14687
14770
|
primary: true,
|
|
14688
14771
|
interceptionFormat: "hooks-event-command-list",
|
|
14689
|
-
interceptionPoints: [
|
|
14772
|
+
interceptionPoints: [
|
|
14773
|
+
"pre-tool-use",
|
|
14774
|
+
"post-tool-use",
|
|
14775
|
+
"user-prompt-submit",
|
|
14776
|
+
"subagent-start",
|
|
14777
|
+
"subagent-stop"
|
|
14778
|
+
]
|
|
14690
14779
|
},
|
|
14691
14780
|
{ path: ".claude/settings.json", scope: "project", parser: "json", primary: false },
|
|
14692
14781
|
{ path: ".claude/settings.local.json", scope: "project", parser: "json", primary: false }
|
|
@@ -14874,7 +14963,7 @@ var init_codex_hooks = __esm({
|
|
|
14874
14963
|
function isRecord3(value3) {
|
|
14875
14964
|
return typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
14876
14965
|
}
|
|
14877
|
-
function readHooks2(document2) {
|
|
14966
|
+
function readHooks2(document2, os) {
|
|
14878
14967
|
if (!isRecord3(document2) || !isRecord3(document2["hooks"]))
|
|
14879
14968
|
return { points: [], matchers: [], commands: [], hookCommands: [] };
|
|
14880
14969
|
const hooks = document2["hooks"];
|
|
@@ -14895,15 +14984,21 @@ function readHooks2(document2) {
|
|
|
14895
14984
|
matchers.push(matcher);
|
|
14896
14985
|
if (Array.isArray(entry["hooks"])) {
|
|
14897
14986
|
for (const [hookIndex, hook] of entry["hooks"].entries()) {
|
|
14898
|
-
if (isRecord3(hook)
|
|
14899
|
-
|
|
14987
|
+
if (!isRecord3(hook))
|
|
14988
|
+
continue;
|
|
14989
|
+
const commandKey = os === "windows" && typeof hook["commandWindows"] === "string" ? "commandWindows" : "command";
|
|
14990
|
+
const command = hook[commandKey];
|
|
14991
|
+
if (typeof command === "string") {
|
|
14992
|
+
commands.push(command);
|
|
14900
14993
|
const entryPointer = `hooks.${point.eventName}.${String(entryIndex)}`;
|
|
14901
14994
|
hookCommands.push({
|
|
14902
14995
|
eventName: point.eventName,
|
|
14996
|
+
interceptionPoint: point.scopeId,
|
|
14903
14997
|
matcher,
|
|
14904
|
-
|
|
14998
|
+
toolFamilies: matcher === null ? MANIFEST2.toolFamilies.map((family) => family.id) : MANIFEST2.toolFamilies.filter((family) => matcherCoversFamily(matcher, family.id)).map((family) => family.id),
|
|
14999
|
+
command,
|
|
14905
15000
|
entryPointer,
|
|
14906
|
-
commandPointer: `${entryPointer}.hooks.${String(hookIndex)}
|
|
15001
|
+
commandPointer: `${entryPointer}.hooks.${String(hookIndex)}.${commandKey}`
|
|
14907
15002
|
});
|
|
14908
15003
|
carries = true;
|
|
14909
15004
|
}
|
|
@@ -14948,7 +15043,7 @@ async function resolveConfig2(declaration, context) {
|
|
|
14948
15043
|
};
|
|
14949
15044
|
}
|
|
14950
15045
|
try {
|
|
14951
|
-
const hooks = readHooks2(JSON.parse(text3));
|
|
15046
|
+
const hooks = readHooks2(JSON.parse(text3), context.facts.os);
|
|
14952
15047
|
return {
|
|
14953
15048
|
declaration,
|
|
14954
15049
|
path,
|
|
@@ -15854,7 +15949,10 @@ var init_codex = __esm({
|
|
|
15854
15949
|
*/
|
|
15855
15950
|
interceptionPoints: [
|
|
15856
15951
|
{ scopeId: "pre-tool-use", eventName: "PreToolUse" },
|
|
15857
|
-
{ scopeId: "post-tool-use", eventName: "PostToolUse" }
|
|
15952
|
+
{ scopeId: "post-tool-use", eventName: "PostToolUse" },
|
|
15953
|
+
{ scopeId: "user-prompt-submit", eventName: "UserPromptSubmit" },
|
|
15954
|
+
{ scopeId: "subagent-start", eventName: "SubagentStart" },
|
|
15955
|
+
{ scopeId: "subagent-stop", eventName: "SubagentStop" }
|
|
15858
15956
|
],
|
|
15859
15957
|
configFiles: [
|
|
15860
15958
|
{ path: ".codex/config.toml", scope: "user", parser: "toml", primary: true },
|
|
@@ -15864,7 +15962,13 @@ var init_codex = __esm({
|
|
|
15864
15962
|
parser: "json",
|
|
15865
15963
|
primary: false,
|
|
15866
15964
|
interceptionFormat: "hooks-event-command-list",
|
|
15867
|
-
interceptionPoints: [
|
|
15965
|
+
interceptionPoints: [
|
|
15966
|
+
"pre-tool-use",
|
|
15967
|
+
"post-tool-use",
|
|
15968
|
+
"user-prompt-submit",
|
|
15969
|
+
"subagent-start",
|
|
15970
|
+
"subagent-stop"
|
|
15971
|
+
]
|
|
15868
15972
|
}
|
|
15869
15973
|
],
|
|
15870
15974
|
toolFamilies: [
|
|
@@ -16632,10 +16736,49 @@ var init_pi = __esm({
|
|
|
16632
16736
|
}
|
|
16633
16737
|
});
|
|
16634
16738
|
|
|
16739
|
+
// packages/adapters/dist/src/harnesses/native-prompt-routing.js
|
|
16740
|
+
function nativePromptRoutingHookEntries(harness, executable = "token-harness") {
|
|
16741
|
+
return NATIVE_PROMPT_ROUTING_EVENTS.map(({ eventName, commandEvent }) => {
|
|
16742
|
+
if (harness === "codex") {
|
|
16743
|
+
const command = `${executable} __internal-prompt-router codex ${commandEvent}`;
|
|
16744
|
+
const handler2 = {
|
|
16745
|
+
type: "command",
|
|
16746
|
+
command,
|
|
16747
|
+
commandWindows: command,
|
|
16748
|
+
timeout: 10
|
|
16749
|
+
};
|
|
16750
|
+
if (commandEvent === "prompt-submit")
|
|
16751
|
+
handler2["additionalContextLimit"] = 500;
|
|
16752
|
+
return { eventName, value: { hooks: [handler2] } };
|
|
16753
|
+
}
|
|
16754
|
+
const handler = {
|
|
16755
|
+
type: "command",
|
|
16756
|
+
command: executable,
|
|
16757
|
+
args: ["__internal-prompt-router", "claude", commandEvent],
|
|
16758
|
+
timeout: 10
|
|
16759
|
+
};
|
|
16760
|
+
return { eventName, value: { hooks: [handler] } };
|
|
16761
|
+
});
|
|
16762
|
+
}
|
|
16763
|
+
var NATIVE_PROMPT_ROUTING_EVENTS;
|
|
16764
|
+
var init_native_prompt_routing = __esm({
|
|
16765
|
+
"packages/adapters/dist/src/harnesses/native-prompt-routing.js"() {
|
|
16766
|
+
"use strict";
|
|
16767
|
+
NATIVE_PROMPT_ROUTING_EVENTS = [
|
|
16768
|
+
{ eventName: "UserPromptSubmit", commandEvent: "prompt-submit" },
|
|
16769
|
+
{ eventName: "SubagentStart", commandEvent: "subagent-start" },
|
|
16770
|
+
{ eventName: "SubagentStop", commandEvent: "subagent-stop" }
|
|
16771
|
+
];
|
|
16772
|
+
}
|
|
16773
|
+
});
|
|
16774
|
+
|
|
16635
16775
|
// packages/adapters/dist/src/harnesses/index.js
|
|
16636
16776
|
function listHarnessAdapters() {
|
|
16637
16777
|
return HARNESS_ADAPTERS;
|
|
16638
16778
|
}
|
|
16779
|
+
function findHarnessAdapter(id) {
|
|
16780
|
+
return HARNESS_ADAPTERS.find((adapter) => adapter.manifest.id === id) ?? null;
|
|
16781
|
+
}
|
|
16639
16782
|
var HARNESS_ADAPTERS;
|
|
16640
16783
|
var init_harnesses = __esm({
|
|
16641
16784
|
"packages/adapters/dist/src/harnesses/index.js"() {
|
|
@@ -16653,6 +16796,7 @@ var init_harnesses = __esm({
|
|
|
16653
16796
|
init_opencode();
|
|
16654
16797
|
init_pi();
|
|
16655
16798
|
init_claude();
|
|
16799
|
+
init_native_prompt_routing();
|
|
16656
16800
|
HARNESS_ADAPTERS = [
|
|
16657
16801
|
claudeAdapter,
|
|
16658
16802
|
codexAdapter,
|
|
@@ -17702,11 +17846,11 @@ async function plan(context, request) {
|
|
|
17702
17846
|
}));
|
|
17703
17847
|
continue;
|
|
17704
17848
|
}
|
|
17705
|
-
const
|
|
17849
|
+
const actionId2 = `harnesstrim-${harness.id}-hook-${digestText(target.configPath).slice(7, 15)}`;
|
|
17706
17850
|
actions.push(appendCommandHookAction({
|
|
17707
17851
|
target,
|
|
17708
17852
|
providerId: HARNESSTRIM2,
|
|
17709
|
-
actionId,
|
|
17853
|
+
actionId: actionId2,
|
|
17710
17854
|
command,
|
|
17711
17855
|
explanation: `Register HarnessTrim after ${harness.displayName} Bash commands and record reductions in ${metricsPath}${codexActivationNote(harness.id)}`
|
|
17712
17856
|
}));
|
|
@@ -18214,7 +18358,7 @@ function installAction(context, manifest) {
|
|
|
18214
18358
|
packageName: channel.packageId ?? "rtk",
|
|
18215
18359
|
// The managed Codex hook first exists in this RTK release. Pinning makes a fresh setup's
|
|
18216
18360
|
// promised surface deterministic instead of installing an older prompt-only build.
|
|
18217
|
-
version: "0.
|
|
18361
|
+
version: "0.51.0"
|
|
18218
18362
|
};
|
|
18219
18363
|
}
|
|
18220
18364
|
function buildRtkPlan(input) {
|
|
@@ -18393,9 +18537,15 @@ async function readHarnessActivity(context, harness) {
|
|
|
18393
18537
|
failure: null
|
|
18394
18538
|
};
|
|
18395
18539
|
}
|
|
18540
|
+
function supportsCodexHook(version3) {
|
|
18541
|
+
if (version3 === null)
|
|
18542
|
+
return false;
|
|
18543
|
+
const parsed = parseSemanticVersion(version3);
|
|
18544
|
+
const minimum = parseSemanticVersion(RTK_CODEX_HOOK_MINIMUM_VERSION);
|
|
18545
|
+
return parsed !== null && minimum !== null && compareVersions(parsed, minimum) >= 0;
|
|
18546
|
+
}
|
|
18396
18547
|
function hasAttributionHook(context, harness) {
|
|
18397
|
-
|
|
18398
|
-
return context.harnessConfigs.some((config) => config.harnessId === harness && config.commands.some((entry) => command.test(entry.trim())));
|
|
18548
|
+
return context.harnessConfigs.some((config) => config.harnessId === harness && config.commands.some((entry) => tokenHarnessRtkHookHarness(entry) === harness));
|
|
18399
18549
|
}
|
|
18400
18550
|
async function detect7(context) {
|
|
18401
18551
|
const evidenceItems = [];
|
|
@@ -18419,7 +18569,7 @@ async function detect7(context) {
|
|
|
18419
18569
|
remediation: "Check the release notes for analytics or hook changes before applying a plan"
|
|
18420
18570
|
}));
|
|
18421
18571
|
}
|
|
18422
|
-
const codexHookSupported = version3.version
|
|
18572
|
+
const codexHookSupported = supportsCodexHook(version3.version);
|
|
18423
18573
|
const codexConfiguredWithoutHookSupport = configured.includes(CODEX4) && !codexHookSupported;
|
|
18424
18574
|
if (codexConfiguredWithoutHookSupport) {
|
|
18425
18575
|
warnings.push(diagnostic({
|
|
@@ -18427,7 +18577,7 @@ async function detect7(context) {
|
|
|
18427
18577
|
code: "rtk-codex-hook-unsupported",
|
|
18428
18578
|
subject: CODEX4,
|
|
18429
18579
|
message: `RTK ${String(version3.version)} does not provide the Codex hook; its configuration entry cannot capture commands`,
|
|
18430
|
-
remediation: `Upgrade RTK to ${
|
|
18580
|
+
remediation: `Upgrade RTK to ${RTK_CODEX_HOOK_MINIMUM_VERSION}, then refresh and apply the attribution plan`
|
|
18431
18581
|
}));
|
|
18432
18582
|
}
|
|
18433
18583
|
const state = version3.version === null ? configured.length > 0 ? "broken" : "absent" : codexConfiguredWithoutHookSupport && configured.length === 1 ? "broken" : configured.length > 0 ? "configured" : "installed";
|
|
@@ -18493,14 +18643,14 @@ async function verify7(context) {
|
|
|
18493
18643
|
remediation: version3.version === null ? "Install RTK, or add it to PATH" : null
|
|
18494
18644
|
});
|
|
18495
18645
|
const configured = harnessesWiredToRtk(context.harnessConfigs);
|
|
18496
|
-
const configuredSupported = configured.filter((harness) => harness === CLAUDE5 || harness === CODEX4 && version3.version
|
|
18646
|
+
const configuredSupported = configured.filter((harness) => harness === CLAUDE5 || harness === CODEX4 && supportsCodexHook(version3.version));
|
|
18497
18647
|
checks.push({
|
|
18498
18648
|
id: "hook-registered",
|
|
18499
18649
|
status: configuredSupported.length > 0 ? "pass" : configured.length > 0 ? "fail" : "not-exercised",
|
|
18500
18650
|
summary: configuredSupported.length > 0 ? `wired to ${configuredSupported.join(", ")}` : configured.length > 0 ? `RTK ${String(version3.version)} cannot run its Codex hook` : "no harness configuration names rtk",
|
|
18501
18651
|
achievedTier: configuredSupported.length > 0 ? "config-only" : null,
|
|
18502
18652
|
evidence: [],
|
|
18503
|
-
remediation: configured.length > 0 && configuredSupported.length === 0 ? `Upgrade RTK to ${
|
|
18653
|
+
remediation: configured.length > 0 && configuredSupported.length === 0 ? `Upgrade RTK to ${RTK_CODEX_HOOK_MINIMUM_VERSION} for Codex hook support` : null
|
|
18504
18654
|
});
|
|
18505
18655
|
let receipt = null;
|
|
18506
18656
|
let bestReceiptTime = Number.NEGATIVE_INFINITY;
|
|
@@ -18508,7 +18658,7 @@ async function verify7(context) {
|
|
|
18508
18658
|
if (!configured.includes(harness))
|
|
18509
18659
|
continue;
|
|
18510
18660
|
const label = harness === CLAUDE5 ? "Claude Code" : "Codex";
|
|
18511
|
-
const supported = harness !== CODEX4 || version3.version
|
|
18661
|
+
const supported = harness !== CODEX4 || supportsCodexHook(version3.version);
|
|
18512
18662
|
if (!supported) {
|
|
18513
18663
|
checks.push({
|
|
18514
18664
|
id: `rtk-attribution-${harness}`,
|
|
@@ -18516,7 +18666,7 @@ async function verify7(context) {
|
|
|
18516
18666
|
summary: `RTK ${String(version3.version)} does not provide an active ${label} hook`,
|
|
18517
18667
|
achievedTier: null,
|
|
18518
18668
|
evidence: [],
|
|
18519
|
-
remediation: `Upgrade RTK to ${
|
|
18669
|
+
remediation: `Upgrade RTK to ${RTK_CODEX_HOOK_MINIMUM_VERSION}, then refresh and apply the tracking update`
|
|
18520
18670
|
});
|
|
18521
18671
|
continue;
|
|
18522
18672
|
}
|
|
@@ -18911,7 +19061,20 @@ async function importHistorySource(context, store, path, attributedHarness) {
|
|
|
18911
19061
|
};
|
|
18912
19062
|
}
|
|
18913
19063
|
function identifiesCommand2(command) {
|
|
18914
|
-
return HOOK_COMMAND_PATTERN2.test(command) || PLUGIN_MODULE_PATTERN3.test(command) ||
|
|
19064
|
+
return HOOK_COMMAND_PATTERN2.test(command) || PLUGIN_MODULE_PATTERN3.test(command) || tokenHarnessRtkHookHarness(command) !== null;
|
|
19065
|
+
}
|
|
19066
|
+
function tokenHarnessRtkHookHarness(command) {
|
|
19067
|
+
const match = /^\s*(?:"([^"]+)"|'([^']+)'|(\S+))\s+__internal-rtk-hook\s+(claude|codex)(?:\s+--restore-rtk)?\s*$/i.exec(command);
|
|
19068
|
+
if (match === null)
|
|
19069
|
+
return null;
|
|
19070
|
+
const executable = match[1] ?? match[2] ?? match[3];
|
|
19071
|
+
if (executable === void 0)
|
|
19072
|
+
return null;
|
|
19073
|
+
const basename = executable.split(/[\\/]/).at(-1);
|
|
19074
|
+
if (basename === void 0 || !/^token-harness(?:\.cmd|\.exe)?$/i.test(basename)) {
|
|
19075
|
+
return null;
|
|
19076
|
+
}
|
|
19077
|
+
return harnessId((match[4] ?? "").toLowerCase());
|
|
18915
19078
|
}
|
|
18916
19079
|
async function plan2(context, request) {
|
|
18917
19080
|
const version3 = await readVersion(context);
|
|
@@ -18935,7 +19098,7 @@ async function plan2(context, request) {
|
|
|
18935
19098
|
hookProxyAvailable
|
|
18936
19099
|
});
|
|
18937
19100
|
}
|
|
18938
|
-
var RTK2, CLAUDE5, CODEX4, OPENCODE3, TRACKED_HARNESSES,
|
|
19101
|
+
var RTK2, CLAUDE5, CODEX4, OPENCODE3, TRACKED_HARNESSES, RTK_CODEX_HOOK_MINIMUM_VERSION, MANIFEST7, TESTED_VERSIONS2, VERSION_PATTERN7, HOOK_COMMAND_PATTERN2, PLUGIN_MODULE_PATTERN3, HARNESS_ACTIVITY_QUERY, STALE_RECEIPT_DAYS, HISTORY_QUERY, GENERATION_QUERY, IMPORT_BATCH_SIZE, SOURCE_LABEL, rtkAdapter;
|
|
18939
19102
|
var init_rtk = __esm({
|
|
18940
19103
|
"packages/adapters/dist/src/providers/rtk.js"() {
|
|
18941
19104
|
"use strict";
|
|
@@ -18946,7 +19109,7 @@ var init_rtk = __esm({
|
|
|
18946
19109
|
CODEX4 = harnessId("codex");
|
|
18947
19110
|
OPENCODE3 = harnessId("opencode");
|
|
18948
19111
|
TRACKED_HARNESSES = [CLAUDE5, CODEX4];
|
|
18949
|
-
|
|
19112
|
+
RTK_CODEX_HOOK_MINIMUM_VERSION = "0.50.0";
|
|
18950
19113
|
MANIFEST7 = {
|
|
18951
19114
|
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
18952
19115
|
id: RTK2,
|
|
@@ -19126,7 +19289,7 @@ var init_rtk = __esm({
|
|
|
19126
19289
|
},
|
|
19127
19290
|
delegatedInstallReviews: null
|
|
19128
19291
|
};
|
|
19129
|
-
TESTED_VERSIONS2 = { minimum: "0.44.0", maximum: "0.
|
|
19292
|
+
TESTED_VERSIONS2 = { minimum: "0.44.0", maximum: "0.51.0" };
|
|
19130
19293
|
VERSION_PATTERN7 = /(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/;
|
|
19131
19294
|
HOOK_COMMAND_PATTERN2 = /(^|[\\/\s"'])rtk(\.exe)?([\s"']|$)/i;
|
|
19132
19295
|
PLUGIN_MODULE_PATTERN3 = /(^|[\\/])rtk\.(ts|js|mjs|cjs|mts|cts)$/i;
|
|
@@ -21806,7 +21969,7 @@ var init_version_compatibility = __esm({
|
|
|
21806
21969
|
GITNEXUS2 = providerId("gitnexus");
|
|
21807
21970
|
HEADROOM3 = providerId("headroom");
|
|
21808
21971
|
PACKAGE_UPDATE_BASELINES = /* @__PURE__ */ new Map([
|
|
21809
|
-
[RTK3, { minimum: "0.44.0", maximum: "0.
|
|
21972
|
+
[RTK3, { minimum: "0.44.0", maximum: "0.51.0" }],
|
|
21810
21973
|
[HARNESSTRIM3, { minimum: "0.0.5", maximum: "0.3.1" }],
|
|
21811
21974
|
[
|
|
21812
21975
|
MCPTOON2,
|
|
@@ -22453,6 +22616,8 @@ function parseArgv(argv2, plannedCommands = PLANNED_COMMANDS) {
|
|
|
22453
22616
|
contextSnapshot: null,
|
|
22454
22617
|
nativePolicy: false,
|
|
22455
22618
|
agentSkill: false,
|
|
22619
|
+
agentRouting: false,
|
|
22620
|
+
disableAgentRouting: false,
|
|
22456
22621
|
verbose: false,
|
|
22457
22622
|
yes: false
|
|
22458
22623
|
};
|
|
@@ -22491,6 +22656,10 @@ function parseArgv(argv2, plannedCommands = PLANNED_COMMANDS) {
|
|
|
22491
22656
|
options.nativePolicy = true;
|
|
22492
22657
|
if (name2 === "--agent-skill")
|
|
22493
22658
|
options.agentSkill = true;
|
|
22659
|
+
if (name2 === "--agent-routing")
|
|
22660
|
+
options.agentRouting = true;
|
|
22661
|
+
if (name2 === "--disable-agent-routing")
|
|
22662
|
+
options.disableAgentRouting = true;
|
|
22494
22663
|
if (name2 === "--verbose")
|
|
22495
22664
|
options.verbose = true;
|
|
22496
22665
|
continue;
|
|
@@ -22727,6 +22896,14 @@ function parseArgv(argv2, plannedCommands = PLANNED_COMMANDS) {
|
|
|
22727
22896
|
}));
|
|
22728
22897
|
return usageError(json, diagnostics);
|
|
22729
22898
|
}
|
|
22899
|
+
if (options.agentRouting && options.disableAgentRouting) {
|
|
22900
|
+
diagnostics.push(diagnostic({
|
|
22901
|
+
severity: "error",
|
|
22902
|
+
code: "conflicting-prompt-routing-flags",
|
|
22903
|
+
message: "--agent-routing and --disable-agent-routing cannot be used together",
|
|
22904
|
+
remediation: "Choose one prompt-routing state to plan"
|
|
22905
|
+
}));
|
|
22906
|
+
}
|
|
22730
22907
|
if (!isAvailableCommand(command)) {
|
|
22731
22908
|
const planned = plannedCommands.includes(command);
|
|
22732
22909
|
diagnostics.push(planned ? diagnostic({
|
|
@@ -22796,7 +22973,557 @@ var init_argv = __esm({
|
|
|
22796
22973
|
"--tasks-left",
|
|
22797
22974
|
"--context-snapshot"
|
|
22798
22975
|
]);
|
|
22799
|
-
BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
22976
|
+
BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
22977
|
+
"--json",
|
|
22978
|
+
"--native-policy",
|
|
22979
|
+
"--agent-skill",
|
|
22980
|
+
"--agent-routing",
|
|
22981
|
+
"--disable-agent-routing",
|
|
22982
|
+
"--verbose",
|
|
22983
|
+
"--yes"
|
|
22984
|
+
]);
|
|
22985
|
+
}
|
|
22986
|
+
});
|
|
22987
|
+
|
|
22988
|
+
// apps/cli/dist/src/prompt-router.js
|
|
22989
|
+
function isHarness(value3) {
|
|
22990
|
+
return value3 === "claude" || value3 === "codex";
|
|
22991
|
+
}
|
|
22992
|
+
function expectedVersions(harness) {
|
|
22993
|
+
return harness === "codex" ? ["0.159.0", "0.160.0"] : ["2.1.274", "2.1.288"];
|
|
22994
|
+
}
|
|
22995
|
+
function configTarget(input) {
|
|
22996
|
+
if (!isHarness(input.harness) || input.home === null)
|
|
22997
|
+
return null;
|
|
22998
|
+
const adapter = findHarnessAdapter(harnessId(input.harness));
|
|
22999
|
+
const declaration = adapter?.manifest.configFiles.find((file) => file.scope === "user" && file.parser === "json" && file.interceptionPoints?.includes("user-prompt-submit") === true);
|
|
23000
|
+
if (declaration === void 0 || adapter === null)
|
|
23001
|
+
return null;
|
|
23002
|
+
const fileContext = {
|
|
23003
|
+
fs: input.fs,
|
|
23004
|
+
runner: input.runner,
|
|
23005
|
+
facts: input.facts,
|
|
23006
|
+
paths: { ...input.paths, home: input.home },
|
|
23007
|
+
projectRoot: input.projectRoot
|
|
23008
|
+
};
|
|
23009
|
+
return {
|
|
23010
|
+
harness: input.harness,
|
|
23011
|
+
path: resolveConfigPath(declaration, fileContext),
|
|
23012
|
+
version: input.version,
|
|
23013
|
+
fileContext
|
|
23014
|
+
};
|
|
23015
|
+
}
|
|
23016
|
+
function hookEntries(harness) {
|
|
23017
|
+
return nativePromptRoutingHookEntries(harnessId(harness), "token-harness");
|
|
23018
|
+
}
|
|
23019
|
+
function asRecord(value3) {
|
|
23020
|
+
return typeof value3 === "object" && value3 !== null && !Array.isArray(value3) ? value3 : null;
|
|
23021
|
+
}
|
|
23022
|
+
function parseHookDocument(text3) {
|
|
23023
|
+
let decoded;
|
|
23024
|
+
try {
|
|
23025
|
+
decoded = JSON.parse(text3);
|
|
23026
|
+
} catch {
|
|
23027
|
+
return { ok: false, reason: "The hook settings file is malformed JSON or contains comments." };
|
|
23028
|
+
}
|
|
23029
|
+
const root = asRecord(decoded);
|
|
23030
|
+
if (root === null)
|
|
23031
|
+
return { ok: false, reason: "The hook settings root must be a JSON object." };
|
|
23032
|
+
const hooksValue = root["hooks"];
|
|
23033
|
+
if (hooksValue === void 0)
|
|
23034
|
+
return { ok: true, hooks: {} };
|
|
23035
|
+
const hooks = asRecord(hooksValue);
|
|
23036
|
+
if (hooks === null)
|
|
23037
|
+
return { ok: false, reason: "The settings hooks property must be an object." };
|
|
23038
|
+
for (const { eventName } of hookEntries("codex")) {
|
|
23039
|
+
const entries = hooks[eventName];
|
|
23040
|
+
if (entries !== void 0 && !Array.isArray(entries))
|
|
23041
|
+
return { ok: false, reason: `The ${eventName} hook property must be an array.` };
|
|
23042
|
+
}
|
|
23043
|
+
return { ok: true, hooks };
|
|
23044
|
+
}
|
|
23045
|
+
function containsRouterCommand(value3, harness) {
|
|
23046
|
+
const row2 = asRecord(value3);
|
|
23047
|
+
const hooks = row2?.["hooks"];
|
|
23048
|
+
if (!Array.isArray(hooks))
|
|
23049
|
+
return false;
|
|
23050
|
+
return hooks.some((hook) => {
|
|
23051
|
+
const handler = asRecord(hook);
|
|
23052
|
+
if (handler === null)
|
|
23053
|
+
return false;
|
|
23054
|
+
if (harness === "codex")
|
|
23055
|
+
return [handler["command"], handler["commandWindows"]].some((command) => typeof command === "string" && command.includes(ROUTE_MARKER));
|
|
23056
|
+
const args = handler["args"];
|
|
23057
|
+
return handler["command"] === "token-harness" && Array.isArray(args) && args[0] === ROUTE_MARKER;
|
|
23058
|
+
});
|
|
23059
|
+
}
|
|
23060
|
+
function configHasExactRouter(hooks, harness) {
|
|
23061
|
+
let exactCount = 0;
|
|
23062
|
+
let routeCount = 0;
|
|
23063
|
+
for (const expected of hookEntries(harness)) {
|
|
23064
|
+
const live = hooks[expected.eventName];
|
|
23065
|
+
const entries = Array.isArray(live) ? live : [];
|
|
23066
|
+
const routeEntries = entries.filter((entry) => containsRouterCommand(entry, harness));
|
|
23067
|
+
routeCount += routeEntries.length;
|
|
23068
|
+
if (routeEntries.some((entry) => jsonValueDigest(entry) === jsonValueDigest(expected.value)))
|
|
23069
|
+
exactCount += 1;
|
|
23070
|
+
}
|
|
23071
|
+
return {
|
|
23072
|
+
complete: exactCount === hookEntries(harness).length,
|
|
23073
|
+
partial: routeCount > 0 && exactCount !== hookEntries(harness).length,
|
|
23074
|
+
conflict: routeCount > exactCount
|
|
23075
|
+
};
|
|
23076
|
+
}
|
|
23077
|
+
function routerOwnedArtifacts(journals, path, harness) {
|
|
23078
|
+
const expected = hookEntries(harness);
|
|
23079
|
+
for (const journal of journals) {
|
|
23080
|
+
const disabledHere = journal.entries.some((entry) => entry.actionId.startsWith(`native-prompt-routing:${harness}:disable:`) && entry.snapshots.some((snapshot) => snapshot.path === path));
|
|
23081
|
+
if (disabledHere && journal.outcome === "committed")
|
|
23082
|
+
return [];
|
|
23083
|
+
const relevant = journal.ownership.filter((artifact) => artifact.kind === "owned-json-entry" && artifact.path === path && artifact.placement === "array-element" && expected.some((entry) => artifact.pointer === `hooks.${entry.eventName}` && artifact.valueDigest === jsonValueDigest(entry.value)));
|
|
23084
|
+
if (relevant.length > 0)
|
|
23085
|
+
return journal.outcome === "committed" ? relevant : [];
|
|
23086
|
+
}
|
|
23087
|
+
return [];
|
|
23088
|
+
}
|
|
23089
|
+
async function journalsFor(input) {
|
|
23090
|
+
if (input.stateRoot === null)
|
|
23091
|
+
return [];
|
|
23092
|
+
const journalRoot = input.fs.join(input.stateRoot, "journals");
|
|
23093
|
+
if ((await input.fs.stat(journalRoot))?.kind !== "directory")
|
|
23094
|
+
return [];
|
|
23095
|
+
return new FileJournalStore({
|
|
23096
|
+
fs: input.fs,
|
|
23097
|
+
journalRoot,
|
|
23098
|
+
backupRoot: input.fs.join(input.stateRoot, "backups")
|
|
23099
|
+
}).list();
|
|
23100
|
+
}
|
|
23101
|
+
function actionId(harness, intent, eventName) {
|
|
23102
|
+
return `native-prompt-routing:${harness}:${intent}:${eventName}`;
|
|
23103
|
+
}
|
|
23104
|
+
async function planNativePromptRoutingInstall(input) {
|
|
23105
|
+
const diagnostics = [];
|
|
23106
|
+
const target = configTarget(input);
|
|
23107
|
+
if (target === null) {
|
|
23108
|
+
diagnostics.push(diagnostic({
|
|
23109
|
+
severity: "warning",
|
|
23110
|
+
code: "prompt-routing-target-unavailable",
|
|
23111
|
+
subject: input.harness,
|
|
23112
|
+
message: "No supported user-scope native prompt hook target is available",
|
|
23113
|
+
remediation: "Resolve the user home and harness installation, then refresh Token Harness"
|
|
23114
|
+
}));
|
|
23115
|
+
return { target: null, actions: [], diagnostics };
|
|
23116
|
+
}
|
|
23117
|
+
if (!expectedVersions(target.harness).includes(target.version ?? "")) {
|
|
23118
|
+
diagnostics.push(diagnostic({
|
|
23119
|
+
severity: "warning",
|
|
23120
|
+
code: "prompt-routing-version-unverified",
|
|
23121
|
+
subject: target.harness,
|
|
23122
|
+
message: `Native prompt routing has no hook fixture for ${target.harness} ${target.version ?? "unknown"}`,
|
|
23123
|
+
path: target.path,
|
|
23124
|
+
remediation: "Refresh Token Harness after the installed harness hook schema is fixture-tested"
|
|
23125
|
+
}));
|
|
23126
|
+
return { target: target.path, actions: [], diagnostics };
|
|
23127
|
+
}
|
|
23128
|
+
const runtimeCheck = await input.runner.run({
|
|
23129
|
+
executable: "token-harness",
|
|
23130
|
+
args: ["__internal-prompt-router", target.harness, "--check"],
|
|
23131
|
+
cwd: input.projectRoot,
|
|
23132
|
+
timeoutMs: 3e3,
|
|
23133
|
+
maxOutputBytes: 256
|
|
23134
|
+
});
|
|
23135
|
+
if (runtimeCheck.failure !== null || runtimeCheck.exitCode !== 0 || runtimeCheck.stdout.trim() !== PROMPT_ROUTER_CHECK_MARKER) {
|
|
23136
|
+
diagnostics.push(diagnostic({
|
|
23137
|
+
severity: "error",
|
|
23138
|
+
code: "prompt-routing-runtime-unavailable",
|
|
23139
|
+
subject: target.harness,
|
|
23140
|
+
message: "The Token Harness executable found on PATH cannot serve the native prompt hook",
|
|
23141
|
+
path: target.path,
|
|
23142
|
+
remediation: "Install or update Token Harness so the same executable is available to the coding agent, then refresh and plan again"
|
|
23143
|
+
}));
|
|
23144
|
+
return { target: target.path, actions: [], diagnostics };
|
|
23145
|
+
}
|
|
23146
|
+
const stat3 = await input.fs.stat(target.path);
|
|
23147
|
+
if (stat3 !== null && stat3.kind !== "file") {
|
|
23148
|
+
diagnostics.push(diagnostic({
|
|
23149
|
+
severity: "error",
|
|
23150
|
+
code: "prompt-routing-target-not-file",
|
|
23151
|
+
subject: target.harness,
|
|
23152
|
+
message: "A non-file occupies the native hook settings path",
|
|
23153
|
+
path: target.path,
|
|
23154
|
+
remediation: "Move the conflicting path and refresh Token Harness"
|
|
23155
|
+
}));
|
|
23156
|
+
return { target: target.path, actions: [], diagnostics };
|
|
23157
|
+
}
|
|
23158
|
+
let hooks = {};
|
|
23159
|
+
if (stat3 !== null) {
|
|
23160
|
+
const parsed = parseHookDocument(DECODER4.decode(await input.fs.readFile(target.path)));
|
|
23161
|
+
if (!parsed.ok) {
|
|
23162
|
+
diagnostics.push(diagnostic({
|
|
23163
|
+
severity: "error",
|
|
23164
|
+
code: "prompt-routing-settings-unmergeable",
|
|
23165
|
+
subject: target.harness,
|
|
23166
|
+
message: parsed.reason,
|
|
23167
|
+
path: target.path,
|
|
23168
|
+
remediation: "Repair the JSON settings file or configure native prompt routing manually"
|
|
23169
|
+
}));
|
|
23170
|
+
return { target: target.path, actions: [], diagnostics };
|
|
23171
|
+
}
|
|
23172
|
+
hooks = parsed.hooks;
|
|
23173
|
+
}
|
|
23174
|
+
const existing = configHasExactRouter(hooks, target.harness);
|
|
23175
|
+
if (existing.complete) {
|
|
23176
|
+
diagnostics.push(diagnostic({
|
|
23177
|
+
severity: "info",
|
|
23178
|
+
code: "prompt-routing-already-configured",
|
|
23179
|
+
subject: target.harness,
|
|
23180
|
+
message: "Native prompt routing hooks are already present; no settings are changed",
|
|
23181
|
+
path: target.path,
|
|
23182
|
+
remediation: null
|
|
23183
|
+
}));
|
|
23184
|
+
return { target: target.path, actions: [], diagnostics };
|
|
23185
|
+
}
|
|
23186
|
+
if (existing.partial || existing.conflict) {
|
|
23187
|
+
diagnostics.push(diagnostic({
|
|
23188
|
+
severity: "error",
|
|
23189
|
+
code: "prompt-routing-existing-hook-conflict",
|
|
23190
|
+
subject: target.harness,
|
|
23191
|
+
message: "A partial or modified Token Harness prompt hook already exists and was left untouched",
|
|
23192
|
+
path: target.path,
|
|
23193
|
+
remediation: "Review the existing native routing entries before planning another change"
|
|
23194
|
+
}));
|
|
23195
|
+
return { target: target.path, actions: [], diagnostics };
|
|
23196
|
+
}
|
|
23197
|
+
const entries = hookEntries(target.harness);
|
|
23198
|
+
const action = {
|
|
23199
|
+
kind: "merge-json",
|
|
23200
|
+
id: actionId(target.harness, "enable", "all"),
|
|
23201
|
+
riskClass: "reversible",
|
|
23202
|
+
requiresNetwork: false,
|
|
23203
|
+
requiresElevation: false,
|
|
23204
|
+
affectedPaths: [target.path],
|
|
23205
|
+
affectedProcesses: [target.harness],
|
|
23206
|
+
preconditions: [
|
|
23207
|
+
"the harness hook settings remain absent or valid JSON",
|
|
23208
|
+
"no Token Harness native prompt-routing hooks are already present"
|
|
23209
|
+
],
|
|
23210
|
+
postconditions: entries.map((entry) => `${entry.eventName} has one Token Harness-owned hook`),
|
|
23211
|
+
rollbackData: "file-snapshot",
|
|
23212
|
+
explanation: `Enable automatic native prompt routing for ${target.harness}` + (target.harness === "codex" ? "; manually enable and trust this hook in Codex after applying" : "; start a new Claude Code session after applying"),
|
|
23213
|
+
path: target.path,
|
|
23214
|
+
ownedPointers: entries.map((entry) => `hooks.${entry.eventName}`),
|
|
23215
|
+
operations: entries.map((entry) => ({
|
|
23216
|
+
kind: "append",
|
|
23217
|
+
pointer: `hooks.${entry.eventName}`,
|
|
23218
|
+
value: entry.value,
|
|
23219
|
+
expectedValueDigest: null
|
|
23220
|
+
})),
|
|
23221
|
+
createIfMissing: true
|
|
23222
|
+
};
|
|
23223
|
+
return { target: target.path, actions: [action], diagnostics };
|
|
23224
|
+
}
|
|
23225
|
+
async function planNativePromptRoutingRemoval(input) {
|
|
23226
|
+
const diagnostics = [];
|
|
23227
|
+
const target = configTarget(input);
|
|
23228
|
+
if (target === null || input.stateRoot === null) {
|
|
23229
|
+
diagnostics.push(diagnostic({
|
|
23230
|
+
severity: "warning",
|
|
23231
|
+
code: "prompt-routing-removal-unavailable",
|
|
23232
|
+
subject: input.harness,
|
|
23233
|
+
message: "The owned native prompt-routing configuration could not be located safely",
|
|
23234
|
+
remediation: "Refresh Token Harness from the signed-in user environment"
|
|
23235
|
+
}));
|
|
23236
|
+
return { target: target?.path ?? null, actions: [], diagnostics };
|
|
23237
|
+
}
|
|
23238
|
+
const expected = hookEntries(target.harness);
|
|
23239
|
+
const journals = await journalsFor({ fs: input.fs, stateRoot: input.stateRoot });
|
|
23240
|
+
const artifacts = routerOwnedArtifacts(journals, target.path, target.harness);
|
|
23241
|
+
const actions = expected.flatMap((entry) => {
|
|
23242
|
+
const pointer = `hooks.${entry.eventName}`;
|
|
23243
|
+
const targetArtifact = artifacts.find((artifact) => artifact.kind === "owned-json-entry" && artifact.pointer === pointer && artifact.valueDigest === jsonValueDigest(entry.value));
|
|
23244
|
+
if (targetArtifact === void 0)
|
|
23245
|
+
return [];
|
|
23246
|
+
const reverses = actionId(target.harness, "enable", "all");
|
|
23247
|
+
return [
|
|
23248
|
+
{
|
|
23249
|
+
kind: "remove-owned-change",
|
|
23250
|
+
id: actionId(target.harness, "disable", entry.eventName),
|
|
23251
|
+
riskClass: "reversible",
|
|
23252
|
+
requiresNetwork: false,
|
|
23253
|
+
requiresElevation: false,
|
|
23254
|
+
affectedPaths: [target.path],
|
|
23255
|
+
affectedProcesses: [target.harness],
|
|
23256
|
+
preconditions: [`${entry.eventName} still contains the exact Token Harness-owned hook`],
|
|
23257
|
+
postconditions: [`${entry.eventName} no longer contains the owned prompt-routing hook`],
|
|
23258
|
+
rollbackData: "file-snapshot",
|
|
23259
|
+
explanation: `Disable automatic native prompt routing for ${target.harness}`,
|
|
23260
|
+
path: target.path,
|
|
23261
|
+
reverses,
|
|
23262
|
+
target: targetArtifact
|
|
23263
|
+
}
|
|
23264
|
+
];
|
|
23265
|
+
});
|
|
23266
|
+
if (actions.length === 0)
|
|
23267
|
+
diagnostics.push(diagnostic({
|
|
23268
|
+
severity: "info",
|
|
23269
|
+
code: "prompt-routing-not-owned",
|
|
23270
|
+
subject: target.harness,
|
|
23271
|
+
message: "Token Harness owns no native prompt-routing hooks here, so nothing is removed",
|
|
23272
|
+
path: target.path,
|
|
23273
|
+
remediation: null
|
|
23274
|
+
}));
|
|
23275
|
+
return { target: target.path, actions, diagnostics };
|
|
23276
|
+
}
|
|
23277
|
+
async function readEvents(input) {
|
|
23278
|
+
if (input.stateRoot === null)
|
|
23279
|
+
return { state: "unavailable", events: [] };
|
|
23280
|
+
const directory = input.fs.join(input.stateRoot, "prompt-routing");
|
|
23281
|
+
if ((await input.fs.stat(directory))?.kind !== "directory")
|
|
23282
|
+
return { state: "available", events: [] };
|
|
23283
|
+
const files = (await input.fs.readDirectory(directory)).filter((name2) => /^events-\d{4}-\d{2}\.jsonl$/.test(name2)).sort().reverse();
|
|
23284
|
+
const events = [];
|
|
23285
|
+
let scannedBytes = 0;
|
|
23286
|
+
try {
|
|
23287
|
+
for (const file of files) {
|
|
23288
|
+
const path = input.fs.join(directory, file);
|
|
23289
|
+
const stat3 = await input.fs.stat(path);
|
|
23290
|
+
if (stat3 === null || stat3.kind !== "file")
|
|
23291
|
+
continue;
|
|
23292
|
+
if (stat3.byteLength > MAX_EVENT_FILE_BYTES || scannedBytes + stat3.byteLength > MAX_EVENT_SCAN_BYTES)
|
|
23293
|
+
return { state: "limited", events };
|
|
23294
|
+
const bytes = await input.fs.readFile(path);
|
|
23295
|
+
if (bytes.byteLength !== stat3.byteLength)
|
|
23296
|
+
return { state: "limited", events };
|
|
23297
|
+
scannedBytes += bytes.byteLength;
|
|
23298
|
+
const text3 = DECODER4.decode(bytes);
|
|
23299
|
+
for (const line of text3.split("\n")) {
|
|
23300
|
+
if (line === "")
|
|
23301
|
+
continue;
|
|
23302
|
+
try {
|
|
23303
|
+
const value3 = JSON.parse(line);
|
|
23304
|
+
if (!isPromptRouterEvent(value3))
|
|
23305
|
+
continue;
|
|
23306
|
+
if (input.harness !== void 0 && value3.harness !== input.harness)
|
|
23307
|
+
continue;
|
|
23308
|
+
if (input.projectId !== void 0 && value3.projectId !== input.projectId)
|
|
23309
|
+
continue;
|
|
23310
|
+
if (input.since !== void 0 && value3.timestamp < input.since)
|
|
23311
|
+
continue;
|
|
23312
|
+
events.push(value3);
|
|
23313
|
+
} catch {
|
|
23314
|
+
}
|
|
23315
|
+
}
|
|
23316
|
+
if (input.since !== void 0 && file.slice(7, 14) < input.since.slice(0, 7))
|
|
23317
|
+
break;
|
|
23318
|
+
}
|
|
23319
|
+
return { state: "available", events };
|
|
23320
|
+
} catch {
|
|
23321
|
+
return { state: "unavailable", events: [] };
|
|
23322
|
+
}
|
|
23323
|
+
}
|
|
23324
|
+
function isPromptRouterEvent(value3) {
|
|
23325
|
+
const row2 = asRecord(value3);
|
|
23326
|
+
return row2?.["schemaVersion"] === 1 && typeof row2["timestamp"] === "string" && Number.isFinite(Date.parse(row2["timestamp"])) && (row2["harness"] === "claude" || row2["harness"] === "codex") && typeof row2["projectId"] === "string" && ["prompt-submit", "subagent-start", "subagent-stop"].includes(String(row2["type"])) && (row2["model"] === null || typeof row2["model"] === "string" && row2["model"].length <= 80) && (row2["agentType"] === null || typeof row2["agentType"] === "string" && row2["agentType"].length <= 80);
|
|
23327
|
+
}
|
|
23328
|
+
async function recordNativePromptRoutingHook(input) {
|
|
23329
|
+
if (input.fs === null || input.stateRoot === null || input.projectId === null)
|
|
23330
|
+
return;
|
|
23331
|
+
let payload = null;
|
|
23332
|
+
if (input.event !== "prompt-submit" && input.hookInput !== null) {
|
|
23333
|
+
try {
|
|
23334
|
+
payload = asRecord(JSON.parse(input.hookInput));
|
|
23335
|
+
} catch {
|
|
23336
|
+
payload = null;
|
|
23337
|
+
}
|
|
23338
|
+
}
|
|
23339
|
+
const agentTypeRaw = payload?.["agent_type"];
|
|
23340
|
+
const agentType = input.event !== "prompt-submit" && typeof agentTypeRaw === "string" && agentTypeRaw.length <= 80 ? agentTypeRaw : null;
|
|
23341
|
+
const timestamp = new Date(input.now).toISOString();
|
|
23342
|
+
const event = {
|
|
23343
|
+
schemaVersion: 1,
|
|
23344
|
+
timestamp,
|
|
23345
|
+
harness: input.harness,
|
|
23346
|
+
projectId: input.projectId,
|
|
23347
|
+
type: input.event,
|
|
23348
|
+
// Hook payload model fields can identify the root session, not the spawned child. Until an
|
|
23349
|
+
// adapter has a versioned child-model field, keep actual worker identity unknown.
|
|
23350
|
+
model: null,
|
|
23351
|
+
agentType
|
|
23352
|
+
};
|
|
23353
|
+
const partition = `events-${timestamp.slice(0, 7)}.jsonl`;
|
|
23354
|
+
const directory = input.fs.join(input.stateRoot, "prompt-routing");
|
|
23355
|
+
await input.fs.createDirectory(directory);
|
|
23356
|
+
await input.fs.appendFile(input.fs.join(directory, partition), UTF84.encode(`${JSON.stringify(event)}
|
|
23357
|
+
`));
|
|
23358
|
+
}
|
|
23359
|
+
function summarizeEvents(events) {
|
|
23360
|
+
return {
|
|
23361
|
+
promptSubmissions: events.filter((event) => event.type === "prompt-submit").length,
|
|
23362
|
+
subagentsStarted: events.filter((event) => event.type === "subagent-start").length,
|
|
23363
|
+
subagentsStopped: events.filter((event) => event.type === "subagent-stop").length,
|
|
23364
|
+
reportedModels: [
|
|
23365
|
+
...new Set(events.filter((event) => event.type === "subagent-start" || event.type === "subagent-stop").flatMap((event) => event.model === null ? [] : [event.model]))
|
|
23366
|
+
],
|
|
23367
|
+
lastObservedAt: events.map((event) => event.timestamp).sort().at(-1) ?? null
|
|
23368
|
+
};
|
|
23369
|
+
}
|
|
23370
|
+
async function observeNativePromptRouting(input) {
|
|
23371
|
+
const harness = isHarness(input.harness) ? input.harness : "codex";
|
|
23372
|
+
const base = {
|
|
23373
|
+
harness,
|
|
23374
|
+
state: "unavailable",
|
|
23375
|
+
label: "Not verified",
|
|
23376
|
+
detail: "Native prompt routing could not be checked on this harness.",
|
|
23377
|
+
configPath: null,
|
|
23378
|
+
configured: null,
|
|
23379
|
+
promptSubmissions: 0,
|
|
23380
|
+
subagentsStarted: 0,
|
|
23381
|
+
subagentsStopped: 0,
|
|
23382
|
+
reportedModels: [],
|
|
23383
|
+
lastObservedAt: null,
|
|
23384
|
+
receiptState: "unavailable"
|
|
23385
|
+
};
|
|
23386
|
+
const target = configTarget({ ...input, harness: input.harness });
|
|
23387
|
+
if (target === null)
|
|
23388
|
+
return base;
|
|
23389
|
+
const eventResult = await readEvents({
|
|
23390
|
+
fs: input.fs,
|
|
23391
|
+
stateRoot: input.stateRoot,
|
|
23392
|
+
harness,
|
|
23393
|
+
...input.projectId === null ? {} : { projectId: input.projectId },
|
|
23394
|
+
since: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString()
|
|
23395
|
+
});
|
|
23396
|
+
const summary = summarizeEvents(eventResult.events);
|
|
23397
|
+
const stat3 = await input.fs.stat(target.path);
|
|
23398
|
+
if (stat3 === null) {
|
|
23399
|
+
return {
|
|
23400
|
+
...base,
|
|
23401
|
+
state: "absent",
|
|
23402
|
+
label: "Disabled",
|
|
23403
|
+
detail: "Automatic routing is off. No Token Harness native prompt hook is installed.",
|
|
23404
|
+
configPath: target.path,
|
|
23405
|
+
configured: false,
|
|
23406
|
+
...summary,
|
|
23407
|
+
receiptState: eventResult.state
|
|
23408
|
+
};
|
|
23409
|
+
}
|
|
23410
|
+
if (stat3.kind !== "file")
|
|
23411
|
+
return {
|
|
23412
|
+
...base,
|
|
23413
|
+
state: "conflict",
|
|
23414
|
+
label: "Path conflict",
|
|
23415
|
+
detail: "A non-file occupies the native hook settings path.",
|
|
23416
|
+
configPath: target.path,
|
|
23417
|
+
...summary,
|
|
23418
|
+
receiptState: eventResult.state
|
|
23419
|
+
};
|
|
23420
|
+
let hooks;
|
|
23421
|
+
try {
|
|
23422
|
+
const parsed = parseHookDocument(DECODER4.decode(await input.fs.readFile(target.path)));
|
|
23423
|
+
if (!parsed.ok)
|
|
23424
|
+
return {
|
|
23425
|
+
...base,
|
|
23426
|
+
state: "conflict",
|
|
23427
|
+
label: "Settings need review",
|
|
23428
|
+
detail: parsed.reason,
|
|
23429
|
+
configPath: target.path,
|
|
23430
|
+
...summary,
|
|
23431
|
+
receiptState: eventResult.state
|
|
23432
|
+
};
|
|
23433
|
+
hooks = parsed.hooks;
|
|
23434
|
+
} catch {
|
|
23435
|
+
return {
|
|
23436
|
+
...base,
|
|
23437
|
+
state: "unavailable",
|
|
23438
|
+
label: "Not verified",
|
|
23439
|
+
detail: "The hook settings file could not be read safely.",
|
|
23440
|
+
configPath: target.path,
|
|
23441
|
+
...summary,
|
|
23442
|
+
receiptState: eventResult.state
|
|
23443
|
+
};
|
|
23444
|
+
}
|
|
23445
|
+
const match = configHasExactRouter(hooks, harness);
|
|
23446
|
+
if (match.conflict || match.partial) {
|
|
23447
|
+
return {
|
|
23448
|
+
...base,
|
|
23449
|
+
state: "conflict",
|
|
23450
|
+
label: "Custom hook needs review",
|
|
23451
|
+
detail: "A partial or edited Token Harness prompt-routing hook was found and was not changed.",
|
|
23452
|
+
configPath: target.path,
|
|
23453
|
+
...summary,
|
|
23454
|
+
receiptState: eventResult.state
|
|
23455
|
+
};
|
|
23456
|
+
}
|
|
23457
|
+
if (!match.complete) {
|
|
23458
|
+
return {
|
|
23459
|
+
...base,
|
|
23460
|
+
state: "absent",
|
|
23461
|
+
label: "Disabled",
|
|
23462
|
+
detail: "Automatic routing is off. No Token Harness native prompt hook is installed.",
|
|
23463
|
+
configPath: target.path,
|
|
23464
|
+
configured: false,
|
|
23465
|
+
...summary,
|
|
23466
|
+
receiptState: eventResult.state
|
|
23467
|
+
};
|
|
23468
|
+
}
|
|
23469
|
+
const artifacts = routerOwnedArtifacts(await journalsFor(input), target.path, harness);
|
|
23470
|
+
const state = artifacts.length === hookEntries(harness).length ? "managed" : "external";
|
|
23471
|
+
const hasRuntimeReceipt = summary.promptSubmissions > 0;
|
|
23472
|
+
const label = state === "external" ? hasRuntimeReceipt ? "Runtime observed \xB7 external" : "Enabled externally" : hasRuntimeReceipt ? "Runtime observed" : harness === "codex" ? "Configured \xB7 trust or runtime pending" : "Configured \xB7 runtime pending";
|
|
23473
|
+
const detail2 = summary.promptSubmissions > 0 ? `${String(summary.promptSubmissions)} prompt hook(s), ${String(summary.subagentsStarted)} native agent start(s), ${String(summary.subagentsStopped)} stop(s) observed in this project during the last 30 days.${eventResult.state === "limited" ? " Counts are partial because the local receipt scan reached its safety limit." : eventResult.state === "unavailable" ? " Local runtime receipts could not be read." : ""}` : harness === "codex" ? "The hook is configured. Review and trust it in Codex with /hooks, then submit a prompt to produce a runtime receipt." : "The hook is configured. Start a new Claude Code session, submit a prompt, and Token Harness will show the runtime receipt.";
|
|
23474
|
+
return {
|
|
23475
|
+
...base,
|
|
23476
|
+
state,
|
|
23477
|
+
label,
|
|
23478
|
+
detail: detail2,
|
|
23479
|
+
configPath: target.path,
|
|
23480
|
+
configured: true,
|
|
23481
|
+
...summary,
|
|
23482
|
+
receiptState: eventResult.state
|
|
23483
|
+
};
|
|
23484
|
+
}
|
|
23485
|
+
async function nativeRoutingObservationForBenchmark(input) {
|
|
23486
|
+
const observed = await observeNativePromptRouting({
|
|
23487
|
+
...input,
|
|
23488
|
+
projectId: input.projectId
|
|
23489
|
+
});
|
|
23490
|
+
const configured = observed.configured;
|
|
23491
|
+
if (input.startedAt === void 0)
|
|
23492
|
+
return {
|
|
23493
|
+
configured,
|
|
23494
|
+
promptSubmissions: 0,
|
|
23495
|
+
subagentsStarted: 0,
|
|
23496
|
+
subagentsStopped: 0,
|
|
23497
|
+
reportedModels: []
|
|
23498
|
+
};
|
|
23499
|
+
const found = await readEvents({
|
|
23500
|
+
fs: input.fs,
|
|
23501
|
+
stateRoot: input.stateRoot,
|
|
23502
|
+
harness: observed.harness,
|
|
23503
|
+
projectId: input.projectId,
|
|
23504
|
+
since: input.startedAt
|
|
23505
|
+
});
|
|
23506
|
+
const summary = summarizeEvents(found.events);
|
|
23507
|
+
return {
|
|
23508
|
+
configured,
|
|
23509
|
+
promptSubmissions: summary.promptSubmissions,
|
|
23510
|
+
subagentsStarted: summary.subagentsStarted,
|
|
23511
|
+
subagentsStopped: summary.subagentsStopped,
|
|
23512
|
+
reportedModels: summary.reportedModels
|
|
23513
|
+
};
|
|
23514
|
+
}
|
|
23515
|
+
var UTF84, DECODER4, ROUTE_MARKER, MAX_EVENT_FILE_BYTES, MAX_EVENT_SCAN_BYTES, PROMPT_ROUTER_CHECK_MARKER;
|
|
23516
|
+
var init_prompt_router = __esm({
|
|
23517
|
+
"apps/cli/dist/src/prompt-router.js"() {
|
|
23518
|
+
"use strict";
|
|
23519
|
+
init_src();
|
|
23520
|
+
init_src3();
|
|
23521
|
+
UTF84 = new TextEncoder();
|
|
23522
|
+
DECODER4 = new TextDecoder("utf-8", { fatal: true });
|
|
23523
|
+
ROUTE_MARKER = "__internal-prompt-router";
|
|
23524
|
+
MAX_EVENT_FILE_BYTES = 4 * 1024 * 1024;
|
|
23525
|
+
MAX_EVENT_SCAN_BYTES = 16 * 1024 * 1024;
|
|
23526
|
+
PROMPT_ROUTER_CHECK_MARKER = "token-harness-prompt-router-v1";
|
|
22800
23527
|
}
|
|
22801
23528
|
});
|
|
22802
23529
|
|
|
@@ -24065,7 +24792,7 @@ var init_agent_skill = __esm({
|
|
|
24065
24792
|
"apps/cli/dist/src/agent-skill.js"() {
|
|
24066
24793
|
"use strict";
|
|
24067
24794
|
init_src();
|
|
24068
|
-
TOKEN_HARNESS_AGENT_SKILL = "---\nname: token-harness\ndescription: Optimizes local Claude Code or Codex work against observed subscription allowance, context pressure, quality floors, and project-local benchmark evidence using the Token Harness CLI.
|
|
24795
|
+
TOKEN_HARNESS_AGENT_SKILL = "---\nname: token-harness\ndescription: Optimizes local Claude Code or Codex work against observed subscription allowance, context pressure, quality floors, and project-local benchmark evidence using the Token Harness CLI. Guides native subagent model routing for substantial bounded coding tasks. Use for substantial coding work where native delegation may apply, or when the user asks about allowance, model/effort/verbosity choices, quota fit, or Token Harness.\n---\n\n# Token Harness\n\nUse Token Harness as a local deterministic policy engine. Do not reproduce its quota math or invent provider conversions yourself.\n\n## Automatic routing\n\nWhen enabled in the Token Harness dashboard, a native prompt hook supplies the routing policy on every submitted prompt. This works without invoking this skill or prefixing the prompt with a command. The hook asks the coding agent to delegate only eligible bounded work; it does not change the root model or prove which child model ran. Use this skill when the user asks for explicit quota-aware advice or a benchmark.\n\n## Default workflow\n\n1. Confirm `token-harness --version` works. If it is missing, do not install it silently. If the user asked to install or set up Token Harness, follow that request; otherwise explain that the local CLI is required.\n2. Identify the harness you are currently running as: `claude` for Claude Code or `codex` for Codex. Do not guess from repository files.\n3. Classify the current task conservatively:\n - `mechanical`: formatting, rename, lookup, simple edits, deterministic scaffolding.\n - `standard`: ordinary implementation, tests, focused bug fixes.\n - `hard`: multi-file reasoning, ambiguous failures, migrations, difficult reviews.\n - `critical`: architecture, security-sensitive work, releases, or high-regression-risk changes.\n If uncertain between two classes, use the higher class.\n4. For a substantial task, or whenever the user asks about allowance/efficiency, run:\n\n `token-harness optimize --harness <claude|codex> --task <class> --profile balanced --json`\n\n5. Treat the JSON result as evidence, not as permission to mutate configuration. Prefer recommendations that reduce avoidable context or session overhead before lowering a quality floor.\n6. Continue with the user's task. Mention Token Harness only when it materially changes the plan, recommends a user-visible action, or lacks enough evidence.\n\nDo not run Token Harness before every trivial tool call. One observation at a meaningful task boundary is normally enough; re-observe when the task class changes materially, after a quota reset, after a substantial session/context change, or when the user asks.\n\n## Active context evidence\n\nWhen the current conversation or your own tool results directly establish useful task-state evidence, you may pass a short-lived `--context-snapshot` file to `optimize`. This metadata is for the CLI; never ask the user to write or understand the JSON. Skip the snapshot when no actionable evidence is directly observable or a temporary file cannot be safely created and removed.\n\n- Set task boundary, validation and quality only from explicit task state and checks you observed. Use `unknown` when those facts are missing or ambiguous.\n- Mark material superseded or condensable only when its current state is directly clear. Include `byteLength` only when tooling measured the exact local bytes; otherwise use `null`. Never estimate bytes from tokens.\n- Set reducer attribution only when directly known; otherwise use `unknown`. Do not include transcript text, prompts, tool payloads, source text, paths, MCP names or schemas.\n- Add a checkpoint byte ceiling only when you will use that same ceiling for the existing bounded `token-harness handoff` command. Omit it when no artifact budget is configured.\n- Create the metadata file temporarily, run `optimize`, then remove it. Treat the decision as advice; do not mask, summarize, compact or start a session on the user's behalf.\n\n## Explicit workload\n\nOnly pass `--tasks-left N` when the remaining accepted-task count is explicit from the user or an explicit task list already in the conversation. Never infer it from token history, source files, GitHub issues, or a guessed backlog. When it is explicit, add it to the same advisory call:\n\n`token-harness optimize --harness <claude|codex> --task <class> --profile balanced --tasks-left <N> --json`\n\nFor multiple independent new tasks whose explicit list can be classified by task class, Token Harness can compare Claude and Codex with:\n\n`token-harness schedule --current <current> --candidate <other> --workload mechanical=N,standard=N,hard=N,critical=N --json`\n\nOmit zero-count classes. This is for queued new work, not an in-progress handoff. Never switch harnesses automatically from this result.\n\n## Native subagent model routing\n\nUse native subagents as the only model-routing surface. This routes delegated work; it never changes the model already selected for the root conversation. Keep Codex as the first supported path.\n\nFor Codex, when the task is substantial and contains a complete, bounded implementation unit that can be handed off without duplicating work, delegate that unit to one native subagent with `model: gpt-6-luna` if Luna is present in the current Codex model picker/catalog. Set the model explicitly in the native spawn request: when it is omitted, Codex inherits the root model and reasoning effort, so a generic delegation is not a cost-routed delegation. If a higher-priority instruction forbids specifying the child model, skip cost routing and continue with the root model. Keep the root model responsible for task framing, integration, and acceptance review. Do not run the same implementation in both agents. Use at most one cost-routed worker at a time.\n\nSkip routing for trivial tasks, tightly coupled or shared-write work, architecture/security/release decisions, work that needs the root model's full context or judgment throughout, when the user asks not to delegate, when the root model is Luna or cannot be identified, or when the requested model is not currently available. Do not substitute an unverified model ID or silently fall back to another harness. If no supported route is available, continue with the current root model.\n\nFor Claude Code, apply the same bounded-task rules only when Claude Code is already configured and authenticated and native subagents are available. Request the current native `haiku` alias for an eligible worker; do not configure Claude Code or authenticate on the user's behalf.\n\nTreat the selected child model as a routing request until Codex or Claude Code visibly reports the worker's actual model. A skill instruction is not runtime telemetry. Subagents add context and coordination overhead and can consume more total tokens than single-agent work; do not claim token, quota, or cost savings without paired, quality-gated usage evidence for the same harness and task class.\n\n## Persistent native changes\n\n`optimize` is advisory. If it recommends a persistent model/reasoning/verbosity change and the user wants it applied:\n\n1. Build a reviewed plan with `token-harness plan --harness <claude|codex> --native-policy --task <class> --profile balanced --json`.\n2. Summarize the exact proposed change, scope, and any limitations to the user.\n3. Apply only after the user explicitly approves the proposed mutation. Use the returned plan id with `token-harness apply --plan <id> --yes`.\n4. Do not treat a persisted preference as a live change to an already-running session. Follow the plan/result instructions about when it takes effect.\n\nNever silently change authentication, billing, provider, model routing, hooks, trust, or purchase/redeem credits.\n\n## Evidence rules\n\n- Never equate local token counts with subscription quota.\n- Never compare raw Claude and Codex percentages as if they were the same currency.\n- Unknown allowance or benchmark evidence stays unknown.\n- Preserve task quality floors; do not lower effort merely because a cheaper setting exists.\n- Prefer project-local measured outcomes and backend quota deltas when Token Harness exposes them.\n- Do not add an MCP server or background model just to use this skill. The local CLI is the tool surface.\n";
|
|
24069
24796
|
ENCODER = new TextEncoder();
|
|
24070
24797
|
SKILL_DIGEST = digestBytes(ENCODER.encode(TOKEN_HARNESS_AGENT_SKILL));
|
|
24071
24798
|
TARGETS = {
|
|
@@ -26045,6 +26772,41 @@ async function computePlan(context) {
|
|
|
26045
26772
|
}
|
|
26046
26773
|
}
|
|
26047
26774
|
}
|
|
26775
|
+
if (context.agentRouting === true || context.disableAgentRouting === true) {
|
|
26776
|
+
const harness = context.harness;
|
|
26777
|
+
if (harness !== harnessId("claude") && harness !== CODEX12) {
|
|
26778
|
+
diagnostics.push(diagnostic({
|
|
26779
|
+
severity: "warning",
|
|
26780
|
+
code: "prompt-routing-harness-required",
|
|
26781
|
+
subject: harness,
|
|
26782
|
+
message: "Automatic prompt routing requires an explicit Claude Code or Codex harness",
|
|
26783
|
+
remediation: "Choose the detected agent in the guided app, or pass --harness claude|codex"
|
|
26784
|
+
}));
|
|
26785
|
+
} else if (context.adapters === null) {
|
|
26786
|
+
diagnostics.push(diagnostic({
|
|
26787
|
+
severity: "warning",
|
|
26788
|
+
code: "prompt-routing-adapters-unavailable",
|
|
26789
|
+
subject: harness,
|
|
26790
|
+
message: "The native prompt hook could not be planned without filesystem adapters",
|
|
26791
|
+
remediation: "Refresh Token Harness from a supported local environment"
|
|
26792
|
+
}));
|
|
26793
|
+
} else {
|
|
26794
|
+
const input = {
|
|
26795
|
+
fs: context.adapters.fs,
|
|
26796
|
+
home: context.home,
|
|
26797
|
+
harness,
|
|
26798
|
+
version: versions.harnesses[harness] ?? null,
|
|
26799
|
+
runner: context.adapters.runner,
|
|
26800
|
+
facts: context.platform,
|
|
26801
|
+
paths: context.adapters.paths,
|
|
26802
|
+
projectRoot: context.projectRoot,
|
|
26803
|
+
stateRoot: context.stateRoot
|
|
26804
|
+
};
|
|
26805
|
+
const routingPlan = context.agentRouting ? await planNativePromptRoutingInstall(input) : await planNativePromptRoutingRemoval(input);
|
|
26806
|
+
actions.push(...routingPlan.actions);
|
|
26807
|
+
diagnostics.push(...routingPlan.diagnostics);
|
|
26808
|
+
}
|
|
26809
|
+
}
|
|
26048
26810
|
if (context.nativePolicy === true && context.harness === harnessId("claude")) {
|
|
26049
26811
|
if (context.taskClass === void 0 || context.taskClass === null) {
|
|
26050
26812
|
diagnostics.push(diagnostic({
|
|
@@ -26087,6 +26849,14 @@ async function computePlan(context) {
|
|
|
26087
26849
|
],
|
|
26088
26850
|
remediation: "Give each provider a distinct marker pair, or disable one of the providers for this instruction region"
|
|
26089
26851
|
}));
|
|
26852
|
+
if (providerAdapters.length === 0 && context.provider !== providerId("none") && actions.length === 0) {
|
|
26853
|
+
diagnostics.push(diagnostic({
|
|
26854
|
+
severity: "info",
|
|
26855
|
+
code: "no-providers-registered",
|
|
26856
|
+
message: "No optimization provider is available for this operation",
|
|
26857
|
+
remediation: null
|
|
26858
|
+
}));
|
|
26859
|
+
}
|
|
26090
26860
|
const conflicts = [...resolution.conflicts, ...markerConflicts];
|
|
26091
26861
|
const report = {
|
|
26092
26862
|
// RFC 0006 §Plan persistence: "a digest over the plan's normalized content, so identical
|
|
@@ -26135,14 +26905,6 @@ async function computePlan(context) {
|
|
|
26135
26905
|
remediation: null
|
|
26136
26906
|
}));
|
|
26137
26907
|
}
|
|
26138
|
-
if (providerAdapters.length === 0) {
|
|
26139
|
-
diagnostics.push(diagnostic({
|
|
26140
|
-
severity: "info",
|
|
26141
|
-
code: "no-providers-registered",
|
|
26142
|
-
message: "No provider adapters are registered in this build, so no plan has actions",
|
|
26143
|
-
remediation: null
|
|
26144
|
-
}));
|
|
26145
|
-
}
|
|
26146
26908
|
if (resolution.ownership.length > 0 && actions.length === 0 && blocked.length === 0) {
|
|
26147
26909
|
diagnostics.push(diagnostic({
|
|
26148
26910
|
severity: "info",
|
|
@@ -26227,6 +26989,7 @@ var init_plan2 = __esm({
|
|
|
26227
26989
|
init_src3();
|
|
26228
26990
|
init_src();
|
|
26229
26991
|
init_agent_skill();
|
|
26992
|
+
init_prompt_router();
|
|
26230
26993
|
init_apply();
|
|
26231
26994
|
init_context_cost2();
|
|
26232
26995
|
init_optimize();
|
|
@@ -26303,6 +27066,48 @@ async function verifyManagedIntegrationPostconditions(context, integrations) {
|
|
|
26303
27066
|
}
|
|
26304
27067
|
return diagnostics;
|
|
26305
27068
|
}
|
|
27069
|
+
async function verifyNativePromptRoutingPostconditions(context, actions) {
|
|
27070
|
+
const routing = actions.filter((action) => action.id.startsWith("native-prompt-routing:"));
|
|
27071
|
+
if (routing.length === 0)
|
|
27072
|
+
return [];
|
|
27073
|
+
if (context.adapters === null || context.stateRoot === null || context.harness !== harnessId("claude") && context.harness !== harnessId("codex")) {
|
|
27074
|
+
return [
|
|
27075
|
+
diagnostic({
|
|
27076
|
+
severity: "error",
|
|
27077
|
+
code: "prompt-routing-postcondition-unavailable",
|
|
27078
|
+
subject: context.harness,
|
|
27079
|
+
message: "Native prompt-routing configuration could not be read after the change",
|
|
27080
|
+
remediation: "Keep the transaction rollback and review a fresh plan from the local agent environment"
|
|
27081
|
+
})
|
|
27082
|
+
];
|
|
27083
|
+
}
|
|
27084
|
+
const observed = await observeNativePromptRouting({
|
|
27085
|
+
fs: context.adapters.fs,
|
|
27086
|
+
home: context.home,
|
|
27087
|
+
stateRoot: context.stateRoot,
|
|
27088
|
+
harness: context.harness,
|
|
27089
|
+
version: null,
|
|
27090
|
+
runner: context.adapters.runner,
|
|
27091
|
+
facts: context.platform,
|
|
27092
|
+
paths: context.adapters.paths,
|
|
27093
|
+
projectRoot: context.projectRoot,
|
|
27094
|
+
projectId: context.adapters.projectIdFor(context.projectRoot)
|
|
27095
|
+
});
|
|
27096
|
+
const shouldBeEnabled = routing.some((action) => action.id.includes(":enable:"));
|
|
27097
|
+
const satisfied = shouldBeEnabled ? observed.configured === true : observed.configured === false;
|
|
27098
|
+
if (satisfied)
|
|
27099
|
+
return [];
|
|
27100
|
+
return [
|
|
27101
|
+
diagnostic({
|
|
27102
|
+
severity: "error",
|
|
27103
|
+
code: "prompt-routing-postcondition-unmet",
|
|
27104
|
+
subject: context.harness,
|
|
27105
|
+
path: observed.configPath,
|
|
27106
|
+
message: `Native prompt-routing hooks were not observed in the requested state after the change: ${observed.label}`,
|
|
27107
|
+
remediation: "Review the hook settings and allow the transaction to restore its backup"
|
|
27108
|
+
})
|
|
27109
|
+
];
|
|
27110
|
+
}
|
|
26306
27111
|
function transactionIdFor(planId, at) {
|
|
26307
27112
|
const digest = digestText(`${planId} ${at}`);
|
|
26308
27113
|
return digest.slice(digest.indexOf(":") + 1, digest.indexOf(":") + 13);
|
|
@@ -26369,6 +27174,8 @@ async function runApply(context) {
|
|
|
26369
27174
|
const diagnostics = [];
|
|
26370
27175
|
let stored = null;
|
|
26371
27176
|
let storedAgentSkill = false;
|
|
27177
|
+
let storedAgentRouting = false;
|
|
27178
|
+
let storedAgentRoutingRemoval = false;
|
|
26372
27179
|
let planningContext = context;
|
|
26373
27180
|
const rejectedReport = () => ({
|
|
26374
27181
|
...emptyReport3("rejected"),
|
|
@@ -26422,11 +27229,15 @@ async function runApply(context) {
|
|
|
26422
27229
|
return finish3("rejected", EXIT_CODES["precondition-drift"], rejectedReport(), diagnostics);
|
|
26423
27230
|
}
|
|
26424
27231
|
storedAgentSkill = stored.actions.some((action) => action.id.startsWith("agent-skill:"));
|
|
27232
|
+
storedAgentRouting = stored.actions.some((action) => action.id.startsWith("native-prompt-routing:") && action.id.includes(":enable:"));
|
|
27233
|
+
storedAgentRoutingRemoval = stored.actions.some((action) => action.id.startsWith("native-prompt-routing:") && action.id.includes(":disable:"));
|
|
26425
27234
|
planningContext = {
|
|
26426
27235
|
...context,
|
|
26427
27236
|
harness: stored.harness,
|
|
26428
27237
|
provider,
|
|
26429
|
-
agentSkill: storedAgentSkill
|
|
27238
|
+
agentSkill: storedAgentSkill,
|
|
27239
|
+
agentRouting: storedAgentRouting,
|
|
27240
|
+
disableAgentRouting: storedAgentRoutingRemoval
|
|
26430
27241
|
};
|
|
26431
27242
|
} catch {
|
|
26432
27243
|
diagnostics.push(diagnostic({
|
|
@@ -26450,6 +27261,16 @@ async function runApply(context) {
|
|
|
26450
27261
|
}));
|
|
26451
27262
|
return finish3("rejected", EXIT_CODES["precondition-drift"], rejectedReport(), diagnostics);
|
|
26452
27263
|
}
|
|
27264
|
+
if (stored !== null && (storedAgentRouting || storedAgentRoutingRemoval) && computed.report.planId !== stored.planId) {
|
|
27265
|
+
diagnostics.push(diagnostic({
|
|
27266
|
+
severity: "error",
|
|
27267
|
+
code: "prompt-routing-plan-drift",
|
|
27268
|
+
subject: stored.harness,
|
|
27269
|
+
message: "The native prompt-routing target or ownership changed after the reviewed preview",
|
|
27270
|
+
remediation: "Review a fresh prompt-routing preview; nothing was written"
|
|
27271
|
+
}));
|
|
27272
|
+
return finish3("rejected", EXIT_CODES["precondition-drift"], rejectedReport(), diagnostics);
|
|
27273
|
+
}
|
|
26453
27274
|
if (computed.blocked.length > 0 && computed.report.actions.length === 0) {
|
|
26454
27275
|
return finish3("rejected", EXIT_CODES["unsupported-environment"], rejectedReport(), diagnostics);
|
|
26455
27276
|
}
|
|
@@ -26553,7 +27374,10 @@ async function runApply(context) {
|
|
|
26553
27374
|
// RFC 0004 §Process policy: an installer reaches the machine through the runner or not at all.
|
|
26554
27375
|
runner: context.adapters.runner,
|
|
26555
27376
|
now: context.now,
|
|
26556
|
-
verifyPostconditions: async () =>
|
|
27377
|
+
verifyPostconditions: async () => [
|
|
27378
|
+
...await verifyManagedIntegrationPostconditions(context, computed.managedIntegrations),
|
|
27379
|
+
...await verifyNativePromptRoutingPostconditions(context, actions)
|
|
27380
|
+
]
|
|
26557
27381
|
});
|
|
26558
27382
|
diagnostics.push(...transaction.diagnostics);
|
|
26559
27383
|
const report = {
|
|
@@ -26589,6 +27413,7 @@ var init_apply = __esm({
|
|
|
26589
27413
|
"use strict";
|
|
26590
27414
|
init_src();
|
|
26591
27415
|
init_src3();
|
|
27416
|
+
init_prompt_router();
|
|
26592
27417
|
init_candidate_lifecycle();
|
|
26593
27418
|
init_plan2();
|
|
26594
27419
|
init_snapshot_safety();
|
|
@@ -26888,6 +27713,18 @@ async function runBenchmarkStart(context) {
|
|
|
26888
27713
|
runContext(observedContext),
|
|
26889
27714
|
runHistory({ ...observedContext, since: "1d", until: null })
|
|
26890
27715
|
]);
|
|
27716
|
+
const nativeRoutingAtStart = context.adapters === null ? null : await nativeRoutingObservationForBenchmark({
|
|
27717
|
+
fs: context.adapters.fs,
|
|
27718
|
+
home: context.home,
|
|
27719
|
+
stateRoot: context.stateRoot,
|
|
27720
|
+
harness,
|
|
27721
|
+
version: null,
|
|
27722
|
+
runner: context.adapters.runner,
|
|
27723
|
+
facts: context.platform,
|
|
27724
|
+
paths: context.adapters.paths,
|
|
27725
|
+
projectRoot: context.projectRoot,
|
|
27726
|
+
projectId
|
|
27727
|
+
});
|
|
26891
27728
|
const budget = budgetResult.data?.harnesses.find((item) => item.harnessId === harness);
|
|
26892
27729
|
const contextObservation = contextResult.data?.harnesses.find((item) => item.harnessId === harness);
|
|
26893
27730
|
const policy = benchmarkPolicySnapshot(contextObservation);
|
|
@@ -26906,7 +27743,8 @@ async function runBenchmarkStart(context) {
|
|
|
26906
27743
|
startedAt,
|
|
26907
27744
|
usageBefore: budget?.windows ?? [],
|
|
26908
27745
|
contextAtStart,
|
|
26909
|
-
localSessionsBefore
|
|
27746
|
+
localSessionsBefore,
|
|
27747
|
+
nativeRoutingAtStart
|
|
26910
27748
|
};
|
|
26911
27749
|
if (!await writeJson(context, paths.capturePath, capture)) {
|
|
26912
27750
|
return commandResult({
|
|
@@ -27091,6 +27929,19 @@ async function runBenchmarkFinish(context) {
|
|
|
27091
27929
|
runContext(completedContext),
|
|
27092
27930
|
runHistory({ ...completedContext, since: "1d", until: null })
|
|
27093
27931
|
]);
|
|
27932
|
+
const nativeRoutingAtFinish = context.adapters === null ? null : await nativeRoutingObservationForBenchmark({
|
|
27933
|
+
fs: context.adapters.fs,
|
|
27934
|
+
home: context.home,
|
|
27935
|
+
stateRoot: context.stateRoot,
|
|
27936
|
+
harness: parsed.capture.harnessId,
|
|
27937
|
+
version: null,
|
|
27938
|
+
runner: context.adapters.runner,
|
|
27939
|
+
facts: context.platform,
|
|
27940
|
+
paths: context.adapters.paths,
|
|
27941
|
+
projectRoot: context.projectRoot,
|
|
27942
|
+
projectId,
|
|
27943
|
+
startedAt: parsed.capture.startedAt
|
|
27944
|
+
});
|
|
27094
27945
|
const budget = budgetResult.data?.harnesses.find((item) => item.harnessId === parsed.capture.harnessId);
|
|
27095
27946
|
const localUsage = parsed.capture.localSessionsBefore !== null && historyResult.data?.source.state === "available" ? deriveTaskLocalUsage(parsed.capture.localSessionsBefore, snapshotTaskLocalSessions(historyResult.data.sessions), parsed.capture.startedAt, completedAt) : null;
|
|
27096
27947
|
const finishContextObservation = contextResult.data?.harnesses.find((item) => item.harnessId === parsed.capture.harnessId);
|
|
@@ -27102,7 +27953,8 @@ async function runBenchmarkFinish(context) {
|
|
|
27102
27953
|
failedAttempts,
|
|
27103
27954
|
localUsage,
|
|
27104
27955
|
contextAtFinish: taskBenchmarkContextSnapshot(finishContextObservation),
|
|
27105
|
-
policyAtFinish: benchmarkPolicySnapshot(finishContextObservation)
|
|
27956
|
+
policyAtFinish: benchmarkPolicySnapshot(finishContextObservation),
|
|
27957
|
+
nativeRoutingAtFinish
|
|
27106
27958
|
});
|
|
27107
27959
|
if (!completed.ok) {
|
|
27108
27960
|
return commandResult({
|
|
@@ -27159,6 +28011,7 @@ var init_benchmark_capture = __esm({
|
|
|
27159
28011
|
init_budget2();
|
|
27160
28012
|
init_context_cost2();
|
|
27161
28013
|
init_history2();
|
|
28014
|
+
init_prompt_router();
|
|
27162
28015
|
CLAUDE13 = harnessId("claude");
|
|
27163
28016
|
CODEX13 = harnessId("codex");
|
|
27164
28017
|
CAPTURE_HARNESSES = /* @__PURE__ */ new Set([CLAUDE13, CODEX13]);
|
|
@@ -33774,12 +34627,19 @@ not-exercised, which is not a failure.`,
|
|
|
33774
34627
|
|
|
33775
34628
|
Usage
|
|
33776
34629
|
token-harness plan [--json] [--harness <id>] [--provider <id>] [--project <dir>]
|
|
34630
|
+
[--agent-routing | --disable-agent-routing]
|
|
33777
34631
|
[--native-policy] [--task <class>] [--profile <name>]
|
|
33778
34632
|
[--reserve <0-95>] [--tasks-left <n>]
|
|
33779
34633
|
|
|
33780
34634
|
Read-only. Exits 0 when a plan was produced, and 4 when a hard conflict prevents
|
|
33781
34635
|
apply. Nothing is changed either way.
|
|
33782
34636
|
|
|
34637
|
+
--agent-routing adds the native per-prompt hook for the selected Claude Code or Codex
|
|
34638
|
+
harness. --disable-agent-routing removes only exact hook entries owned by Token Harness.
|
|
34639
|
+
Both changes use the normal stored-plan, approval, verification and rollback path. Claude
|
|
34640
|
+
loads the change in a new session; Codex requires the user to review and trust the hook in
|
|
34641
|
+
/hooks. Configuration is shown separately from runtime callbacks in the guided app.
|
|
34642
|
+
|
|
33783
34643
|
--native-policy adds reviewed Codex native settings derived from the same optimizer
|
|
33784
34644
|
policy as token-harness optimize. This build manages reasoning effort and verbosity
|
|
33785
34645
|
only. A field coming from project config or a selected profile is left untouched.
|
|
@@ -33998,6 +34858,8 @@ async function run(options) {
|
|
|
33998
34858
|
nativePolicy: invocation.options.nativePolicy,
|
|
33999
34859
|
env: options.env ?? {},
|
|
34000
34860
|
agentSkill: invocation.options.agentSkill,
|
|
34861
|
+
agentRouting: invocation.options.agentRouting,
|
|
34862
|
+
disableAgentRouting: invocation.options.disableAgentRouting,
|
|
34001
34863
|
since: invocation.options.since,
|
|
34002
34864
|
until: invocation.options.until,
|
|
34003
34865
|
planId: invocation.options.plan,
|
|
@@ -34488,6 +35350,48 @@ function allowanceEvidence(entries, scope, quality) {
|
|
|
34488
35350
|
pairs: deltas.length
|
|
34489
35351
|
};
|
|
34490
35352
|
}
|
|
35353
|
+
function routedAllowanceEvidence(entries, scope) {
|
|
35354
|
+
const deltas = entries.flatMap((entry) => {
|
|
35355
|
+
const quota = entry.quota;
|
|
35356
|
+
if (quota === null || quota.scope !== scope || quota.confidence !== "authoritative")
|
|
35357
|
+
return [];
|
|
35358
|
+
return [quota.baselineDeltaUsedPercent - quota.optimizedDeltaUsedPercent];
|
|
35359
|
+
});
|
|
35360
|
+
const savedPercent = median2(deltas);
|
|
35361
|
+
return {
|
|
35362
|
+
state: savedPercent === null ? "not-measured" : "measured",
|
|
35363
|
+
scope,
|
|
35364
|
+
savedPercent: savedPercent === null ? null : roundOne(savedPercent),
|
|
35365
|
+
equivalentMinutes: scope === "five-hour" && savedPercent !== null ? roundOne(savedPercent * 3) : null,
|
|
35366
|
+
pairs: deltas.length
|
|
35367
|
+
};
|
|
35368
|
+
}
|
|
35369
|
+
function routingEvidence(entries) {
|
|
35370
|
+
const routed = entries.filter((entry) => entry.nativeRouting?.verdict === "attributed");
|
|
35371
|
+
const eligible = routed.filter((entry) => entry.nativeRouting?.qualityGatesPassed === true);
|
|
35372
|
+
const local = eligible.filter((entry) => entry.baselineLocalTokens !== null && entry.optimizedLocalTokens !== null);
|
|
35373
|
+
const baselineLocalTokens = local.length ? local.reduce((total, entry) => total + (entry.baselineLocalTokens ?? 0), 0) : null;
|
|
35374
|
+
const optimizedLocalTokens = local.length ? local.reduce((total, entry) => total + (entry.optimizedLocalTokens ?? 0), 0) : null;
|
|
35375
|
+
const savedLocalTokens = baselineLocalTokens === null || optimizedLocalTokens === null ? null : baselineLocalTokens - optimizedLocalTokens;
|
|
35376
|
+
const localTokenSavingPercent = baselineLocalTokens === null || optimizedLocalTokens === null || baselineLocalTokens <= 0 ? null : roundOne(savedLocalTokens / baselineLocalTokens * 100);
|
|
35377
|
+
const qualityBlockedPairs = routed.length - eligible.length;
|
|
35378
|
+
return {
|
|
35379
|
+
state: routed.length === 0 ? "not-measured" : eligible.length === 0 ? "blocked-by-quality" : "measured",
|
|
35380
|
+
pairs: eligible.length,
|
|
35381
|
+
qualityBlockedPairs,
|
|
35382
|
+
localPairs: local.length,
|
|
35383
|
+
baselineLocalTokens,
|
|
35384
|
+
optimizedLocalTokens,
|
|
35385
|
+
savedLocalTokens,
|
|
35386
|
+
localTokenSavingPercent,
|
|
35387
|
+
allowance5h: routedAllowanceEvidence(eligible, "five-hour"),
|
|
35388
|
+
allowance7d: routedAllowanceEvidence(eligible, "weekly"),
|
|
35389
|
+
reportedChildModels: [
|
|
35390
|
+
...new Set(eligible.flatMap((entry) => entry.nativeRouting?.optimizedReportedModels ?? []))
|
|
35391
|
+
],
|
|
35392
|
+
basis: routed.length === 0 ? "No paired benchmark currently proves that a native prompt hook ran and started a subagent." : eligible.length === 0 ? "Routing callbacks were observed, but all attributed pairs failed the quality gate; no savings are credited." : local.length > 0 || eligible.some((entry) => entry.quota?.confidence === "authoritative") ? "Exact local token counts and authoritative quota deltas are reported in separate units, only for attributed pairs that passed both quality gates." : "Routing was observed and both quality gates passed, but local token or authoritative quota usage was unavailable; no savings amount is inferred."
|
|
35393
|
+
};
|
|
35394
|
+
}
|
|
34491
35395
|
function guidedValueEvidence(report) {
|
|
34492
35396
|
const entries = report?.entries ?? [];
|
|
34493
35397
|
const quality = qualityEvidence(entries);
|
|
@@ -34496,6 +35400,7 @@ function guidedValueEvidence(report) {
|
|
|
34496
35400
|
allowance5h: allowanceEvidence(entries, "five-hour", quality),
|
|
34497
35401
|
allowance7d: allowanceEvidence(entries, "weekly", quality),
|
|
34498
35402
|
quality,
|
|
35403
|
+
routing: routingEvidence(entries),
|
|
34499
35404
|
candidates: (report?.candidateEvidence ?? []).map((item) => ({ ...item })),
|
|
34500
35405
|
apiCost: {
|
|
34501
35406
|
state: "not-measured",
|
|
@@ -34597,7 +35502,7 @@ function guideSetupTargets(report, harness) {
|
|
|
34597
35502
|
return GUIDE_MANAGED_PROVIDERS.map((provider) => guideSetupTarget(report, harness, provider));
|
|
34598
35503
|
}
|
|
34599
35504
|
function explainGuideIssue(diagnostics, fallback) {
|
|
34600
|
-
const known = diagnostics.find((entry) => ISSUE_COPY[entry.code] !== void 0);
|
|
35505
|
+
const known = diagnostics.find((entry) => entry.severity === "error" && ISSUE_COPY[entry.code] !== void 0) ?? diagnostics.find((entry) => entry.severity === "warning" && ISSUE_COPY[entry.code] !== void 0) ?? diagnostics.find((entry) => entry.severity === "info" && ISSUE_COPY[entry.code] !== void 0);
|
|
34601
35506
|
if (known !== void 0)
|
|
34602
35507
|
return ISSUE_COPY[known.code];
|
|
34603
35508
|
const blocked = diagnostics.find((entry) => /compatibility|unsupported|unreviewed|no-row/.test(entry.code));
|
|
@@ -34740,7 +35645,7 @@ function guidanceView(id, observation) {
|
|
|
34740
35645
|
...observation.state === "absent" ? { action: { kind: "skill", label: "Enable in-session guidance", harness: id } } : {}
|
|
34741
35646
|
};
|
|
34742
35647
|
}
|
|
34743
|
-
function agentRules(id, providers, context, guidance) {
|
|
35648
|
+
function agentRules(id, providers, context, guidance, promptRouting) {
|
|
34744
35649
|
const observation = context?.harnesses.find((item) => item.harnessId === id);
|
|
34745
35650
|
const reasoning = reasoningView(id, observation);
|
|
34746
35651
|
return [
|
|
@@ -34790,6 +35695,29 @@ function agentRules(id, providers, context, guidance) {
|
|
|
34790
35695
|
next: guidance?.state === "managed" ? "Keep coding normally. Ask the agent to use Token Harness when you want an explicit quota-aware check." : guidance?.state === "external" ? "The matching skill can be used as-is. Token Harness keeps it user-owned." : guidance?.state === "conflict" ? "Review the existing skill manually. Token Harness will not overwrite it." : "Enable this once, then keep coding normally. Ask the agent to use Token Harness for a task when you want an explicit check.",
|
|
34791
35696
|
...guidance?.action ? { action: guidance.action } : {}
|
|
34792
35697
|
},
|
|
35698
|
+
{
|
|
35699
|
+
id: `${id}-prompt-routing`,
|
|
35700
|
+
title: "Automatic prompt routing",
|
|
35701
|
+
state: promptRouting?.label ?? "Not verified",
|
|
35702
|
+
mode: promptRouting?.state === "absent" ? "not-enabled" : promptRouting?.state === "managed" || promptRouting?.state === "external" ? "automatic" : "integration",
|
|
35703
|
+
what: promptRouting?.detail ?? "Adds a native prompt hook that supplies the routing policy on every submitted prompt.",
|
|
35704
|
+
why: "Eligible bounded work may use a cheaper native subagent. The root conversation model stays unchanged, and the model decides whether a native subagent is appropriate.",
|
|
35705
|
+
evidence: promptRouting?.promptSubmissions ? `${String(promptRouting.promptSubmissions)} prompt callback(s) and ${String(promptRouting.subagentsStarted)} subagent start(s) observed in the last 30 days. Actual child model is shown only when the harness reports it.` : promptRouting?.configured ? "The hook is configured, but no prompt callback has been observed yet. Configuration alone is not runtime proof." : "No runtime routing evidence has been recorded yet.",
|
|
35706
|
+
next: promptRouting?.state === "absent" ? "Enable routing once, restart or trust the hook if the harness requires it, then keep using prompts normally." : promptRouting?.state === "managed" ? "Routing is enabled. Disable it here if you want to stop injecting the policy on each prompt." : promptRouting?.state === "external" ? "This hook is user-owned. Token Harness can report it but will not remove it." : promptRouting?.detail ?? "Refresh to inspect the native prompt-hook state.",
|
|
35707
|
+
...promptRouting?.state === "absent" ? {
|
|
35708
|
+
action: {
|
|
35709
|
+
kind: "routing-enable",
|
|
35710
|
+
label: "Enable automatic routing",
|
|
35711
|
+
harness: id
|
|
35712
|
+
}
|
|
35713
|
+
} : promptRouting?.state === "managed" ? {
|
|
35714
|
+
action: {
|
|
35715
|
+
kind: "routing-disable",
|
|
35716
|
+
label: "Disable automatic routing",
|
|
35717
|
+
harness: id
|
|
35718
|
+
}
|
|
35719
|
+
} : {}
|
|
35720
|
+
},
|
|
34793
35721
|
{
|
|
34794
35722
|
id: `${id}-mcp`,
|
|
34795
35723
|
title: "Connected tools",
|
|
@@ -34924,6 +35852,13 @@ var init_guided = __esm({
|
|
|
34924
35852
|
"codex-native-policy-unavailable": "Codex did not expose a writable, versioned user setting. No change is proposed.",
|
|
34925
35853
|
"codex-native-policy-shadowed": "A project or profile overrides this Codex setting. That setting belongs to you and will not be replaced.",
|
|
34926
35854
|
"no-providers-registered": "No optimization provider was selected for this operation.",
|
|
35855
|
+
"prompt-routing-target-unavailable": "Token Harness could not locate a supported user-level prompt-hook settings file for this agent.",
|
|
35856
|
+
"prompt-routing-version-unverified": "Automatic routing is not available for this agent version until its prompt-hook format has been verified.",
|
|
35857
|
+
"prompt-routing-runtime-unavailable": "The Token Harness hook command could not run from this dashboard environment. Make Token Harness available on PATH, then review routing again.",
|
|
35858
|
+
"prompt-routing-target-not-file": "A non-file occupies the agent hook settings path, so Token Harness left it unchanged.",
|
|
35859
|
+
"prompt-routing-settings-unmergeable": "The current hook settings cannot be merged safely. Repair the JSON or review the hook manually.",
|
|
35860
|
+
"prompt-routing-already-configured": "Automatic routing hooks are already present. Nothing needs to be changed.",
|
|
35861
|
+
"prompt-routing-existing-hook-conflict": "An existing Token Harness routing hook was changed or only partly installed. It was left untouched for review.",
|
|
34927
35862
|
"already-in-desired-state": "The supported integration is already configured. Nothing needs to be changed.",
|
|
34928
35863
|
"delegated-install-snapshot-too-large": "The optimizer setup found too much unrelated data inside its rollback boundary. Nothing was changed. Update Token Harness or use a narrower project directory before retrying.",
|
|
34929
35864
|
"delegated-install-failed": "The optimizer installer itself did not complete successfully. Nothing was kept from the failed transaction.",
|
|
@@ -35023,11 +35958,13 @@ var init_guided = __esm({
|
|
|
35023
35958
|
now;
|
|
35024
35959
|
random;
|
|
35025
35960
|
observeGuidance;
|
|
35026
|
-
|
|
35961
|
+
observeRouting;
|
|
35962
|
+
constructor(call, now, random, observeGuidance = null, observeRouting = null) {
|
|
35027
35963
|
this.call = call;
|
|
35028
35964
|
this.now = now;
|
|
35029
35965
|
this.random = random;
|
|
35030
35966
|
this.observeGuidance = observeGuidance;
|
|
35967
|
+
this.observeRouting = observeRouting;
|
|
35031
35968
|
}
|
|
35032
35969
|
status() {
|
|
35033
35970
|
return {
|
|
@@ -35099,6 +36036,7 @@ var init_guided = __esm({
|
|
|
35099
36036
|
const empty2 = () => ({ data: null, diagnostics: [], exitCode: 9 });
|
|
35100
36037
|
let doctor = empty2(), budget = empty2(), context = empty2();
|
|
35101
36038
|
let guidance;
|
|
36039
|
+
let promptRouting;
|
|
35102
36040
|
const observe = async (id, args) => {
|
|
35103
36041
|
let result6;
|
|
35104
36042
|
try {
|
|
@@ -35116,7 +36054,7 @@ var init_guided = __esm({
|
|
|
35116
36054
|
loading.agents = this.agentView(doctor, budget, context, {
|
|
35117
36055
|
rules: loading.stages.find((item) => item.id === "rules")?.state !== "working",
|
|
35118
36056
|
allowance: loading.stages.find((item) => item.id === "allowance")?.state !== "working"
|
|
35119
|
-
}, guidance);
|
|
36057
|
+
}, guidance, promptRouting);
|
|
35120
36058
|
};
|
|
35121
36059
|
const [, , , metrics, status, benchmark] = await Promise.all([
|
|
35122
36060
|
observe("agents", ["doctor"]).then((result6) => {
|
|
@@ -35143,6 +36081,29 @@ var init_guided = __esm({
|
|
|
35143
36081
|
}
|
|
35144
36082
|
}));
|
|
35145
36083
|
}
|
|
36084
|
+
if (this.observeRouting !== null) {
|
|
36085
|
+
promptRouting = {};
|
|
36086
|
+
await Promise.all(["claude", "codex"].map(async (harness) => {
|
|
36087
|
+
try {
|
|
36088
|
+
promptRouting[harness] = await this.observeRouting(harness);
|
|
36089
|
+
} catch {
|
|
36090
|
+
promptRouting[harness] = {
|
|
36091
|
+
harness,
|
|
36092
|
+
state: "unavailable",
|
|
36093
|
+
label: "Not verified",
|
|
36094
|
+
detail: "Native prompt-hook status could not be checked.",
|
|
36095
|
+
configPath: null,
|
|
36096
|
+
configured: null,
|
|
36097
|
+
promptSubmissions: 0,
|
|
36098
|
+
subagentsStarted: 0,
|
|
36099
|
+
subagentsStopped: 0,
|
|
36100
|
+
reportedModels: [],
|
|
36101
|
+
lastObservedAt: null,
|
|
36102
|
+
receiptState: "unavailable"
|
|
36103
|
+
};
|
|
36104
|
+
}
|
|
36105
|
+
}));
|
|
36106
|
+
}
|
|
35146
36107
|
updateAgents();
|
|
35147
36108
|
}),
|
|
35148
36109
|
observe("savings", [
|
|
@@ -35156,7 +36117,7 @@ var init_guided = __esm({
|
|
|
35156
36117
|
observe("checks", ["status"]),
|
|
35157
36118
|
observe("value", ["benchmark-matrix"])
|
|
35158
36119
|
]);
|
|
35159
|
-
const agents = this.agentView(doctor, budget, context, { rules: true, allowance: true }, guidance);
|
|
36120
|
+
const agents = this.agentView(doctor, budget, context, { rules: true, allowance: true }, guidance, promptRouting);
|
|
35160
36121
|
const notices = [];
|
|
35161
36122
|
if (doctor.data === null)
|
|
35162
36123
|
notices.push("The agent inventory could not be read. Check the local installation and refresh.");
|
|
@@ -35184,7 +36145,7 @@ var init_guided = __esm({
|
|
|
35184
36145
|
notices
|
|
35185
36146
|
};
|
|
35186
36147
|
}
|
|
35187
|
-
agentView(doctor, budget, context, complete2, guidance) {
|
|
36148
|
+
agentView(doctor, budget, context, complete2, guidance, promptRouting) {
|
|
35188
36149
|
const present = (doctor.data?.harnesses ?? []).filter((item) => item.state !== "absent" && (item.harnessId === "claude" || item.harnessId === "codex"));
|
|
35189
36150
|
return present.map((agent) => {
|
|
35190
36151
|
const providers = (doctor.data?.providers ?? []).filter((provider) => provider.state === "configured" && provider.configuredHarnesses.includes(agent.harnessId)).map((p) => p.providerId);
|
|
@@ -35207,8 +36168,9 @@ var init_guided = __esm({
|
|
|
35207
36168
|
effort: observed?.nativeEffort?.current ?? observed?.reasoningEffort ?? null,
|
|
35208
36169
|
reasoning: reasoningView(agent.harnessId, observed),
|
|
35209
36170
|
...guidance?.[agent.harnessId] ? { guidance: guidance[agent.harnessId] } : {},
|
|
36171
|
+
...promptRouting?.[agent.harnessId] ? { promptRouting: promptRouting[agent.harnessId] } : {},
|
|
35210
36172
|
allowanceAction: allowanceAction(usage?.diagnostics ?? []),
|
|
35211
|
-
rules: agentRules(agent.harnessId, providers, context.data, guidance?.[agent.harnessId]),
|
|
36173
|
+
rules: agentRules(agent.harnessId, providers, context.data, guidance?.[agent.harnessId], promptRouting?.[agent.harnessId]),
|
|
35212
36174
|
allowance: (usage?.windows ?? []).map((window) => ({
|
|
35213
36175
|
label: window.scope === "five-hour" ? "5-hour allowance" : `${window.scope} allowance`,
|
|
35214
36176
|
remaining: window.remainingPercent,
|
|
@@ -35243,11 +36205,13 @@ var init_guided = __esm({
|
|
|
35243
36205
|
"setup",
|
|
35244
36206
|
"effort",
|
|
35245
36207
|
"skill",
|
|
36208
|
+
"routing-enable",
|
|
36209
|
+
"routing-disable",
|
|
35246
36210
|
"undo",
|
|
35247
36211
|
"remove",
|
|
35248
36212
|
"candidate-setup",
|
|
35249
36213
|
"candidate-remove"
|
|
35250
|
-
].includes(action) || data["harness"] !== void 0 && !["claude", "codex"].includes(String(data["harness"])) || data["harnesses"] !== void 0 && !validHarnesses || data["harnesses"] !== void 0 && action !== "setup" || data["harnesses"] !== void 0 && data["harness"] !== void 0 || data["task"] !== void 0 && !TASKS.has(String(data["task"])) || data["provider"] !== void 0 && !["rtk", "harnesstrim", "mcptoon", "gitnexus", "headroom"].includes(String(data["provider"])) || data["candidate"] !== void 0 && !["mcptoon", "gitnexus"].includes(String(data["candidate"])) || action === "effort" && (data["harness"] === void 0 || data["task"] === void 0) || action === "skill" && data["harness"] === void 0 || action === "remove" && (data["provider"] === void 0 || data["harness"] !== void 0 || data["harnesses"] !== void 0 || data["task"] !== void 0 || data["candidate"] !== void 0) || data["provider"] !== void 0 && action !== "remove" && action !== "setup" || candidateAction && (data["candidate"] === void 0 || data["harness"] === void 0 || data["provider"] !== void 0 || data["task"] !== void 0) || !candidateAction && data["candidate"] !== void 0)
|
|
36214
|
+
].includes(action) || data["harness"] !== void 0 && !["claude", "codex"].includes(String(data["harness"])) || data["harnesses"] !== void 0 && !validHarnesses || data["harnesses"] !== void 0 && action !== "setup" || data["harnesses"] !== void 0 && data["harness"] !== void 0 || data["task"] !== void 0 && !TASKS.has(String(data["task"])) || data["provider"] !== void 0 && !["rtk", "harnesstrim", "mcptoon", "gitnexus", "headroom"].includes(String(data["provider"])) || data["candidate"] !== void 0 && !["mcptoon", "gitnexus"].includes(String(data["candidate"])) || action === "effort" && (data["harness"] === void 0 || data["task"] === void 0) || action === "skill" && data["harness"] === void 0 || (action === "routing-enable" || action === "routing-disable") && data["harness"] === void 0 || action === "remove" && (data["provider"] === void 0 || data["harness"] !== void 0 || data["harnesses"] !== void 0 || data["task"] !== void 0 || data["candidate"] !== void 0) || data["provider"] !== void 0 && action !== "remove" && action !== "setup" || candidateAction && (data["candidate"] === void 0 || data["harness"] === void 0 || data["provider"] !== void 0 || data["task"] !== void 0) || !candidateAction && data["candidate"] !== void 0)
|
|
35251
36215
|
throw new GuideError(400, "Choose a supported agent and action.");
|
|
35252
36216
|
return this.exclusive(async () => {
|
|
35253
36217
|
this.approval = null;
|
|
@@ -35435,13 +36399,17 @@ var init_guided = __esm({
|
|
|
35435
36399
|
args.push("--provider", setupProvider);
|
|
35436
36400
|
if (data["action"] === "skill") {
|
|
35437
36401
|
args.push("--provider", "none", "--agent-skill");
|
|
36402
|
+
} else if (data["action"] === "routing-enable") {
|
|
36403
|
+
args.push("--provider", "none", "--agent-routing");
|
|
36404
|
+
} else if (data["action"] === "routing-disable") {
|
|
36405
|
+
args.push("--provider", "none", "--disable-agent-routing");
|
|
35438
36406
|
} else if (data["action"] === "effort")
|
|
35439
36407
|
args.push("--provider", "none", "--native-policy", "--task", String(data["task"]), "--profile", data["task"] === "mechanical" ? "economy" : data["task"] === "standard" ? "balanced" : "quality");
|
|
35440
36408
|
const result6 = await this.call(args);
|
|
35441
36409
|
const report = result6.data;
|
|
35442
36410
|
if (report === null || result6.exitCode !== 0 || report.conflicts.length > 0 || report.actions.length === 0 || !report.persisted || report.planId === null) {
|
|
35443
36411
|
const subject = setupProvider !== null ? `${name(agent.harnessId)} \xB7 ${name(setupProvider)}` : name(agent.harnessId);
|
|
35444
|
-
notices.push(`${subject}: ${explainGuideIssue(result6.diagnostics, data["action"] === "effort" ? "No supported preference change is needed or available. Your current preference is kept." : data["action"] === "skill" ? "In-session guidance is already present, or an existing user-owned skill location was left untouched." : "No safe setup change is available for the current provider, agent version and platform.")}`);
|
|
36412
|
+
notices.push(`${subject}: ${explainGuideIssue(result6.diagnostics, data["action"] === "effort" ? "No supported preference change is needed or available. Your current preference is kept." : data["action"] === "skill" ? "In-session guidance is already present, or an existing user-owned skill location was left untouched." : data["action"] === "routing-enable" || data["action"] === "routing-disable" ? "No safe native prompt-routing change is available for the current harness, hook state and ownership evidence." : "No safe setup change is available for the current provider, agent version and platform.")}`);
|
|
35445
36413
|
continue;
|
|
35446
36414
|
}
|
|
35447
36415
|
plans.push(report.planId);
|
|
@@ -35451,6 +36419,8 @@ var init_guided = __esm({
|
|
|
35451
36419
|
description: "Installs one reviewed Token Harness Agent Skill in the standard user skill directory. It does not change model, login, billing, hooks, trust, or the current conversation.",
|
|
35452
36420
|
files: 1
|
|
35453
36421
|
});
|
|
36422
|
+
} else if (data["action"] === "routing-enable" || data["action"] === "routing-disable") {
|
|
36423
|
+
changes.push(...report.actions.map((action2) => describeChange(action2, agent.harnessId)));
|
|
35454
36424
|
} else {
|
|
35455
36425
|
changes.push(...report.actions.map((action2) => describeChange(action2, agent.harnessId)));
|
|
35456
36426
|
}
|
|
@@ -35468,7 +36438,7 @@ var init_guided = __esm({
|
|
|
35468
36438
|
plans,
|
|
35469
36439
|
transactionId: null,
|
|
35470
36440
|
provider: null,
|
|
35471
|
-
description: data["action"] === "effort" ? "Task preference" : data["action"] === "skill" ? "In-session guidance" : "Integration setup",
|
|
36441
|
+
description: data["action"] === "effort" ? "Task preference" : data["action"] === "skill" ? "In-session guidance" : data["action"] === "routing-enable" || data["action"] === "routing-disable" ? "Automatic prompt routing" : "Integration setup",
|
|
35472
36442
|
operation: "apply",
|
|
35473
36443
|
network
|
|
35474
36444
|
};
|
|
@@ -35480,7 +36450,7 @@ var init_guided = __esm({
|
|
|
35480
36450
|
notices,
|
|
35481
36451
|
expiresAt: id === null ? null : new Date(expires).toISOString(),
|
|
35482
36452
|
network,
|
|
35483
|
-
restart: data["action"] === "effort" || data["action"] === "skill"
|
|
36453
|
+
restart: data["action"] === "effort" || data["action"] === "skill" || data["action"] === "routing-enable" || data["action"] === "routing-disable"
|
|
35484
36454
|
};
|
|
35485
36455
|
});
|
|
35486
36456
|
}
|
|
@@ -35927,22 +36897,51 @@ var init_guided = __esm({
|
|
|
35927
36897
|
const messages = [];
|
|
35928
36898
|
const results = [];
|
|
35929
36899
|
let ok = true;
|
|
36900
|
+
let healthyAtDeclaredTier = true;
|
|
35930
36901
|
const inventory = await this.call(["doctor"]);
|
|
35931
36902
|
const present = (inventory.data?.harnesses ?? []).filter((item) => item.state !== "absent" && ["claude", "codex"].includes(item.harnessId));
|
|
36903
|
+
if (inventory.data === null) {
|
|
36904
|
+
ok = false;
|
|
36905
|
+
healthyAtDeclaredTier = false;
|
|
36906
|
+
messages.push("The installed-agent inventory could not be read. Refresh and check the local installation.");
|
|
36907
|
+
}
|
|
35932
36908
|
if (present.length === 0) {
|
|
35933
36909
|
ok = false;
|
|
35934
|
-
|
|
36910
|
+
healthyAtDeclaredTier = false;
|
|
36911
|
+
messages.push("No supported installed agent was detected, so no integration was checked.");
|
|
35935
36912
|
}
|
|
35936
36913
|
for (const agent of present) {
|
|
35937
36914
|
const harness = agent.harnessId;
|
|
35938
36915
|
this.record(`Checking ${name(harness)} configuration and available execution evidence. No settings changed.`, "working");
|
|
35939
36916
|
const result6 = await this.call(["verify", "--harness", harness]);
|
|
35940
36917
|
const healthy = result6.data?.healthyAtDeclaredTier === true;
|
|
35941
|
-
|
|
36918
|
+
const versionWarnings = result6.diagnostics.filter((entry) => entry.severity === "warning" && (entry.code === "harness-version-unknown-newer" || entry.code === "provider-version-unknown-newer"));
|
|
36919
|
+
const failed = result6.data === null || result6.exitCode !== 0 || result6.diagnostics.some((entry) => entry.severity === "error" || entry.severity === "warning" && !versionWarnings.includes(entry)) || result6.data.results.some((entry) => entry.status === "degraded" || entry.status === "failed");
|
|
36920
|
+
if (failed)
|
|
35942
36921
|
ok = false;
|
|
36922
|
+
if (!healthy)
|
|
36923
|
+
healthyAtDeclaredTier = false;
|
|
35943
36924
|
if (result6.data !== null)
|
|
35944
36925
|
results.push(...result6.data.results);
|
|
35945
|
-
|
|
36926
|
+
const prefix = `${name(harness)}: `;
|
|
36927
|
+
if (result6.data === null) {
|
|
36928
|
+
messages.push(prefix + "the verification report could not be read. Refresh and check the local installation.");
|
|
36929
|
+
} else if (healthy) {
|
|
36930
|
+
messages.push(prefix + "the available integration checks passed. This is not proof that every command was reduced.");
|
|
36931
|
+
} else if (failed) {
|
|
36932
|
+
messages.push(prefix + "a known integration check failed. Review the specific check before changing setup.");
|
|
36933
|
+
} else if (result6.data.results.length === 0) {
|
|
36934
|
+
messages.push(prefix + "the agent is detected, but no managed optimizer connection is present to verify. Review setup only if you want to connect one.");
|
|
36935
|
+
} else {
|
|
36936
|
+
const pendingProviders = [
|
|
36937
|
+
...new Set(result6.data.results.filter((entry) => entry.status === "not-applicable").map((entry) => name(entry.providerId)))
|
|
36938
|
+
];
|
|
36939
|
+
const subject = pendingProviders.length > 0 ? pendingProviders.join(" and ") : "Some integrations";
|
|
36940
|
+
messages.push(`${prefix}${subject} have not produced enough attributable runtime evidence for ${name(harness)} yet. This is an evidence gap, not a finding that the setup is broken. If you do not use this agent on this machine, no action is required.`);
|
|
36941
|
+
}
|
|
36942
|
+
if (versionWarnings.length > 0) {
|
|
36943
|
+
messages.push(prefix + "the installed version is newer than Token Harness\u2019s recorded compatibility sample; read-only checks can continue, but review the version before changing its integration.");
|
|
36944
|
+
}
|
|
35946
36945
|
}
|
|
35947
36946
|
if (inventory.data !== null) {
|
|
35948
36947
|
const fingerprint = stackFingerprint(inventory.data);
|
|
@@ -35952,7 +36951,7 @@ var init_guided = __esm({
|
|
|
35952
36951
|
receiptId: null,
|
|
35953
36952
|
appliedAt: null,
|
|
35954
36953
|
results,
|
|
35955
|
-
healthyAtDeclaredTier:
|
|
36954
|
+
healthyAtDeclaredTier: healthyAtDeclaredTier && present.length > 0
|
|
35956
36955
|
}
|
|
35957
36956
|
};
|
|
35958
36957
|
this.stackBase = {
|
|
@@ -35968,7 +36967,13 @@ var init_guided = __esm({
|
|
|
35968
36967
|
if (this.cached !== null)
|
|
35969
36968
|
this.cached.value = { ...this.cached.value, stack };
|
|
35970
36969
|
this.record("Integration checks completed. No settings changed.", ok ? "success" : "attention");
|
|
35971
|
-
return {
|
|
36970
|
+
return {
|
|
36971
|
+
ok,
|
|
36972
|
+
title: ok ? healthyAtDeclaredTier ? "Integration checks passed" : "Configuration checks complete; runtime evidence pending" : "Integration checks need attention",
|
|
36973
|
+
messages,
|
|
36974
|
+
appliedPlans: 0,
|
|
36975
|
+
stack
|
|
36976
|
+
};
|
|
35972
36977
|
});
|
|
35973
36978
|
}
|
|
35974
36979
|
};
|
|
@@ -38470,6 +39475,31 @@ var init_guided_product_client = __esm({
|
|
|
38470
39475
|
'caption',
|
|
38471
39476
|
),
|
|
38472
39477
|
);
|
|
39478
|
+
const routing = agent.promptRouting;
|
|
39479
|
+
const routingCard = node('div', undefined, 'routing-feature');
|
|
39480
|
+
const routingHead = node('div', undefined, 'tool-head');
|
|
39481
|
+
routingHead.append(
|
|
39482
|
+
node('strong', 'Automatic prompt routing'),
|
|
39483
|
+
pill(routing?.label || 'Not verified', routing?.state === 'managed' ? 'good' : routing?.state === 'absent' ? '' : 'warn'),
|
|
39484
|
+
);
|
|
39485
|
+
routingCard.append(
|
|
39486
|
+
routingHead,
|
|
39487
|
+
node(
|
|
39488
|
+
'p',
|
|
39489
|
+
routing?.detail || 'A native hook can inject the routing policy on every submitted prompt. Setup and runtime activity are tracked separately.',
|
|
39490
|
+
'caption',
|
|
39491
|
+
),
|
|
39492
|
+
);
|
|
39493
|
+
const routingActions = node('div', undefined, 'inline-actions');
|
|
39494
|
+
if (routing?.state === 'absent') {
|
|
39495
|
+
routingActions.append(actionButton('Enable routing', () => reviewPromptRouting(agent.id, true), 'secondary'));
|
|
39496
|
+
} else if (routing?.state === 'managed') {
|
|
39497
|
+
routingActions.append(actionButton('Disable routing', () => reviewPromptRouting(agent.id, false), 'secondary'));
|
|
39498
|
+
} else if (routing?.state === 'external') {
|
|
39499
|
+
routingActions.append(node('span', 'Managed elsewhere · left untouched', 'caption'));
|
|
39500
|
+
}
|
|
39501
|
+
if (routingActions.children.length) routingCard.append(routingActions);
|
|
39502
|
+
card.append(routingCard);
|
|
38473
39503
|
if (baseline.unavailable.length) {
|
|
38474
39504
|
const details = node('details', undefined, 'agent-details');
|
|
38475
39505
|
details.append(node('summary', 'Connection limitations'));
|
|
@@ -38561,6 +39591,57 @@ var init_guided_product_client = __esm({
|
|
|
38561
39591
|
});
|
|
38562
39592
|
}
|
|
38563
39593
|
|
|
39594
|
+
function reviewPromptRouting(agentId, enabled) {
|
|
39595
|
+
if (busy) return;
|
|
39596
|
+
const run = modal((enabled ? 'Enable' : 'Disable') + ' automatic routing · ' + agentName(agentId));
|
|
39597
|
+
$('modal-content').append(
|
|
39598
|
+
messageBox(
|
|
39599
|
+
'How this works',
|
|
39600
|
+
enabled
|
|
39601
|
+
? 'Token Harness adds a native UserPromptSubmit hook that supplies a short routing policy on each prompt. The agent may delegate eligible bounded work to a lower-cost native subagent; the root model stays the same.'
|
|
39602
|
+
: 'Token Harness removes only the exact native routing entries it owns. User-edited or manually installed hooks remain untouched.',
|
|
39603
|
+
),
|
|
39604
|
+
progress('Preparing a read-only plan', 'No harness settings change until you approve the exact preview.'),
|
|
39605
|
+
);
|
|
39606
|
+
$('modal-actions').append(modalClose('Cancel'));
|
|
39607
|
+
setBusy(true, false);
|
|
39608
|
+
ensureSession()
|
|
39609
|
+
.then(() => request('/api/preview', {
|
|
39610
|
+
action: enabled ? 'routing-enable' : 'routing-disable',
|
|
39611
|
+
harness: agentId,
|
|
39612
|
+
}))
|
|
39613
|
+
.then(data => {
|
|
39614
|
+
if (run !== modalRun || !$('modal').open) return;
|
|
39615
|
+
pendingTicket = data.ticket;
|
|
39616
|
+
$('modal-content').replaceChildren();
|
|
39617
|
+
for (const change of data.changes || []) {
|
|
39618
|
+
const item = node('article', undefined, 'preview-change');
|
|
39619
|
+
item.append(node('h3', change.title), node('p', change.description));
|
|
39620
|
+
$('modal-content').append(item);
|
|
39621
|
+
}
|
|
39622
|
+
if (!(data.changes || []).length)
|
|
39623
|
+
$('modal-content').append(messageBox('No change proposed', (data.notices || []).join(' ') || 'The current routing state or ownership evidence does not support a safe change.'));
|
|
39624
|
+
for (const notice of data.notices || []) $('modal-content').append(node('p', notice, 'notice-row'));
|
|
39625
|
+
if (data.ticket) $('modal-content').append(messageBox(
|
|
39626
|
+
agentId === 'codex' ? 'Codex trust step' : 'When it takes effect',
|
|
39627
|
+
agentId === 'codex'
|
|
39628
|
+
? 'After Apply, review and trust the UserPromptSubmit hook in Codex using /hooks. Until a callback is observed, the dashboard will show it as configured but not runtime verified.'
|
|
39629
|
+
: 'After Apply, start a new Claude Code session. The dashboard will show configured state first and runtime activity after the next prompt callback.',
|
|
39630
|
+
'safe',
|
|
39631
|
+
));
|
|
39632
|
+
$('modal-actions').replaceChildren(modalClose(data.ticket ? 'Cancel' : 'Done'));
|
|
39633
|
+
if (data.ticket) $('modal-actions').append(actionButton(enabled ? 'Apply routing hook' : 'Remove owned routing hook', () => applyTicket(data.ticket)));
|
|
39634
|
+
})
|
|
39635
|
+
.catch(error => {
|
|
39636
|
+
if (run !== modalRun) return;
|
|
39637
|
+
$('modal-error').textContent = error.message;
|
|
39638
|
+
$('modal-error').hidden = false;
|
|
39639
|
+
})
|
|
39640
|
+
.finally(() => {
|
|
39641
|
+
if (run === modalRun) setBusy(false, false);
|
|
39642
|
+
});
|
|
39643
|
+
}
|
|
39644
|
+
|
|
38564
39645
|
function reviewSetup(providerId = null) {
|
|
38565
39646
|
if (busy) return;
|
|
38566
39647
|
const choices = setupChoiceData(providerId);
|
|
@@ -39251,10 +40332,6 @@ var init_guided_product_client = __esm({
|
|
|
39251
40332
|
node('strong', component?.configuredHarnesses?.length ? component.configuredHarnesses.map(agentName).join(', ') : 'No detected agent'),
|
|
39252
40333
|
);
|
|
39253
40334
|
const measured = rows.filter(row => row.providerId === id);
|
|
39254
|
-
facts.append(
|
|
39255
|
-
node('span', 'Recorded results'),
|
|
39256
|
-
node('strong', measured.length ? measured.length + ' recorded result' + (measured.length === 1 ? '' : 's') : 'None in this period'),
|
|
39257
|
-
);
|
|
39258
40335
|
card.append(facts);
|
|
39259
40336
|
if (!measured.length) {
|
|
39260
40337
|
card.append(
|
|
@@ -39358,6 +40435,29 @@ var init_guided_product_client = __esm({
|
|
|
39358
40435
|
metricCard('5h / 7d allowance', allowance.value, allowance.detail, allowance.cls),
|
|
39359
40436
|
metricCard('Quality', quality.value, quality.detail, quality.cls),
|
|
39360
40437
|
);
|
|
40438
|
+
const routed = current?.value?.routing;
|
|
40439
|
+
const quotaParts = [];
|
|
40440
|
+
if (routed?.allowance5h?.state === 'measured' && routed.allowance5h.savedPercent !== null)
|
|
40441
|
+
quotaParts.push(routed.allowance5h.savedPercent >= 0
|
|
40442
|
+
? '5h saved ' + count(routed.allowance5h.savedPercent) + '%'
|
|
40443
|
+
: '5h use +' + count(Math.abs(routed.allowance5h.savedPercent)) + '%');
|
|
40444
|
+
if (routed?.allowance7d?.state === 'measured' && routed.allowance7d.savedPercent !== null)
|
|
40445
|
+
quotaParts.push(routed.allowance7d.savedPercent >= 0
|
|
40446
|
+
? '7d saved ' + count(routed.allowance7d.savedPercent) + '%'
|
|
40447
|
+
: '7d use +' + count(Math.abs(routed.allowance7d.savedPercent)) + '%');
|
|
40448
|
+
const routingValue = routed?.state === 'blocked-by-quality'
|
|
40449
|
+
? 'Not credited'
|
|
40450
|
+
: routed?.savedLocalTokens !== null && routed?.savedLocalTokens !== undefined
|
|
40451
|
+
? (routed.savedLocalTokens >= 0
|
|
40452
|
+
? count(routed.savedLocalTokens) + ' tokens saved' + (routed.localTokenSavingPercent === null ? '' : ' · ' + count(routed.localTokenSavingPercent) + '%')
|
|
40453
|
+
: count(Math.abs(routed.savedLocalTokens)) + ' tokens added' + (routed.localTokenSavingPercent === null ? '' : ' · ' + count(Math.abs(routed.localTokenSavingPercent)) + '%'))
|
|
40454
|
+
: quotaParts.length ? 'Allowance measured' : routed?.state === 'measured' ? 'Usage unavailable' : 'Not measured yet';
|
|
40455
|
+
const routingDetail = routed?.state === 'blocked-by-quality'
|
|
40456
|
+
? routed.basis
|
|
40457
|
+
: (quotaParts.length ? quotaParts.join(' · ') + '. ' : '') +
|
|
40458
|
+
(routed?.pairs ? count(routed.pairs) + ' quality-passed routed pair(s). ' : '') +
|
|
40459
|
+
'Local tokens and allowance percentages are separate measurements. Actual child model is not exposed by every harness hook.';
|
|
40460
|
+
$('result-summary').append(metricCard('Automatic routing', routingValue, routingDetail, routed?.state === 'measured' ? 'positive' : ''));
|
|
39361
40461
|
renderResultOptimizers();
|
|
39362
40462
|
renderResultAgents();
|
|
39363
40463
|
renderSavings();
|
|
@@ -39505,6 +40605,7 @@ var init_guided_product_styles = __esm({
|
|
|
39505
40605
|
.setup-step{margin:1.6rem 0}.step-heading{display:grid;grid-template-columns:34px 1fr;gap:.65rem;align-items:start;margin-bottom:.7rem}.step-number{display:grid;place-items:center;width:32px;height:32px;border-radius:9px;background:var(--accent);color:#fff;font-weight:900}.step-heading h2{margin:0}.step-heading p{margin:.2rem 0;color:var(--muted)}
|
|
39506
40606
|
.connection-overview{display:grid;gap:.75rem}.connection-summary{display:flex;align-items:center;justify-content:space-between;gap:1rem;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1rem}.connection-summary p{margin:.15rem 0 0}.connection-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel)}.connection-table{min-width:max(720px,100%)}.connection-row{display:grid;grid-template-columns:minmax(170px,1.25fr) repeat(var(--connection-columns),minmax(130px,1fr)) minmax(155px,.8fr);align-items:center;gap:.6rem;padding:.72rem .8rem;border-bottom:1px solid var(--line)}.connection-row:last-child{border-bottom:0}.connection-head{background:var(--panel-soft);color:var(--muted);font-size:.8rem}.connection-name{display:grid;gap:.12rem}.connection-cell,.connection-action{min-width:0}.connection-action{display:flex;justify-content:flex-end}.tool-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem}.candidate-comparison-toolbar{grid-column:1/-1;justify-content:flex-end;align-self:start}.tool-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1rem;box-shadow:var(--shadow)}.tool-card.experimental{border-style:dashed}.tool-card.compact{box-shadow:none}.tool-card>p{color:var(--muted);margin:.65rem 0}.tool-head{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem}.tool-head h3{margin:0}.tool-facts{display:grid;grid-template-columns:auto 1fr;gap:.3rem .75rem;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:.65rem 0;margin:.65rem 0}.tool-facts span{color:var(--muted);font-size:.8rem}.tool-facts strong{font-size:.85rem}
|
|
39507
40607
|
.connection-role{max-width:28ch}.setup-choice-list{display:grid;gap:.55rem;margin:.9rem 0}.setup-choice-list h3{margin:.25rem 0 0}.setup-choice{display:grid;grid-template-columns:auto 1fr;align-items:start;gap:.7rem;padding:.8rem;border:1px solid var(--line);border-radius:12px;background:var(--panel);cursor:pointer}.setup-choice:hover{border-color:var(--accent);background:var(--accent-soft)}.setup-choice input{inline-size:1.1rem;block-size:1.1rem;margin:.15rem 0 0;accent-color:var(--accent)}.setup-choice-copy{display:grid;gap:.2rem}.setup-choice-limitation{color:var(--muted)}
|
|
40608
|
+
.routing-feature{margin:.8rem 0;padding:.8rem;border:1px solid var(--line);border-radius:12px;background:var(--panel-soft)}.routing-feature .tool-head{align-items:center}.routing-feature p{margin:.55rem 0;color:var(--muted)}
|
|
39508
40609
|
.managed-action-box{margin-top:.8rem;background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;padding:.85rem}.managed-action-box p{margin:.1rem 0 .65rem}
|
|
39509
40610
|
.maintenance-list{display:grid;gap:.55rem}.maintenance-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:.8rem}.maintenance-row p{margin:.15rem 0}
|
|
39510
40611
|
.explain-box{background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;padding:.8rem;margin:.6rem 0}.explain-box p{margin:.25rem 0;color:var(--muted)}.explain-box.warn{background:var(--warn-soft);border-color:color-mix(in srgb,var(--warn) 35%,var(--line))}.explain-box.safe{background:var(--good-soft);border-color:color-mix(in srgb,var(--good) 30%,var(--line))}.operation-progress{margin:.75rem 0;padding:.8rem;border:1px solid var(--line);border-radius:12px}.operation-progress p{margin:.35rem 0 0}
|
|
@@ -40185,7 +41286,7 @@ ${GUIDE_CANDIDATE_READINESS_JS}`;
|
|
|
40185
41286
|
</div>
|
|
40186
41287
|
|
|
40187
41288
|
<section class="setup-step" id="coding-agents">
|
|
40188
|
-
<div class="section-title"><div><h2>Coding agents</h2><p>
|
|
41289
|
+
<div class="section-title"><div><h2>Coding agents</h2><p>Enable automatic per-prompt routing here for each detected coding app. The card distinguishes hook configuration from callbacks actually observed at runtime.</p></div></div>
|
|
40189
41290
|
<div id="setup-agents" class="tool-grid"><article class="tool-card"><h3>Checking agents\u2026</h3></article></div>
|
|
40190
41291
|
<details class="disclosure advanced-disclosure">
|
|
40191
41292
|
<summary>Agent details and optional reasoning settings</summary>
|
|
@@ -40653,6 +41754,19 @@ async function runAsDatabaseReader(argv2) {
|
|
|
40653
41754
|
process5.exitCode = 0;
|
|
40654
41755
|
return true;
|
|
40655
41756
|
}
|
|
41757
|
+
function parsePromptRouterEvent(value3) {
|
|
41758
|
+
if (value3 === "prompt-submit" || value3 === "subagent-start" || value3 === "subagent-stop")
|
|
41759
|
+
return value3;
|
|
41760
|
+
return null;
|
|
41761
|
+
}
|
|
41762
|
+
function emitPromptRouterContext(harness) {
|
|
41763
|
+
process5.stdout.write(JSON.stringify({
|
|
41764
|
+
hookSpecificOutput: {
|
|
41765
|
+
hookEventName: "UserPromptSubmit",
|
|
41766
|
+
additionalContext: ROUTING_CONTEXT[harness]
|
|
41767
|
+
}
|
|
41768
|
+
}) + "\n");
|
|
41769
|
+
}
|
|
40656
41770
|
async function readStandardInput() {
|
|
40657
41771
|
const chunks = [];
|
|
40658
41772
|
let bytes = 0;
|
|
@@ -40677,6 +41791,16 @@ async function main(argv2) {
|
|
|
40677
41791
|
}
|
|
40678
41792
|
return;
|
|
40679
41793
|
}
|
|
41794
|
+
if (argv2[0] === PROMPT_ROUTER_FLAG && argv2[2] === "--check") {
|
|
41795
|
+
if (argv2[1] === "claude" || argv2[1] === "codex") {
|
|
41796
|
+
process5.stdout.write(`${PROMPT_ROUTER_CHECK_MARKER2}
|
|
41797
|
+
`);
|
|
41798
|
+
process5.exitCode = EXIT_CODES.ok;
|
|
41799
|
+
} else {
|
|
41800
|
+
process5.exitCode = EXIT_CODES["usage-error"];
|
|
41801
|
+
}
|
|
41802
|
+
return;
|
|
41803
|
+
}
|
|
40680
41804
|
const opensGuide = argv2.length === 0 || argv2[0] === "start" || argv2[0] === "ui";
|
|
40681
41805
|
const readOnly = argv2.includes("--read-only");
|
|
40682
41806
|
const uiInvocation = opensGuide ? parseUiArgs(argv2.slice(1).filter((arg) => arg !== "--read-only")) : null;
|
|
@@ -40746,6 +41870,34 @@ Run token-harness ui --help for usage.
|
|
|
40746
41870
|
env: process5.env,
|
|
40747
41871
|
stdoutIsTty: process5.stdout.isTTY === true
|
|
40748
41872
|
};
|
|
41873
|
+
if (argv2[0] === PROMPT_ROUTER_FLAG) {
|
|
41874
|
+
const selected = argv2[1];
|
|
41875
|
+
const event = parsePromptRouterEvent(argv2[2]);
|
|
41876
|
+
if (selected !== "claude" && selected !== "codex" || event === null) {
|
|
41877
|
+
process5.exitCode = EXIT_CODES.ok;
|
|
41878
|
+
return;
|
|
41879
|
+
}
|
|
41880
|
+
const input = await readStandardInput();
|
|
41881
|
+
if (resolution.ok && fs !== null && input !== null) {
|
|
41882
|
+
try {
|
|
41883
|
+
const projectId = attribution.salt === null ? null : deriveProjectId(process5.cwd(), attribution.salt, resolution.environment.facts.os === "windows");
|
|
41884
|
+
await recordNativePromptRoutingHook({
|
|
41885
|
+
fs,
|
|
41886
|
+
stateRoot: resolution.environment.paths.state,
|
|
41887
|
+
harness: selected,
|
|
41888
|
+
event,
|
|
41889
|
+
projectId,
|
|
41890
|
+
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41891
|
+
hookInput: input
|
|
41892
|
+
});
|
|
41893
|
+
} catch {
|
|
41894
|
+
}
|
|
41895
|
+
}
|
|
41896
|
+
if (event === "prompt-submit")
|
|
41897
|
+
emitPromptRouterContext(selected);
|
|
41898
|
+
process5.exitCode = EXIT_CODES.ok;
|
|
41899
|
+
return;
|
|
41900
|
+
}
|
|
40749
41901
|
if (argv2[0] === RTK_HOOK_PROXY_FLAG) {
|
|
40750
41902
|
const selected = argv2[1];
|
|
40751
41903
|
if (selected !== "claude" && selected !== "codex") {
|
|
@@ -40968,6 +42120,35 @@ async function runGuidedUi(options, base) {
|
|
|
40968
42120
|
stateRoot: base.stateRoot ?? null,
|
|
40969
42121
|
harness
|
|
40970
42122
|
});
|
|
42123
|
+
}, async (harness) => {
|
|
42124
|
+
if (base.adapters === null || base.adapters === void 0 || base.platform === null) {
|
|
42125
|
+
return {
|
|
42126
|
+
harness,
|
|
42127
|
+
state: "unavailable",
|
|
42128
|
+
label: "Not verified",
|
|
42129
|
+
detail: "The local filesystem is unavailable, so native prompt routing cannot be checked.",
|
|
42130
|
+
configPath: null,
|
|
42131
|
+
configured: null,
|
|
42132
|
+
promptSubmissions: 0,
|
|
42133
|
+
subagentsStarted: 0,
|
|
42134
|
+
subagentsStopped: 0,
|
|
42135
|
+
reportedModels: [],
|
|
42136
|
+
lastObservedAt: null,
|
|
42137
|
+
receiptState: "unavailable"
|
|
42138
|
+
};
|
|
42139
|
+
}
|
|
42140
|
+
return observeNativePromptRouting({
|
|
42141
|
+
fs: base.adapters.fs,
|
|
42142
|
+
home: base.home,
|
|
42143
|
+
stateRoot: base.stateRoot ?? null,
|
|
42144
|
+
harness: harnessId(harness),
|
|
42145
|
+
version: null,
|
|
42146
|
+
runner: base.adapters.runner,
|
|
42147
|
+
facts: base.platform,
|
|
42148
|
+
paths: base.adapters.paths,
|
|
42149
|
+
projectRoot: base.cwd,
|
|
42150
|
+
projectId: base.adapters.projectIdFor(base.cwd)
|
|
42151
|
+
});
|
|
40971
42152
|
});
|
|
40972
42153
|
const token = randomBytes2(32).toString("hex");
|
|
40973
42154
|
let authority = "";
|
|
@@ -41068,7 +42249,7 @@ async function runSavingsView(args, base) {
|
|
|
41068
42249
|
}
|
|
41069
42250
|
return result6.exitCode;
|
|
41070
42251
|
}
|
|
41071
|
-
var RTK_HOOK_PROXY_FLAG, MAX_HOOK_INPUT_BYTES, UI_SECURITY_HEADERS;
|
|
42252
|
+
var RTK_HOOK_PROXY_FLAG, PROMPT_ROUTER_FLAG, PROMPT_ROUTER_CHECK_MARKER2, MAX_HOOK_INPUT_BYTES, ROUTING_CONTEXT, UI_SECURITY_HEADERS;
|
|
41072
42253
|
var init_main = __esm({
|
|
41073
42254
|
"apps/cli/dist/src/main.js"() {
|
|
41074
42255
|
"use strict";
|
|
@@ -41079,11 +42260,19 @@ var init_main = __esm({
|
|
|
41079
42260
|
init_version2();
|
|
41080
42261
|
init_guided();
|
|
41081
42262
|
init_agent_skill();
|
|
42263
|
+
init_prompt_router();
|
|
41082
42264
|
init_guided_candidate_campaign_status();
|
|
41083
42265
|
init_guided_http();
|
|
41084
42266
|
init_rtk_hook_proxy();
|
|
42267
|
+
init_prompt_router();
|
|
41085
42268
|
RTK_HOOK_PROXY_FLAG = "__internal-rtk-hook";
|
|
42269
|
+
PROMPT_ROUTER_FLAG = "__internal-prompt-router";
|
|
42270
|
+
PROMPT_ROUTER_CHECK_MARKER2 = "token-harness-prompt-router-v1";
|
|
41086
42271
|
MAX_HOOK_INPUT_BYTES = 1024 * 1024;
|
|
42272
|
+
ROUTING_CONTEXT = {
|
|
42273
|
+
codex: "For substantial coding work, delegate at most one independent bounded subtask to a native subagent with gpt-6-luna if available and the root is not Luna. Keep trivial, coupled, security, architecture, release, and integration decisions on the root. Specify the model; if unavailable, stay on the root. The root reviews. Claim savings only from paired, quality-gated measurements.",
|
|
42274
|
+
claude: "For substantial coding work, delegate at most one independent bounded subtask to a native subagent with the current Haiku alias if available and cheaper than the root. Keep trivial, coupled, security, architecture, release, and integration decisions on the root. Specify the model; if unavailable, stay on the root. The root reviews. Claim savings only from paired, quality-gated measurements."
|
|
42275
|
+
};
|
|
41087
42276
|
UI_SECURITY_HEADERS = {
|
|
41088
42277
|
"Cache-Control": "no-store",
|
|
41089
42278
|
"Content-Security-Policy": "default-src 'self'; script-src 'self'; style-src 'self'; connect-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'",
|