@event4u/agent-config 12.1.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +151 -0
- package/README.md +1 -1
- package/dist/agent-src/commands/cost/report.md +23 -0
- package/dist/agent-src/contexts/execution/subagent-routing.md +148 -33
- package/dist/agent-src/contexts/subagent-configuration.md +69 -7
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/design-fidelity.md +1 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +10 -5
- package/dist/agent-src/rules/evaluator-independence.md +27 -5
- package/dist/agent-src/rules/git-history-discipline.md +5 -1
- package/dist/agent-src/rules/missing-skill-recovery.md +89 -0
- package/dist/agent-src/rules/ui-audit-gate.md +9 -4
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +33 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +17 -2
- package/dist/agent-src/skills/authz-review/SKILL.md +4 -0
- package/dist/agent-src/skills/design-system-capture/SKILL.md +4 -0
- package/dist/agent-src/skills/design-system-capture/references/snapshot-preference-order.md +77 -0
- package/dist/agent-src/skills/merge-conflicts/SKILL.md +4 -0
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +17 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +4 -4
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +4 -0
- package/dist/agent-src/skills/threat-modeling/SKILL.md +3 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/{chunk-O52B4F5S.js → chunk-3B72LSZL.js} +1 -1
- package/dist/cli-delegate/{chunk-55WZN5VF.js → chunk-EVTY7ISR.js} +2 -2
- package/dist/cli-delegate/{chunk-K34QTSD5.js → chunk-N7FEST6D.js} +17 -17
- package/dist/cli-delegate/{chunk-LKZ5DOYW.js → chunk-XURJ4AQC.js} +11 -3
- package/dist/cli-delegate/cmd_conformance.js +2 -2
- package/dist/cli-delegate/cmd_doctor.js +2 -2
- package/dist/cli-delegate/cmd_export.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +2 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +2 -2
- package/dist/cli-delegate/cmd_uninstall.js +2 -2
- package/dist/cli-delegate/cmd_validate.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +43 -22
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +936 -346
- package/dist/install/install.mjs +12 -4
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1192 -160
- package/dist/router.json +1 -1
- package/dist/server/schemas/settings.js +2 -2
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/guidelines/design-fidelity-mechanics.md +21 -0
- package/docs/guidelines/design-handover-extraction.md +87 -0
- package/docs/guidelines/prompt-templates.md +24 -1
- package/package.json +1 -1
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +33 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +17 -2
- package/src/config/evaluator-budgets.json +5 -4
- package/src/config/gate-coverage.yml +33 -11
- package/src/config/gate-violation-baselines.json +9 -3
- package/src/config/hook-token-budget.json +8 -1
- package/src/scripts/_lib/bench_ab_complexity.ts +439 -0
- package/src/scripts/_lib/bench_ab_safety_tier.ts +142 -0
- package/src/scripts/_lib/bench_ab_scoring_v2.ts +28 -3
- package/src/scripts/_lib/bench_ab_search_adherence.ts +423 -0
- package/src/scripts/_lib/bench_ab_size_claim.ts +206 -0
- package/src/scripts/_lib/bench_ab_workspace.ts +111 -0
- package/src/scripts/_lib/skill_catalogue.ts +258 -5
- package/src/scripts/_lib/tier_budget_routing.ts +31 -331
- package/src/scripts/ai_council/clients.ts +21 -21
- package/src/scripts/bench_ab_v2_complexity.ts +252 -0
- package/src/scripts/bench_ab_v2_run.ts +3 -42
- package/src/scripts/bench_ab_v2_safety.ts +296 -0
- package/src/scripts/bench_ab_v2_search.ts +343 -0
- package/src/scripts/bench_ab_v2_stats.ts +191 -0
- package/src/scripts/build_archive_index.ts +383 -0
- package/src/scripts/capture_skill_catalogue.ts +107 -2
- package/src/scripts/check_source_size_budget.ts +428 -0
- package/src/scripts/check_suppression_hygiene.ts +5 -1
- package/src/scripts/cost/backfill_rates.mjs +298 -0
- package/src/scripts/cost/budget.mjs +12 -32
- package/src/scripts/cost_summary.ts +25 -0
- package/src/scripts/external_sources_denylist.json +1 -0
- package/src/scripts/hook_manifest.yaml +28 -2
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/skill_route_hook.ts +226 -0
- package/src/scripts/hooks/ui_route_nudge_hook.ts +6 -3
- package/src/scripts/lint_design_antipattern_parity.ts +40 -6
- package/src/scripts/lint_harvest_provenance.ts +35 -1
- package/src/scripts/lint_rule_skill_pack_reach.ts +43 -0
- package/src/scripts/lint_skill_router_head.ts +21 -0
- package/src/scripts/mcp_server/consumer_tool_catalog.json +26 -3
- package/src/scripts/mcp_server/tool_catalog_source.ts +6 -24
- package/src/scripts/mcp_server/tools.ts +87 -0
- package/src/scripts/release.ts +5 -5
- package/src/scripts/routing_doctor.ts +50 -13
- package/src/scripts/schemas/command.schema.json +1 -1
- package/src/scripts/schemas/skill.schema.json +18 -1
- package/src/scripts/trigger_coverage.ts +224 -3
- package/src/server/schemas/settings.ts +2 -2
- package/src/config/budget-routing.json +0 -7
package/dist/mcp/server.mjs
CHANGED
|
@@ -1841,17 +1841,17 @@ var require_visit = __commonJS({
|
|
|
1841
1841
|
visit.BREAK = BREAK;
|
|
1842
1842
|
visit.SKIP = SKIP;
|
|
1843
1843
|
visit.REMOVE = REMOVE;
|
|
1844
|
-
function visit_(key, node, visitor,
|
|
1845
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
1844
|
+
function visit_(key, node, visitor, path77) {
|
|
1845
|
+
const ctrl = callVisitor(key, node, visitor, path77);
|
|
1846
1846
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
1847
|
-
replaceNode(key,
|
|
1848
|
-
return visit_(key, ctrl, visitor,
|
|
1847
|
+
replaceNode(key, path77, ctrl);
|
|
1848
|
+
return visit_(key, ctrl, visitor, path77);
|
|
1849
1849
|
}
|
|
1850
1850
|
if (typeof ctrl !== "symbol") {
|
|
1851
1851
|
if (identity.isCollection(node)) {
|
|
1852
|
-
|
|
1852
|
+
path77 = Object.freeze(path77.concat(node));
|
|
1853
1853
|
for (let i = 0; i < node.items.length; ++i) {
|
|
1854
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
1854
|
+
const ci = visit_(i, node.items[i], visitor, path77);
|
|
1855
1855
|
if (typeof ci === "number")
|
|
1856
1856
|
i = ci - 1;
|
|
1857
1857
|
else if (ci === BREAK)
|
|
@@ -1862,13 +1862,13 @@ var require_visit = __commonJS({
|
|
|
1862
1862
|
}
|
|
1863
1863
|
}
|
|
1864
1864
|
} else if (identity.isPair(node)) {
|
|
1865
|
-
|
|
1866
|
-
const ck = visit_("key", node.key, visitor,
|
|
1865
|
+
path77 = Object.freeze(path77.concat(node));
|
|
1866
|
+
const ck = visit_("key", node.key, visitor, path77);
|
|
1867
1867
|
if (ck === BREAK)
|
|
1868
1868
|
return BREAK;
|
|
1869
1869
|
else if (ck === REMOVE)
|
|
1870
1870
|
node.key = null;
|
|
1871
|
-
const cv = visit_("value", node.value, visitor,
|
|
1871
|
+
const cv = visit_("value", node.value, visitor, path77);
|
|
1872
1872
|
if (cv === BREAK)
|
|
1873
1873
|
return BREAK;
|
|
1874
1874
|
else if (cv === REMOVE)
|
|
@@ -1889,17 +1889,17 @@ var require_visit = __commonJS({
|
|
|
1889
1889
|
visitAsync.BREAK = BREAK;
|
|
1890
1890
|
visitAsync.SKIP = SKIP;
|
|
1891
1891
|
visitAsync.REMOVE = REMOVE;
|
|
1892
|
-
async function visitAsync_(key, node, visitor,
|
|
1893
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
1892
|
+
async function visitAsync_(key, node, visitor, path77) {
|
|
1893
|
+
const ctrl = await callVisitor(key, node, visitor, path77);
|
|
1894
1894
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
1895
|
-
replaceNode(key,
|
|
1896
|
-
return visitAsync_(key, ctrl, visitor,
|
|
1895
|
+
replaceNode(key, path77, ctrl);
|
|
1896
|
+
return visitAsync_(key, ctrl, visitor, path77);
|
|
1897
1897
|
}
|
|
1898
1898
|
if (typeof ctrl !== "symbol") {
|
|
1899
1899
|
if (identity.isCollection(node)) {
|
|
1900
|
-
|
|
1900
|
+
path77 = Object.freeze(path77.concat(node));
|
|
1901
1901
|
for (let i = 0; i < node.items.length; ++i) {
|
|
1902
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
1902
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path77);
|
|
1903
1903
|
if (typeof ci === "number")
|
|
1904
1904
|
i = ci - 1;
|
|
1905
1905
|
else if (ci === BREAK)
|
|
@@ -1910,13 +1910,13 @@ var require_visit = __commonJS({
|
|
|
1910
1910
|
}
|
|
1911
1911
|
}
|
|
1912
1912
|
} else if (identity.isPair(node)) {
|
|
1913
|
-
|
|
1914
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
1913
|
+
path77 = Object.freeze(path77.concat(node));
|
|
1914
|
+
const ck = await visitAsync_("key", node.key, visitor, path77);
|
|
1915
1915
|
if (ck === BREAK)
|
|
1916
1916
|
return BREAK;
|
|
1917
1917
|
else if (ck === REMOVE)
|
|
1918
1918
|
node.key = null;
|
|
1919
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
1919
|
+
const cv = await visitAsync_("value", node.value, visitor, path77);
|
|
1920
1920
|
if (cv === BREAK)
|
|
1921
1921
|
return BREAK;
|
|
1922
1922
|
else if (cv === REMOVE)
|
|
@@ -1943,23 +1943,23 @@ var require_visit = __commonJS({
|
|
|
1943
1943
|
}
|
|
1944
1944
|
return visitor;
|
|
1945
1945
|
}
|
|
1946
|
-
function callVisitor(key, node, visitor,
|
|
1946
|
+
function callVisitor(key, node, visitor, path77) {
|
|
1947
1947
|
if (typeof visitor === "function")
|
|
1948
|
-
return visitor(key, node,
|
|
1948
|
+
return visitor(key, node, path77);
|
|
1949
1949
|
if (identity.isMap(node))
|
|
1950
|
-
return visitor.Map?.(key, node,
|
|
1950
|
+
return visitor.Map?.(key, node, path77);
|
|
1951
1951
|
if (identity.isSeq(node))
|
|
1952
|
-
return visitor.Seq?.(key, node,
|
|
1952
|
+
return visitor.Seq?.(key, node, path77);
|
|
1953
1953
|
if (identity.isPair(node))
|
|
1954
|
-
return visitor.Pair?.(key, node,
|
|
1954
|
+
return visitor.Pair?.(key, node, path77);
|
|
1955
1955
|
if (identity.isScalar(node))
|
|
1956
|
-
return visitor.Scalar?.(key, node,
|
|
1956
|
+
return visitor.Scalar?.(key, node, path77);
|
|
1957
1957
|
if (identity.isAlias(node))
|
|
1958
|
-
return visitor.Alias?.(key, node,
|
|
1958
|
+
return visitor.Alias?.(key, node, path77);
|
|
1959
1959
|
return void 0;
|
|
1960
1960
|
}
|
|
1961
|
-
function replaceNode(key,
|
|
1962
|
-
const parent =
|
|
1961
|
+
function replaceNode(key, path77, node) {
|
|
1962
|
+
const parent = path77[path77.length - 1];
|
|
1963
1963
|
if (identity.isCollection(parent)) {
|
|
1964
1964
|
parent.items[key] = node;
|
|
1965
1965
|
} else if (identity.isPair(parent)) {
|
|
@@ -2569,10 +2569,10 @@ var require_Collection = __commonJS({
|
|
|
2569
2569
|
var createNode = require_createNode();
|
|
2570
2570
|
var identity = require_identity();
|
|
2571
2571
|
var Node = require_Node();
|
|
2572
|
-
function collectionFromPath(schema,
|
|
2572
|
+
function collectionFromPath(schema, path77, value) {
|
|
2573
2573
|
let v = value;
|
|
2574
|
-
for (let i =
|
|
2575
|
-
const k =
|
|
2574
|
+
for (let i = path77.length - 1; i >= 0; --i) {
|
|
2575
|
+
const k = path77[i];
|
|
2576
2576
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
2577
2577
|
const a = [];
|
|
2578
2578
|
a[k] = v;
|
|
@@ -2591,7 +2591,7 @@ var require_Collection = __commonJS({
|
|
|
2591
2591
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
2592
2592
|
});
|
|
2593
2593
|
}
|
|
2594
|
-
var isEmptyPath = (
|
|
2594
|
+
var isEmptyPath = (path77) => path77 == null || typeof path77 === "object" && !!path77[Symbol.iterator]().next().done;
|
|
2595
2595
|
var Collection = class extends Node.NodeBase {
|
|
2596
2596
|
constructor(type, schema) {
|
|
2597
2597
|
super(type);
|
|
@@ -2621,11 +2621,11 @@ var require_Collection = __commonJS({
|
|
|
2621
2621
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
2622
2622
|
* that already exists in the map.
|
|
2623
2623
|
*/
|
|
2624
|
-
addIn(
|
|
2625
|
-
if (isEmptyPath(
|
|
2624
|
+
addIn(path77, value) {
|
|
2625
|
+
if (isEmptyPath(path77))
|
|
2626
2626
|
this.add(value);
|
|
2627
2627
|
else {
|
|
2628
|
-
const [key, ...rest] =
|
|
2628
|
+
const [key, ...rest] = path77;
|
|
2629
2629
|
const node = this.get(key, true);
|
|
2630
2630
|
if (identity.isCollection(node))
|
|
2631
2631
|
node.addIn(rest, value);
|
|
@@ -2639,8 +2639,8 @@ var require_Collection = __commonJS({
|
|
|
2639
2639
|
* Removes a value from the collection.
|
|
2640
2640
|
* @returns `true` if the item was found and removed.
|
|
2641
2641
|
*/
|
|
2642
|
-
deleteIn(
|
|
2643
|
-
const [key, ...rest] =
|
|
2642
|
+
deleteIn(path77) {
|
|
2643
|
+
const [key, ...rest] = path77;
|
|
2644
2644
|
if (rest.length === 0)
|
|
2645
2645
|
return this.delete(key);
|
|
2646
2646
|
const node = this.get(key, true);
|
|
@@ -2654,8 +2654,8 @@ var require_Collection = __commonJS({
|
|
|
2654
2654
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
2655
2655
|
* `true` (collections are always returned intact).
|
|
2656
2656
|
*/
|
|
2657
|
-
getIn(
|
|
2658
|
-
const [key, ...rest] =
|
|
2657
|
+
getIn(path77, keepScalar) {
|
|
2658
|
+
const [key, ...rest] = path77;
|
|
2659
2659
|
const node = this.get(key, true);
|
|
2660
2660
|
if (rest.length === 0)
|
|
2661
2661
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -2673,8 +2673,8 @@ var require_Collection = __commonJS({
|
|
|
2673
2673
|
/**
|
|
2674
2674
|
* Checks if the collection includes a value with the key `key`.
|
|
2675
2675
|
*/
|
|
2676
|
-
hasIn(
|
|
2677
|
-
const [key, ...rest] =
|
|
2676
|
+
hasIn(path77) {
|
|
2677
|
+
const [key, ...rest] = path77;
|
|
2678
2678
|
if (rest.length === 0)
|
|
2679
2679
|
return this.has(key);
|
|
2680
2680
|
const node = this.get(key, true);
|
|
@@ -2684,8 +2684,8 @@ var require_Collection = __commonJS({
|
|
|
2684
2684
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
2685
2685
|
* boolean to add/remove the item from the set.
|
|
2686
2686
|
*/
|
|
2687
|
-
setIn(
|
|
2688
|
-
const [key, ...rest] =
|
|
2687
|
+
setIn(path77, value) {
|
|
2688
|
+
const [key, ...rest] = path77;
|
|
2689
2689
|
if (rest.length === 0) {
|
|
2690
2690
|
this.set(key, value);
|
|
2691
2691
|
} else {
|
|
@@ -5200,9 +5200,9 @@ var require_Document = __commonJS({
|
|
|
5200
5200
|
this.contents.add(value);
|
|
5201
5201
|
}
|
|
5202
5202
|
/** Adds a value to the document. */
|
|
5203
|
-
addIn(
|
|
5203
|
+
addIn(path77, value) {
|
|
5204
5204
|
if (assertCollection(this.contents))
|
|
5205
|
-
this.contents.addIn(
|
|
5205
|
+
this.contents.addIn(path77, value);
|
|
5206
5206
|
}
|
|
5207
5207
|
/**
|
|
5208
5208
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -5277,14 +5277,14 @@ var require_Document = __commonJS({
|
|
|
5277
5277
|
* Removes a value from the document.
|
|
5278
5278
|
* @returns `true` if the item was found and removed.
|
|
5279
5279
|
*/
|
|
5280
|
-
deleteIn(
|
|
5281
|
-
if (Collection.isEmptyPath(
|
|
5280
|
+
deleteIn(path77) {
|
|
5281
|
+
if (Collection.isEmptyPath(path77)) {
|
|
5282
5282
|
if (this.contents == null)
|
|
5283
5283
|
return false;
|
|
5284
5284
|
this.contents = null;
|
|
5285
5285
|
return true;
|
|
5286
5286
|
}
|
|
5287
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
5287
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path77) : false;
|
|
5288
5288
|
}
|
|
5289
5289
|
/**
|
|
5290
5290
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -5299,10 +5299,10 @@ var require_Document = __commonJS({
|
|
|
5299
5299
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
5300
5300
|
* `true` (collections are always returned intact).
|
|
5301
5301
|
*/
|
|
5302
|
-
getIn(
|
|
5303
|
-
if (Collection.isEmptyPath(
|
|
5302
|
+
getIn(path77, keepScalar) {
|
|
5303
|
+
if (Collection.isEmptyPath(path77))
|
|
5304
5304
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
5305
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
5305
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path77, keepScalar) : void 0;
|
|
5306
5306
|
}
|
|
5307
5307
|
/**
|
|
5308
5308
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -5313,10 +5313,10 @@ var require_Document = __commonJS({
|
|
|
5313
5313
|
/**
|
|
5314
5314
|
* Checks if the document includes a value at `path`.
|
|
5315
5315
|
*/
|
|
5316
|
-
hasIn(
|
|
5317
|
-
if (Collection.isEmptyPath(
|
|
5316
|
+
hasIn(path77) {
|
|
5317
|
+
if (Collection.isEmptyPath(path77))
|
|
5318
5318
|
return this.contents !== void 0;
|
|
5319
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
5319
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path77) : false;
|
|
5320
5320
|
}
|
|
5321
5321
|
/**
|
|
5322
5322
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -5333,13 +5333,13 @@ var require_Document = __commonJS({
|
|
|
5333
5333
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
5334
5334
|
* boolean to add/remove the item from the set.
|
|
5335
5335
|
*/
|
|
5336
|
-
setIn(
|
|
5337
|
-
if (Collection.isEmptyPath(
|
|
5336
|
+
setIn(path77, value) {
|
|
5337
|
+
if (Collection.isEmptyPath(path77)) {
|
|
5338
5338
|
this.contents = value;
|
|
5339
5339
|
} else if (this.contents == null) {
|
|
5340
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
5340
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path77), value);
|
|
5341
5341
|
} else if (assertCollection(this.contents)) {
|
|
5342
|
-
this.contents.setIn(
|
|
5342
|
+
this.contents.setIn(path77, value);
|
|
5343
5343
|
}
|
|
5344
5344
|
}
|
|
5345
5345
|
/**
|
|
@@ -7299,9 +7299,9 @@ var require_cst_visit = __commonJS({
|
|
|
7299
7299
|
visit.BREAK = BREAK;
|
|
7300
7300
|
visit.SKIP = SKIP;
|
|
7301
7301
|
visit.REMOVE = REMOVE;
|
|
7302
|
-
visit.itemAtPath = (cst,
|
|
7302
|
+
visit.itemAtPath = (cst, path77) => {
|
|
7303
7303
|
let item = cst;
|
|
7304
|
-
for (const [field, index] of
|
|
7304
|
+
for (const [field, index] of path77) {
|
|
7305
7305
|
const tok = item?.[field];
|
|
7306
7306
|
if (tok && "items" in tok) {
|
|
7307
7307
|
item = tok.items[index];
|
|
@@ -7310,23 +7310,23 @@ var require_cst_visit = __commonJS({
|
|
|
7310
7310
|
}
|
|
7311
7311
|
return item;
|
|
7312
7312
|
};
|
|
7313
|
-
visit.parentCollection = (cst,
|
|
7314
|
-
const parent = visit.itemAtPath(cst,
|
|
7315
|
-
const field =
|
|
7313
|
+
visit.parentCollection = (cst, path77) => {
|
|
7314
|
+
const parent = visit.itemAtPath(cst, path77.slice(0, -1));
|
|
7315
|
+
const field = path77[path77.length - 1][0];
|
|
7316
7316
|
const coll = parent?.[field];
|
|
7317
7317
|
if (coll && "items" in coll)
|
|
7318
7318
|
return coll;
|
|
7319
7319
|
throw new Error("Parent collection not found");
|
|
7320
7320
|
};
|
|
7321
|
-
function _visit(
|
|
7322
|
-
let ctrl = visitor(item,
|
|
7321
|
+
function _visit(path77, item, visitor) {
|
|
7322
|
+
let ctrl = visitor(item, path77);
|
|
7323
7323
|
if (typeof ctrl === "symbol")
|
|
7324
7324
|
return ctrl;
|
|
7325
7325
|
for (const field of ["key", "value"]) {
|
|
7326
7326
|
const token = item[field];
|
|
7327
7327
|
if (token && "items" in token) {
|
|
7328
7328
|
for (let i = 0; i < token.items.length; ++i) {
|
|
7329
|
-
const ci = _visit(Object.freeze(
|
|
7329
|
+
const ci = _visit(Object.freeze(path77.concat([[field, i]])), token.items[i], visitor);
|
|
7330
7330
|
if (typeof ci === "number")
|
|
7331
7331
|
i = ci - 1;
|
|
7332
7332
|
else if (ci === BREAK)
|
|
@@ -7337,10 +7337,10 @@ var require_cst_visit = __commonJS({
|
|
|
7337
7337
|
}
|
|
7338
7338
|
}
|
|
7339
7339
|
if (typeof ctrl === "function" && field === "key")
|
|
7340
|
-
ctrl = ctrl(item,
|
|
7340
|
+
ctrl = ctrl(item, path77);
|
|
7341
7341
|
}
|
|
7342
7342
|
}
|
|
7343
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
7343
|
+
return typeof ctrl === "function" ? ctrl(item, path77) : ctrl;
|
|
7344
7344
|
}
|
|
7345
7345
|
exports.visit = visit;
|
|
7346
7346
|
}
|
|
@@ -8642,14 +8642,14 @@ var require_parser = __commonJS({
|
|
|
8642
8642
|
case "scalar":
|
|
8643
8643
|
case "single-quoted-scalar":
|
|
8644
8644
|
case "double-quoted-scalar": {
|
|
8645
|
-
const
|
|
8645
|
+
const fs80 = this.flowScalar(this.type);
|
|
8646
8646
|
if (atNextItem || it.value) {
|
|
8647
|
-
map.items.push({ start, key:
|
|
8647
|
+
map.items.push({ start, key: fs80, sep: [] });
|
|
8648
8648
|
this.onKeyLine = true;
|
|
8649
8649
|
} else if (it.sep) {
|
|
8650
|
-
this.stack.push(
|
|
8650
|
+
this.stack.push(fs80);
|
|
8651
8651
|
} else {
|
|
8652
|
-
Object.assign(it, { key:
|
|
8652
|
+
Object.assign(it, { key: fs80, sep: [] });
|
|
8653
8653
|
this.onKeyLine = true;
|
|
8654
8654
|
}
|
|
8655
8655
|
return;
|
|
@@ -8777,13 +8777,13 @@ var require_parser = __commonJS({
|
|
|
8777
8777
|
case "scalar":
|
|
8778
8778
|
case "single-quoted-scalar":
|
|
8779
8779
|
case "double-quoted-scalar": {
|
|
8780
|
-
const
|
|
8780
|
+
const fs80 = this.flowScalar(this.type);
|
|
8781
8781
|
if (!it || it.value)
|
|
8782
|
-
fc.items.push({ start: [], key:
|
|
8782
|
+
fc.items.push({ start: [], key: fs80, sep: [] });
|
|
8783
8783
|
else if (it.sep)
|
|
8784
|
-
this.stack.push(
|
|
8784
|
+
this.stack.push(fs80);
|
|
8785
8785
|
else
|
|
8786
|
-
Object.assign(it, { key:
|
|
8786
|
+
Object.assign(it, { key: fs80, sep: [] });
|
|
8787
8787
|
return;
|
|
8788
8788
|
}
|
|
8789
8789
|
case "flow-map-end":
|
|
@@ -19547,7 +19547,7 @@ var init_update_roadmap_progress = __esm({
|
|
|
19547
19547
|
BLOCKER_HEADING_RE = /^###[ \t]+blocker:[ \t]*(.+?)[ \t]*$/gim;
|
|
19548
19548
|
NEXT_H2_RE = /^##[ \t]+\S/m;
|
|
19549
19549
|
LEGACY_BLOCKED_UNTIL_RE = /^>[ \t]*Blocked until:?[ \t]*(.+)$/im;
|
|
19550
|
-
BLOCKER_FIELD_RE = /^-[ \t]*\*\*
|
|
19550
|
+
BLOCKER_FIELD_RE = /^-[ \t]*\*\*[^*]+:\*\*/;
|
|
19551
19551
|
ArgparseExit = class extends Error {
|
|
19552
19552
|
code;
|
|
19553
19553
|
constructor(code) {
|
|
@@ -19793,6 +19793,21 @@ function _regen_dashboard(root, dry_run) {
|
|
|
19793
19793
|
_run(["git", "add", "--", "agents/roadmaps-progress.md"], root);
|
|
19794
19794
|
}
|
|
19795
19795
|
}
|
|
19796
|
+
function _regen_archive_index(root, dry_run) {
|
|
19797
|
+
if (dry_run) {
|
|
19798
|
+
return;
|
|
19799
|
+
}
|
|
19800
|
+
const script = path22.join(root, "src", "scripts", "build_archive_index.ts");
|
|
19801
|
+
if (!_isFile8(script)) {
|
|
19802
|
+
return;
|
|
19803
|
+
}
|
|
19804
|
+
_runTwin(root, script);
|
|
19805
|
+
for (const rel of ["agents/roadmaps/archive/INDEX.md", "agents/roadmaps/archive/index.json"]) {
|
|
19806
|
+
if (_isFile8(path22.join(root, rel))) {
|
|
19807
|
+
_run(["git", "add", "--", rel], root);
|
|
19808
|
+
}
|
|
19809
|
+
}
|
|
19810
|
+
}
|
|
19796
19811
|
function _runTwin(root, script) {
|
|
19797
19812
|
const binName = process9.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
19798
19813
|
let dir = path22.dirname(_HERE6);
|
|
@@ -19865,6 +19880,7 @@ function main10(argv) {
|
|
|
19865
19880
|
return 0;
|
|
19866
19881
|
}
|
|
19867
19882
|
_regen_dashboard(root, ns.dry_run);
|
|
19883
|
+
_regen_archive_index(root, ns.dry_run);
|
|
19868
19884
|
const verb = ns.dry_run ? "Would archive" : "Archived";
|
|
19869
19885
|
for (const rec of archived) {
|
|
19870
19886
|
process9.stdout.write(
|
|
@@ -21712,8 +21728,8 @@ function lockfile_path(env) {
|
|
|
21712
21728
|
}
|
|
21713
21729
|
return write_target("installed.lock", { env: env ?? null });
|
|
21714
21730
|
}
|
|
21715
|
-
function read_lockfile(
|
|
21716
|
-
const target =
|
|
21731
|
+
function read_lockfile(path77) {
|
|
21732
|
+
const target = path77 ?? lockfile_path();
|
|
21717
21733
|
let text;
|
|
21718
21734
|
try {
|
|
21719
21735
|
text = fs31.readFileSync(target, { encoding: "utf-8" });
|
|
@@ -21923,18 +21939,18 @@ function manifest_path(project_root, env) {
|
|
|
21923
21939
|
}
|
|
21924
21940
|
return fsPath.join(project_root, DEFAULT_MANIFEST_RELATIVE);
|
|
21925
21941
|
}
|
|
21926
|
-
function read_manifest(
|
|
21942
|
+
function read_manifest(path77) {
|
|
21927
21943
|
let text;
|
|
21928
21944
|
try {
|
|
21929
|
-
text = require_read_text(
|
|
21945
|
+
text = require_read_text(path77);
|
|
21930
21946
|
} catch {
|
|
21931
21947
|
return null;
|
|
21932
21948
|
}
|
|
21933
21949
|
const data = _parse_manual(text);
|
|
21934
21950
|
return _normalise_v2_shape(data);
|
|
21935
21951
|
}
|
|
21936
|
-
function require_read_text(
|
|
21937
|
-
return fs33.readFileSync(
|
|
21952
|
+
function require_read_text(path77) {
|
|
21953
|
+
return fs33.readFileSync(path77, { encoding: "utf-8" });
|
|
21938
21954
|
}
|
|
21939
21955
|
function _normalise_v2_shape(data) {
|
|
21940
21956
|
if (data["tools"] === void 0 || data["tools"] === null) {
|
|
@@ -22115,9 +22131,9 @@ function stable_sort(items, key) {
|
|
|
22115
22131
|
return a.index - b.index;
|
|
22116
22132
|
}).map((entry) => entry.item);
|
|
22117
22133
|
}
|
|
22118
|
-
function write_manifest(
|
|
22134
|
+
function write_manifest(path77, version, tools, options = {}) {
|
|
22119
22135
|
const rendered = _render(version, tools, { deploy_roots: options.deploy_roots ?? null });
|
|
22120
|
-
return write_atomic(
|
|
22136
|
+
return write_atomic(path77, rendered);
|
|
22121
22137
|
}
|
|
22122
22138
|
function upsert_tool(existing, options) {
|
|
22123
22139
|
const {
|
|
@@ -27307,23 +27323,23 @@ ${user_prompt}`;
|
|
|
27307
27323
|
// documented "disable all tools" value.
|
|
27308
27324
|
//
|
|
27309
27325
|
// It also repairs a live failure, which is how the grant was found
|
|
27310
|
-
// rather than reasoned about.
|
|
27311
|
-
//
|
|
27312
|
-
//
|
|
27313
|
-
//
|
|
27314
|
-
//
|
|
27315
|
-
// In this package that overflowed the model's context window
|
|
27316
|
-
// outright: `is_error: true`, `"the request is ~214331 tokens
|
|
27326
|
+
// rather than reasoned about. AT THE TIME (2026-08-12) the spawn
|
|
27327
|
+
// inherited the caller's cwd, so invoking the council from inside a
|
|
27328
|
+
// repository made the child load that project's own instructions AND
|
|
27329
|
+
// every tool definition. In this package that overflowed the context
|
|
27330
|
+
// window outright: `is_error: true`, `"the request is ~214331 tokens
|
|
27317
27331
|
// (limit 200000) … the rest is system prompt, tool definitions"`,
|
|
27318
|
-
// exit 1, empty stderr —
|
|
27319
|
-
//
|
|
27320
|
-
//
|
|
27321
|
-
// returns the worktree call to exit 0.
|
|
27332
|
+
// exit 1, empty stderr — the member reported unavailable with no
|
|
27333
|
+
// diagnosable cause. Identical call from `/tmp` exit 0, from the
|
|
27334
|
+
// worktree exit 1, and this one flag returns the worktree to exit 0.
|
|
27322
27335
|
//
|
|
27323
|
-
//
|
|
27324
|
-
//
|
|
27325
|
-
//
|
|
27326
|
-
//
|
|
27336
|
+
// TENSE CORRECTED 2026-08-16. This block read "`_runSubprocess` sets
|
|
27337
|
+
// none, deliberately" and "dropping the tools RATHER THAN
|
|
27338
|
+
// neutralising the cwd" — both false since `_runSubprocess` set
|
|
27339
|
+
// `cwd: os.tmpdir()` for a DIFFERENT contamination (a member
|
|
27340
|
+
// answering this repo's `end-review-nudge`). Two repairs, one
|
|
27341
|
+
// cause, neither aware of the other, so a reader here concluded
|
|
27342
|
+
// the cwd is inherited. Both are live; this flag bounds what a member may DO.
|
|
27327
27343
|
"--tools",
|
|
27328
27344
|
"",
|
|
27329
27345
|
"--append-system-prompt",
|
|
@@ -27413,7 +27429,7 @@ ${user_prompt}`;
|
|
|
27413
27429
|
if (measuredOn === void 0) return null;
|
|
27414
27430
|
return {
|
|
27415
27431
|
code: "model_unsupported_on_transport",
|
|
27416
|
-
detail: `openai member pins model \`${this.model}\`, which the codex CLI (subscription transport) refused when measured on ${measuredOn}: "The '${this.model}' model is not supported when using Codex with a ChatGPT account." The CLI publishes no list of models it DOES accept, so there is no supported set to offer here \u2014 the one configuration measured to work is no pin at all. Fix:
|
|
27432
|
+
detail: `openai member pins model \`${this.model}\`, which the codex CLI (subscription transport) refused when measured on ${measuredOn}: "The '${this.model}' model is not supported when using Codex with a ChatGPT account." The CLI publishes no list of models it DOES accept, so there is no supported set to offer here \u2014 the one configuration measured to work is no pin at all. Fix: set \`model: codex-default\` on the openai member. Do NOT delete the \`model:\` line \u2014 an enabled member with no model fails config load, so that takes EVERY provider to NOT CONFIGURED. A pin is reachable only on the API transport.`
|
|
27417
27433
|
};
|
|
27418
27434
|
}
|
|
27419
27435
|
/**
|
|
@@ -27528,7 +27544,7 @@ ${user_prompt}`;
|
|
|
27528
27544
|
// needs and neither of which the error code carries.
|
|
27529
27545
|
detail: failure.slice(0, 400),
|
|
27530
27546
|
...unsupported ? {
|
|
27531
|
-
hint: "the codex subscription transport serves no explicitly pinned model measured so far \u2014
|
|
27547
|
+
hint: "the codex subscription transport serves no explicitly pinned model measured so far \u2014 set `model: codex-default` on the openai member; deleting the line fails config load"
|
|
27532
27548
|
} : {}
|
|
27533
27549
|
}
|
|
27534
27550
|
});
|
|
@@ -30583,8 +30599,8 @@ function ruleFileArrives(sourcePath, scope) {
|
|
|
30583
30599
|
if (!sourcePath.endsWith(".md")) {
|
|
30584
30600
|
return true;
|
|
30585
30601
|
}
|
|
30586
|
-
const
|
|
30587
|
-
if (COMPAT_ALWAYS_EXCLUDED.includes(
|
|
30602
|
+
const basename22 = path52.basename(sourcePath);
|
|
30603
|
+
if (COMPAT_ALWAYS_EXCLUDED.includes(basename22)) {
|
|
30588
30604
|
return false;
|
|
30589
30605
|
}
|
|
30590
30606
|
return rule_in_scope(sourcePath, scope.workspaces, scope.packs, scope.roles ?? null);
|
|
@@ -33444,9 +33460,9 @@ function detectToolPresence(root) {
|
|
|
33444
33460
|
agentsMd: existsSync25(join49(root, "AGENTS.md"))
|
|
33445
33461
|
};
|
|
33446
33462
|
}
|
|
33447
|
-
function isDir3(
|
|
33463
|
+
function isDir3(path77) {
|
|
33448
33464
|
try {
|
|
33449
|
-
return statSync32(
|
|
33465
|
+
return statSync32(path77).isDirectory();
|
|
33450
33466
|
} catch {
|
|
33451
33467
|
return false;
|
|
33452
33468
|
}
|
|
@@ -42805,8 +42821,8 @@ function aggregate_scores(findings, scores) {
|
|
|
42805
42821
|
by_id.get(s.finding_id).push(s);
|
|
42806
42822
|
}
|
|
42807
42823
|
const out = /* @__PURE__ */ new Map();
|
|
42808
|
-
for (const [fid,
|
|
42809
|
-
if (
|
|
42824
|
+
for (const [fid, fs80] of by_id) {
|
|
42825
|
+
if (fs80.length === 0) {
|
|
42810
42826
|
out.set(
|
|
42811
42827
|
fid,
|
|
42812
42828
|
new ConsensusMetadata({
|
|
@@ -42822,13 +42838,13 @@ function aggregate_scores(findings, scores) {
|
|
|
42822
42838
|
);
|
|
42823
42839
|
continue;
|
|
42824
42840
|
}
|
|
42825
|
-
const mean2 =
|
|
42826
|
-
const agree_rate =
|
|
42841
|
+
const mean2 = fs80.reduce((acc, s) => acc + s.score, 0) / fs80.length;
|
|
42842
|
+
const agree_rate = fs80.filter((s) => s.agree).length / fs80.length;
|
|
42827
42843
|
const strength = mean2 / 10 * agree_rate;
|
|
42828
|
-
const dissent =
|
|
42829
|
-
const concur =
|
|
42830
|
-
const scorers =
|
|
42831
|
-
const dissent_reasons =
|
|
42844
|
+
const dissent = fs80.filter((s) => !s.agree).length;
|
|
42845
|
+
const concur = fs80.filter((s) => s.agree).length;
|
|
42846
|
+
const scorers = fs80.map((s) => s.scorer);
|
|
42847
|
+
const dissent_reasons = fs80.filter((s) => !s.agree).map((s) => [s.scorer, s.reason]);
|
|
42832
42848
|
const mean_rounded = pyRound(mean2, 2);
|
|
42833
42849
|
out.set(
|
|
42834
42850
|
fid,
|
|
@@ -49192,7 +49208,7 @@ function run_enveloped(spec) {
|
|
|
49192
49208
|
if (cmd === void 0) {
|
|
49193
49209
|
throw new Error("envelope argv must not be empty");
|
|
49194
49210
|
}
|
|
49195
|
-
return new Promise((
|
|
49211
|
+
return new Promise((resolve44) => {
|
|
49196
49212
|
execFile(
|
|
49197
49213
|
cmd,
|
|
49198
49214
|
args,
|
|
@@ -49215,7 +49231,7 @@ function run_enveloped(spec) {
|
|
|
49215
49231
|
}
|
|
49216
49232
|
const [out, outTrunc] = _truncate(String(stdout ?? ""), spec.max_output_bytes);
|
|
49217
49233
|
const [err, errTrunc] = _truncate(String(stderr ?? ""), spec.max_output_bytes);
|
|
49218
|
-
|
|
49234
|
+
resolve44({
|
|
49219
49235
|
exit_code: timedOut ? null : exitCode,
|
|
49220
49236
|
timed_out: timedOut,
|
|
49221
49237
|
stdout: out,
|
|
@@ -49235,9 +49251,977 @@ var init_safety_envelope = __esm({
|
|
|
49235
49251
|
}
|
|
49236
49252
|
});
|
|
49237
49253
|
|
|
49238
|
-
// src/scripts/
|
|
49254
|
+
// src/scripts/_lib/skill_catalogue.ts
|
|
49255
|
+
var skill_catalogue_exports = {};
|
|
49256
|
+
__export(skill_catalogue_exports, {
|
|
49257
|
+
DEFAULT_CATALOGUE_ROOTS: () => DEFAULT_CATALOGUE_ROOTS,
|
|
49258
|
+
OBSERVATION_LOG: () => OBSERVATION_LOG,
|
|
49259
|
+
analyzeSelector: () => analyzeSelector,
|
|
49260
|
+
buildHostEventRecord: () => buildHostEventRecord,
|
|
49261
|
+
buildNoTruncationRecord: () => buildNoTruncationRecord,
|
|
49262
|
+
buildObservationRecord: () => buildObservationRecord,
|
|
49263
|
+
catalogueLimitWarning: () => catalogueLimitWarning,
|
|
49264
|
+
classifyHostProjection: () => classifyHostProjection,
|
|
49265
|
+
formatPerHostVerdicts: () => formatPerHostVerdicts,
|
|
49266
|
+
formatProjectionModes: () => formatProjectionModes,
|
|
49267
|
+
formatReport: () => formatReport,
|
|
49268
|
+
headlineRecordPerHost: () => headlineRecordPerHost,
|
|
49269
|
+
knownHostLimits: () => knownHostLimits,
|
|
49270
|
+
measureCatalogueVolume: () => measureCatalogueVolume,
|
|
49271
|
+
migrationEligibility: () => migrationEligibility,
|
|
49272
|
+
migrationPromptLines: () => migrationPromptLines,
|
|
49273
|
+
observationSourceOf: () => observationSourceOf,
|
|
49274
|
+
parseHostBudgetEvent: () => parseHostBudgetEvent,
|
|
49275
|
+
readObservationLog: () => readObservationLog,
|
|
49276
|
+
readProjectedCatalogue: () => readProjectedCatalogue,
|
|
49277
|
+
resolveSkillsRoot: () => resolveSkillsRoot,
|
|
49278
|
+
truncationModeOf: () => truncationModeOf
|
|
49279
|
+
});
|
|
49280
|
+
import * as fs77 from "node:fs";
|
|
49281
|
+
import * as path73 from "node:path";
|
|
49282
|
+
function resolveSkillsRoot(workspaceRoot) {
|
|
49283
|
+
for (const candidate of DEFAULT_CATALOGUE_ROOTS) {
|
|
49284
|
+
const abs = path73.join(workspaceRoot, candidate);
|
|
49285
|
+
try {
|
|
49286
|
+
if (fs77.existsSync(abs) && fs77.statSync(abs).isDirectory()) return abs;
|
|
49287
|
+
} catch {
|
|
49288
|
+
}
|
|
49289
|
+
}
|
|
49290
|
+
return null;
|
|
49291
|
+
}
|
|
49292
|
+
function frontmatterOf(content) {
|
|
49293
|
+
if (!content.startsWith("---")) return "";
|
|
49294
|
+
const end = content.indexOf("\n---", 3);
|
|
49295
|
+
if (end === -1) return "";
|
|
49296
|
+
return content.slice(3, end);
|
|
49297
|
+
}
|
|
49298
|
+
function topLevelKeys(frontmatter) {
|
|
49299
|
+
const keys = [];
|
|
49300
|
+
for (const line of frontmatter.split("\n")) {
|
|
49301
|
+
const match = /^([A-Za-z_][A-Za-z0-9_-]*):/.exec(line);
|
|
49302
|
+
if (match) keys.push(match[1]);
|
|
49303
|
+
}
|
|
49304
|
+
return keys;
|
|
49305
|
+
}
|
|
49306
|
+
function descriptionOf(frontmatter) {
|
|
49307
|
+
const lines = frontmatter.split("\n");
|
|
49308
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
49309
|
+
const match = /^description:\s*(.*)$/.exec(lines[i]);
|
|
49310
|
+
if (!match) continue;
|
|
49311
|
+
const rest = match[1].trim();
|
|
49312
|
+
if (/^[|>][-+]?\d*$/.test(rest)) {
|
|
49313
|
+
const body = [];
|
|
49314
|
+
for (let j = i + 1; j < lines.length; j += 1) {
|
|
49315
|
+
const line = lines[j];
|
|
49316
|
+
if (line.trim() === "") {
|
|
49317
|
+
body.push("");
|
|
49318
|
+
continue;
|
|
49319
|
+
}
|
|
49320
|
+
if (!/^\s/.test(line)) break;
|
|
49321
|
+
body.push(line.trim());
|
|
49322
|
+
}
|
|
49323
|
+
return body.join(" ").trim();
|
|
49324
|
+
}
|
|
49325
|
+
return rest.replace(/^["']|["']$/g, "");
|
|
49326
|
+
}
|
|
49327
|
+
return "";
|
|
49328
|
+
}
|
|
49329
|
+
function readProjectedCatalogue(root) {
|
|
49330
|
+
const names = fs77.readdirSync(root).filter((n) => fs77.existsSync(path73.join(root, n, "SKILL.md"))).sort();
|
|
49331
|
+
return names.map((name, index) => {
|
|
49332
|
+
const content = fs77.readFileSync(path73.join(root, name, "SKILL.md"), "utf-8");
|
|
49333
|
+
const frontmatter = frontmatterOf(content);
|
|
49334
|
+
const description = descriptionOf(frontmatter);
|
|
49335
|
+
return {
|
|
49336
|
+
name,
|
|
49337
|
+
position: index + 1,
|
|
49338
|
+
hasDescription: description.length > 0,
|
|
49339
|
+
descriptionLength: description.length,
|
|
49340
|
+
description,
|
|
49341
|
+
frontmatterKeys: topLevelKeys(frontmatter)
|
|
49342
|
+
};
|
|
49343
|
+
});
|
|
49344
|
+
}
|
|
49345
|
+
function rangesAreDisjoint(a, b) {
|
|
49346
|
+
if (a.length === 0 || b.length === 0) return false;
|
|
49347
|
+
const maxA = Math.max(...a);
|
|
49348
|
+
const minA = Math.min(...a);
|
|
49349
|
+
const maxB = Math.max(...b);
|
|
49350
|
+
const minB = Math.min(...b);
|
|
49351
|
+
return maxA < minB || maxB < minA;
|
|
49352
|
+
}
|
|
49353
|
+
function analyzeSelector(projected, observedBare, observedDescribed) {
|
|
49354
|
+
const known = new Map(projected.map((e) => [e.name, e]));
|
|
49355
|
+
const bare = observedBare.filter((n) => known.has(n));
|
|
49356
|
+
const describedInput = observedDescribed ?? projected.map((e) => e.name).filter((n) => !bare.includes(n));
|
|
49357
|
+
const described = describedInput.filter((n) => known.has(n));
|
|
49358
|
+
const unknownObserved = [
|
|
49359
|
+
.../* @__PURE__ */ new Set([
|
|
49360
|
+
...observedBare.filter((n) => !known.has(n)),
|
|
49361
|
+
...(observedDescribed ?? []).filter((n) => !known.has(n))
|
|
49362
|
+
])
|
|
49363
|
+
].sort();
|
|
49364
|
+
const base = {
|
|
49365
|
+
entriesTotal: projected.length,
|
|
49366
|
+
observedBare: [...bare].sort(),
|
|
49367
|
+
observedDescribed: [...described].sort(),
|
|
49368
|
+
unknownObserved
|
|
49369
|
+
};
|
|
49370
|
+
if (bare.length === 0 || described.length === 0) {
|
|
49371
|
+
return {
|
|
49372
|
+
...base,
|
|
49373
|
+
candidates: [],
|
|
49374
|
+
verdict: "insufficient-observation"
|
|
49375
|
+
};
|
|
49376
|
+
}
|
|
49377
|
+
const bareEntries = bare.map((n) => known.get(n));
|
|
49378
|
+
const describedEntries = described.map((n) => known.get(n));
|
|
49379
|
+
const candidates = [];
|
|
49380
|
+
const bareWithDesc = bareEntries.filter((e) => e.hasDescription).length;
|
|
49381
|
+
const describedWithoutDesc = describedEntries.filter((e) => !e.hasDescription).length;
|
|
49382
|
+
candidates.push({
|
|
49383
|
+
id: "declares-description",
|
|
49384
|
+
describes: "the projected SKILL.md declares a `description:`",
|
|
49385
|
+
separates: bareWithDesc === 0 && describedWithoutDesc === 0,
|
|
49386
|
+
detail: `${bareWithDesc}/${bareEntries.length} bare entries declare one; ${describedWithoutDesc}/${describedEntries.length} described entries do not`
|
|
49387
|
+
});
|
|
49388
|
+
const barePositions = bareEntries.map((e) => e.position);
|
|
49389
|
+
const describedPositions = describedEntries.map((e) => e.position);
|
|
49390
|
+
const positional = Math.max(...describedPositions) < Math.min(...barePositions);
|
|
49391
|
+
candidates.push({
|
|
49392
|
+
id: "positional-head",
|
|
49393
|
+
describes: "every described entry sorts before every bare entry (a head-N budget)",
|
|
49394
|
+
separates: positional,
|
|
49395
|
+
detail: positional ? `described top out at #${Math.max(...describedPositions)}, bare start at #${Math.min(...barePositions)}` : `described reach #${Math.max(...describedPositions)} while bare start at #${Math.min(...barePositions)} \u2014 the ranges overlap, so no head-N cut explains this`
|
|
49396
|
+
});
|
|
49397
|
+
const lengthSeparates = rangesAreDisjoint(
|
|
49398
|
+
bareEntries.map((e) => e.descriptionLength),
|
|
49399
|
+
describedEntries.map((e) => e.descriptionLength)
|
|
49400
|
+
);
|
|
49401
|
+
candidates.push({
|
|
49402
|
+
id: "description-length",
|
|
49403
|
+
describes: "description length ranges do not overlap between the groups",
|
|
49404
|
+
separates: lengthSeparates,
|
|
49405
|
+
detail: lengthSeparates ? "a length threshold separates the two groups" : "length ranges overlap"
|
|
49406
|
+
});
|
|
49407
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
49408
|
+
for (const entry of projected) for (const key of entry.frontmatterKeys) allKeys.add(key);
|
|
49409
|
+
for (const key of [...allKeys].sort()) {
|
|
49410
|
+
const bareHas = bareEntries.filter((e) => e.frontmatterKeys.includes(key)).length;
|
|
49411
|
+
const describedHas = describedEntries.filter(
|
|
49412
|
+
(e) => e.frontmatterKeys.includes(key)
|
|
49413
|
+
).length;
|
|
49414
|
+
const separates = bareHas === 0 && describedHas === describedEntries.length || describedHas === 0 && bareHas === bareEntries.length;
|
|
49415
|
+
if (!separates) continue;
|
|
49416
|
+
candidates.push({
|
|
49417
|
+
id: `frontmatter:${key}`,
|
|
49418
|
+
describes: `presence of the \`${key}:\` frontmatter key`,
|
|
49419
|
+
separates: true,
|
|
49420
|
+
detail: `bare ${bareHas}/${bareEntries.length}, described ${describedHas}/${describedEntries.length}`
|
|
49421
|
+
});
|
|
49422
|
+
}
|
|
49423
|
+
return {
|
|
49424
|
+
...base,
|
|
49425
|
+
candidates,
|
|
49426
|
+
verdict: candidates.some((c) => c.separates) ? "selector-found" : "no-selector"
|
|
49427
|
+
};
|
|
49428
|
+
}
|
|
49429
|
+
function truncationModeOf(record) {
|
|
49430
|
+
return record.truncation_mode ?? "per-entry";
|
|
49431
|
+
}
|
|
49432
|
+
function observationSourceOf(record) {
|
|
49433
|
+
return record.observation_source ?? "self-report";
|
|
49434
|
+
}
|
|
49435
|
+
function buildObservationRecord(report2, host, observedAt) {
|
|
49436
|
+
return {
|
|
49437
|
+
schema: 1,
|
|
49438
|
+
observed_at: observedAt,
|
|
49439
|
+
host,
|
|
49440
|
+
entries_total: report2.entriesTotal,
|
|
49441
|
+
bare_count: report2.observedBare.length,
|
|
49442
|
+
described_count: report2.observedDescribed.length,
|
|
49443
|
+
bare_names: report2.observedBare,
|
|
49444
|
+
verdict: report2.verdict,
|
|
49445
|
+
separating_candidates: report2.candidates.filter((c) => c.separates).map((c) => c.id),
|
|
49446
|
+
truncation_mode: "per-entry",
|
|
49447
|
+
observation_source: "self-report"
|
|
49448
|
+
};
|
|
49449
|
+
}
|
|
49450
|
+
function parseHostBudgetEvent(stream) {
|
|
49451
|
+
for (const line of stream.split("\n")) {
|
|
49452
|
+
const trimmed = line.trim();
|
|
49453
|
+
if (!trimmed.startsWith("{")) continue;
|
|
49454
|
+
let parsed;
|
|
49455
|
+
try {
|
|
49456
|
+
parsed = JSON.parse(trimmed);
|
|
49457
|
+
} catch {
|
|
49458
|
+
continue;
|
|
49459
|
+
}
|
|
49460
|
+
const item = parsed.item;
|
|
49461
|
+
if (item === void 0 || item === null || item.type !== "error") continue;
|
|
49462
|
+
const message = typeof item.message === "string" ? item.message : "";
|
|
49463
|
+
if (!/skills context budget/i.test(message)) continue;
|
|
49464
|
+
const dropped = /(\d+)\s+additional skills were not included/i.exec(message);
|
|
49465
|
+
if (!dropped) {
|
|
49466
|
+
return null;
|
|
49467
|
+
}
|
|
49468
|
+
return {
|
|
49469
|
+
droppedCount: Number.parseInt(dropped[1], 10),
|
|
49470
|
+
descriptionsStripped: /descriptions were removed/i.test(message)
|
|
49471
|
+
};
|
|
49472
|
+
}
|
|
49473
|
+
return null;
|
|
49474
|
+
}
|
|
49475
|
+
function buildHostEventRecord(host, observedAt, entriesOffered, event, projectedSkillCount, projectionMode) {
|
|
49476
|
+
return {
|
|
49477
|
+
schema: 1,
|
|
49478
|
+
observed_at: observedAt,
|
|
49479
|
+
host,
|
|
49480
|
+
// OUR projection, not the host's denominator. Measured 2026-08-15 they
|
|
49481
|
+
// are not the same number and there is no way to read the host's:
|
|
49482
|
+
// `~/.codex` projects 297 skills + 200 commands = 497 by this tool's
|
|
49483
|
+
// count, while the host reported dropping 393 — and a controlled +60
|
|
49484
|
+
// commands moved that by ZERO. Whatever codex counts, it is not this.
|
|
49485
|
+
// So `entries_total - dropped_count` is NOT a delivered count, and
|
|
49486
|
+
// nothing here computes one: a subtraction across two different
|
|
49487
|
+
// denominators produces a confident number describing neither.
|
|
49488
|
+
entries_total: entriesOffered,
|
|
49489
|
+
bare_count: 0,
|
|
49490
|
+
described_count: 0,
|
|
49491
|
+
bare_names: [],
|
|
49492
|
+
// There is nothing to separate: the host did not choose per entry, it
|
|
49493
|
+
// stripped all of them. `no-selector` would read as "we looked and
|
|
49494
|
+
// found none", which is not what happened.
|
|
49495
|
+
verdict: "insufficient-observation",
|
|
49496
|
+
separating_candidates: [],
|
|
49497
|
+
truncation_mode: "budget-strip-and-drop",
|
|
49498
|
+
observation_source: "host-event",
|
|
49499
|
+
dropped_count: event.droppedCount,
|
|
49500
|
+
...projectedSkillCount === void 0 ? {} : { projected_skill_count: projectedSkillCount },
|
|
49501
|
+
...projectionMode === void 0 ? {} : { projection_mode: projectionMode }
|
|
49502
|
+
};
|
|
49503
|
+
}
|
|
49504
|
+
function buildNoTruncationRecord(host, observedAt, entriesOffered, projectedSkillCount, projectionMode) {
|
|
49505
|
+
return {
|
|
49506
|
+
schema: 1,
|
|
49507
|
+
observed_at: observedAt,
|
|
49508
|
+
host,
|
|
49509
|
+
entries_total: entriesOffered,
|
|
49510
|
+
// BOTH counts stay 0, and neither is a claim that nothing arrived
|
|
49511
|
+
// described. The host published no per-entry breakdown at all — it
|
|
49512
|
+
// published nothing, which is what `truncation_mode: 'none'` records.
|
|
49513
|
+
// Writing `described_count: entriesOffered` would look like a
|
|
49514
|
+
// measurement and be an inference; 0 here means "not counted", exactly
|
|
49515
|
+
// as it does on the strip-and-drop record beside it.
|
|
49516
|
+
bare_count: 0,
|
|
49517
|
+
described_count: 0,
|
|
49518
|
+
bare_names: [],
|
|
49519
|
+
// Nothing arrived bare, so no property separated bare from described —
|
|
49520
|
+
// which is what `no-selector` states. Unlike the strip-and-drop case,
|
|
49521
|
+
// here the label is literally true rather than merely available.
|
|
49522
|
+
verdict: "no-selector",
|
|
49523
|
+
separating_candidates: [],
|
|
49524
|
+
truncation_mode: "none",
|
|
49525
|
+
observation_source: "host-event",
|
|
49526
|
+
dropped_count: 0,
|
|
49527
|
+
...projectedSkillCount === void 0 ? {} : { projected_skill_count: projectedSkillCount },
|
|
49528
|
+
...projectionMode === void 0 ? {} : { projection_mode: projectionMode }
|
|
49529
|
+
};
|
|
49530
|
+
}
|
|
49531
|
+
function markdownFilesUnder(root) {
|
|
49532
|
+
if (!fs77.existsSync(root)) return [];
|
|
49533
|
+
const out = [];
|
|
49534
|
+
const walk = (dir) => {
|
|
49535
|
+
for (const entry of fs77.readdirSync(dir, { withFileTypes: true })) {
|
|
49536
|
+
const full = path73.join(dir, entry.name);
|
|
49537
|
+
if (fs77.statSync(full).isDirectory()) walk(full);
|
|
49538
|
+
else if (entry.name.endsWith(".md")) out.push(full);
|
|
49539
|
+
}
|
|
49540
|
+
};
|
|
49541
|
+
walk(root);
|
|
49542
|
+
return out;
|
|
49543
|
+
}
|
|
49544
|
+
function measureCatalogueVolume(host, root) {
|
|
49545
|
+
const skillsRoot = path73.join(root, "skills");
|
|
49546
|
+
const skills = fs77.existsSync(skillsRoot) ? readProjectedCatalogue(skillsRoot) : [];
|
|
49547
|
+
const commandEntries = markdownFilesUnder(path73.join(root, "commands")).length;
|
|
49548
|
+
return {
|
|
49549
|
+
host,
|
|
49550
|
+
root,
|
|
49551
|
+
skillEntries: skills.length,
|
|
49552
|
+
commandEntries,
|
|
49553
|
+
artefacts: skills.length + commandEntries,
|
|
49554
|
+
descriptionBytes: skills.reduce((sum, e) => sum + Buffer.byteLength(e.description), 0)
|
|
49555
|
+
};
|
|
49556
|
+
}
|
|
49557
|
+
function classifyHostProjection(volume, counts) {
|
|
49558
|
+
const ambiguous = counts.scoped === counts.legacyAll;
|
|
49559
|
+
let matches = "indeterminate";
|
|
49560
|
+
if (!ambiguous) {
|
|
49561
|
+
if (volume.skillEntries === counts.scoped) matches = "scoped";
|
|
49562
|
+
else if (volume.skillEntries === counts.legacyAll) matches = "legacy-all";
|
|
49563
|
+
}
|
|
49564
|
+
return {
|
|
49565
|
+
host: volume.host,
|
|
49566
|
+
root: volume.root,
|
|
49567
|
+
installedSkills: volume.skillEntries,
|
|
49568
|
+
matches
|
|
49569
|
+
};
|
|
49570
|
+
}
|
|
49571
|
+
function formatProjectionModes(counts, rows) {
|
|
49572
|
+
const lines = [
|
|
49573
|
+
"projected SKILL counts by projection mode (package side, one walk):",
|
|
49574
|
+
` scoped: ${counts.scoped}`,
|
|
49575
|
+
` legacy-all: ${counts.legacyAll}`,
|
|
49576
|
+
` pruned under scoped: ${counts.prunedUnderScoped}`,
|
|
49577
|
+
` active packs under scoped: ${counts.activePacks.length}`,
|
|
49578
|
+
""
|
|
49579
|
+
];
|
|
49580
|
+
if (rows.length === 0) {
|
|
49581
|
+
lines.push(
|
|
49582
|
+
"No host root measured. Pass --host-root <dir> (repeatable) to read what",
|
|
49583
|
+
"each host currently holds against the two numbers above."
|
|
49584
|
+
);
|
|
49585
|
+
return lines.join("\n");
|
|
49586
|
+
}
|
|
49587
|
+
lines.push("installed host roots:");
|
|
49588
|
+
for (const row of [...rows].sort((a, b) => a.host.localeCompare(b.host))) {
|
|
49589
|
+
lines.push(` ${row.host}: ${row.installedSkills} skills \u2014 consistent with ${row.matches}`);
|
|
49590
|
+
}
|
|
49591
|
+
lines.push(
|
|
49592
|
+
"",
|
|
49593
|
+
"This is the PROJECTION half only, and it is a measurement: no default was",
|
|
49594
|
+
"read, changed, or recommended here. `indeterminate` means the root carries",
|
|
49595
|
+
"neither count \u2014 another suite, a plugin, or a stale install all produce it.",
|
|
49596
|
+
"No host limit is extrapolated from another host, and no delivered or",
|
|
49597
|
+
"survivor count is computed anywhere."
|
|
49598
|
+
);
|
|
49599
|
+
return lines.join("\n");
|
|
49600
|
+
}
|
|
49601
|
+
function _supersedes(candidate, incumbent) {
|
|
49602
|
+
if (candidate.observed_at !== incumbent.observed_at) {
|
|
49603
|
+
return candidate.observed_at > incumbent.observed_at;
|
|
49604
|
+
}
|
|
49605
|
+
return (candidate.dropped_count ?? 0) > (incumbent.dropped_count ?? 0);
|
|
49606
|
+
}
|
|
49607
|
+
function headlineRecordPerHost(records) {
|
|
49608
|
+
const out = /* @__PURE__ */ new Map();
|
|
49609
|
+
for (const record of records) {
|
|
49610
|
+
const previous = out.get(record.host);
|
|
49611
|
+
if (previous === void 0 || _supersedes(record, previous)) {
|
|
49612
|
+
out.set(record.host, record);
|
|
49613
|
+
}
|
|
49614
|
+
}
|
|
49615
|
+
return out;
|
|
49616
|
+
}
|
|
49617
|
+
function knownHostLimits(records) {
|
|
49618
|
+
const out = /* @__PURE__ */ new Map();
|
|
49619
|
+
const chosen = /* @__PURE__ */ new Map();
|
|
49620
|
+
for (const record of records) {
|
|
49621
|
+
if (truncationModeOf(record) !== "budget-strip-and-drop") continue;
|
|
49622
|
+
if (typeof record.dropped_count !== "number") continue;
|
|
49623
|
+
if (record.dropped_count <= 0) continue;
|
|
49624
|
+
const previous = chosen.get(record.host);
|
|
49625
|
+
if (previous !== void 0 && !_supersedes(record, previous)) continue;
|
|
49626
|
+
chosen.set(record.host, record);
|
|
49627
|
+
out.set(record.host, {
|
|
49628
|
+
host: record.host,
|
|
49629
|
+
droppedEntries: record.dropped_count,
|
|
49630
|
+
projectedVolume: record.entries_total,
|
|
49631
|
+
projectedSkills: record.projected_skill_count ?? null,
|
|
49632
|
+
observedAt: record.observed_at
|
|
49633
|
+
});
|
|
49634
|
+
}
|
|
49635
|
+
return out;
|
|
49636
|
+
}
|
|
49637
|
+
function catalogueLimitWarning(volume, limit) {
|
|
49638
|
+
if (limit === void 0) return null;
|
|
49639
|
+
if (limit.projectedSkills === null) return null;
|
|
49640
|
+
if (volume.skillEntries < limit.projectedSkills) return null;
|
|
49641
|
+
return `${volume.host}: deploying ${volume.skillEntries} skills. This host reported dropping ${limit.droppedEntries} entries from the model-visible list when last measured (${limit.observedAt}, at ${limit.projectedSkills} skills) \u2014 that much never reaches the model. Explain: \`agent-config exec capture_skill_catalogue --limits\``;
|
|
49642
|
+
}
|
|
49643
|
+
function migrationEligibility(host, resolvedMode, currentSkillCount, limits) {
|
|
49644
|
+
if (resolvedMode === "scoped") return { eligible: false, reason: "already-scoped" };
|
|
49645
|
+
const limit = limits.get(host);
|
|
49646
|
+
if (limit === void 0) return { eligible: false, reason: "no-observation-for-host" };
|
|
49647
|
+
if (limit.projectedSkills === null) return { eligible: false, reason: "observation-not-comparable" };
|
|
49648
|
+
if (limit.droppedEntries <= 0) return { eligible: false, reason: "no-truncation-observed" };
|
|
49649
|
+
if (currentSkillCount < limit.projectedSkills) {
|
|
49650
|
+
return { eligible: false, reason: "below-observed-skill-volume" };
|
|
49651
|
+
}
|
|
49652
|
+
return {
|
|
49653
|
+
eligible: true,
|
|
49654
|
+
reason: "eligible",
|
|
49655
|
+
droppedEntries: limit.droppedEntries,
|
|
49656
|
+
observedAt: limit.observedAt
|
|
49657
|
+
};
|
|
49658
|
+
}
|
|
49659
|
+
function migrationPromptLines(host, eligibility, settingsPath) {
|
|
49660
|
+
return [
|
|
49661
|
+
`${host}: ${eligibility.droppedEntries} catalogue entries never reach the model.`,
|
|
49662
|
+
`Measured on this machine (${eligibility.observedAt}). This install is on \`legacy-all\`,`,
|
|
49663
|
+
"which ships everything and lets the host drop what does not fit \u2014 silently.",
|
|
49664
|
+
"",
|
|
49665
|
+
"Scoping the projection to your active packs is the alternative. Nothing here",
|
|
49666
|
+
"changes it for you: `projection.mode` is yours to set, by hand or in the GUI.",
|
|
49667
|
+
"",
|
|
49668
|
+
` edit ${settingsPath}`,
|
|
49669
|
+
" projection:",
|
|
49670
|
+
" mode: scoped",
|
|
49671
|
+
"",
|
|
49672
|
+
" or agent-config config (Settings \u2192 projection)",
|
|
49673
|
+
"",
|
|
49674
|
+
"Keeping `legacy-all` is a legitimate choice \u2014 this is a notification, not a gate."
|
|
49675
|
+
];
|
|
49676
|
+
}
|
|
49677
|
+
function readObservationLog(logPath) {
|
|
49678
|
+
if (!fs77.existsSync(logPath)) return [];
|
|
49679
|
+
const out = [];
|
|
49680
|
+
for (const line of fs77.readFileSync(logPath, "utf-8").split("\n")) {
|
|
49681
|
+
const trimmed = line.trim();
|
|
49682
|
+
if (trimmed.length === 0) continue;
|
|
49683
|
+
try {
|
|
49684
|
+
out.push(JSON.parse(trimmed));
|
|
49685
|
+
} catch {
|
|
49686
|
+
continue;
|
|
49687
|
+
}
|
|
49688
|
+
}
|
|
49689
|
+
return out;
|
|
49690
|
+
}
|
|
49691
|
+
function formatPerHostVerdicts(records) {
|
|
49692
|
+
if (records.length === 0) return "no observations recorded yet.";
|
|
49693
|
+
const byHost = /* @__PURE__ */ new Map();
|
|
49694
|
+
for (const record of records) {
|
|
49695
|
+
const bucket = byHost.get(record.host) ?? [];
|
|
49696
|
+
bucket.push(record);
|
|
49697
|
+
byHost.set(record.host, bucket);
|
|
49698
|
+
}
|
|
49699
|
+
const headline = headlineRecordPerHost(records);
|
|
49700
|
+
const lines = [];
|
|
49701
|
+
for (const host of [...byHost.keys()].sort()) {
|
|
49702
|
+
const bucket = byHost.get(host);
|
|
49703
|
+
const latest = headline.get(host);
|
|
49704
|
+
const mode = truncationModeOf(latest);
|
|
49705
|
+
lines.push(
|
|
49706
|
+
`${host}: ${bucket.length} observation(s) \xB7 mode ${mode} \xB7 source ${observationSourceOf(latest)} \xB7 latest ${latest.observed_at}`
|
|
49707
|
+
);
|
|
49708
|
+
lines.push(
|
|
49709
|
+
mode === "budget-strip-and-drop" ? ` offered ${latest.entries_total}, dropped ${latest.dropped_count ?? "unknown"} \u2014 no per-entry selector exists on this host; the quantity is the budget.` : ` verdict ${latest.verdict} \xB7 ${latest.bare_count} bare of ${latest.entries_total}`
|
|
49710
|
+
);
|
|
49711
|
+
}
|
|
49712
|
+
const modes = new Set([...headline.values()].map((r) => truncationModeOf(r)));
|
|
49713
|
+
lines.push("");
|
|
49714
|
+
lines.push(
|
|
49715
|
+
modes.size > 1 ? `hosts: ${byHost.size} \xB7 truncation modes DIFFER (${[...modes].sort().join(", ")}) \u2014 a pooled verdict across them would describe neither host.` : `hosts: ${byHost.size} \xB7 all observed hosts truncate the same way (${[...modes][0] ?? "none"}).`
|
|
49716
|
+
);
|
|
49717
|
+
return lines.join("\n");
|
|
49718
|
+
}
|
|
49719
|
+
function formatReport(report2) {
|
|
49720
|
+
const lines = [];
|
|
49721
|
+
lines.push(`catalogue root: ${report2.catalogueRoot}`);
|
|
49722
|
+
lines.push(`entries: ${report2.entriesTotal}`);
|
|
49723
|
+
lines.push(
|
|
49724
|
+
`observed: ${report2.observedBare.length} bare \xB7 ${report2.observedDescribed.length} described (self-reported)`
|
|
49725
|
+
);
|
|
49726
|
+
if (report2.unknownObserved.length > 0) {
|
|
49727
|
+
lines.push(
|
|
49728
|
+
`\u26A0\uFE0F ${report2.unknownObserved.length} observed name(s) absent from the projection: ${report2.unknownObserved.join(", ")}`
|
|
49729
|
+
);
|
|
49730
|
+
}
|
|
49731
|
+
if (report2.verdict === "insufficient-observation") {
|
|
49732
|
+
lines.push("");
|
|
49733
|
+
lines.push(
|
|
49734
|
+
"verdict: insufficient-observation \u2014 an observation needs at least one bare AND one described entry to separate anything."
|
|
49735
|
+
);
|
|
49736
|
+
return lines.join("\n");
|
|
49737
|
+
}
|
|
49738
|
+
lines.push("");
|
|
49739
|
+
lines.push("selector candidates:");
|
|
49740
|
+
for (const candidate of report2.candidates) {
|
|
49741
|
+
lines.push(` ${candidate.separates ? "\u2705" : "\u274C"} ${candidate.id} \u2014 ${candidate.describes}`);
|
|
49742
|
+
lines.push(` ${candidate.detail}`);
|
|
49743
|
+
}
|
|
49744
|
+
lines.push("");
|
|
49745
|
+
lines.push(
|
|
49746
|
+
report2.verdict === "selector-found" ? "verdict: selector-found \u2014 a delivery fix can act on the separating property above." : "verdict: no-selector \u2014 no measured property separates the groups; the selector is host-internal on this evidence. Publish the null rather than guessing a fix."
|
|
49747
|
+
);
|
|
49748
|
+
return lines.join("\n");
|
|
49749
|
+
}
|
|
49750
|
+
var DEFAULT_CATALOGUE_ROOTS, OBSERVATION_LOG;
|
|
49751
|
+
var init_skill_catalogue = __esm({
|
|
49752
|
+
"src/scripts/_lib/skill_catalogue.ts"() {
|
|
49753
|
+
"use strict";
|
|
49754
|
+
DEFAULT_CATALOGUE_ROOTS = [".claude/skills", "src/skills"];
|
|
49755
|
+
OBSERVATION_LOG = path73.join(
|
|
49756
|
+
"agents",
|
|
49757
|
+
"evidence",
|
|
49758
|
+
"metrics",
|
|
49759
|
+
"skill-catalogue.jsonl"
|
|
49760
|
+
);
|
|
49761
|
+
}
|
|
49762
|
+
});
|
|
49763
|
+
|
|
49764
|
+
// src/scripts/skill_tools/score_skill_relevance.ts
|
|
49765
|
+
var score_skill_relevance_exports = {};
|
|
49766
|
+
__export(score_skill_relevance_exports, {
|
|
49767
|
+
DEFAULT_SKILLS_DIR: () => DEFAULT_SKILLS_DIR,
|
|
49768
|
+
ROOT: () => ROOT3,
|
|
49769
|
+
_SAMPLE: () => _SAMPLE,
|
|
49770
|
+
_parse_frontmatter: () => _parse_frontmatter2,
|
|
49771
|
+
_tokenize: () => _tokenize,
|
|
49772
|
+
main: () => main35,
|
|
49773
|
+
parse_args: () => parse_args7,
|
|
49774
|
+
rank: () => rank
|
|
49775
|
+
});
|
|
49776
|
+
import * as fs78 from "node:fs";
|
|
49239
49777
|
import * as path74 from "node:path";
|
|
49240
|
-
import { fileURLToPath as
|
|
49778
|
+
import { fileURLToPath as fileURLToPath46, pathToFileURL as pathToFileURL35 } from "node:url";
|
|
49779
|
+
function pyLen(s) {
|
|
49780
|
+
let n = 0;
|
|
49781
|
+
for (const _ of s) {
|
|
49782
|
+
n++;
|
|
49783
|
+
}
|
|
49784
|
+
return n;
|
|
49785
|
+
}
|
|
49786
|
+
function _tokenize(text) {
|
|
49787
|
+
const out = /* @__PURE__ */ new Set();
|
|
49788
|
+
const matches = text.toLowerCase().match(TOKEN_RE3) ?? [];
|
|
49789
|
+
for (const t of matches) {
|
|
49790
|
+
if (!STOPWORDS.has(t) && pyLen(t) > 2) {
|
|
49791
|
+
out.add(t);
|
|
49792
|
+
}
|
|
49793
|
+
}
|
|
49794
|
+
return out;
|
|
49795
|
+
}
|
|
49796
|
+
function _parse_frontmatter2(filePath) {
|
|
49797
|
+
const text = fs78.readFileSync(filePath, "utf-8");
|
|
49798
|
+
if (!text.startsWith("---")) {
|
|
49799
|
+
return {};
|
|
49800
|
+
}
|
|
49801
|
+
const end = text.indexOf("\n---", 3);
|
|
49802
|
+
if (end === -1) {
|
|
49803
|
+
return {};
|
|
49804
|
+
}
|
|
49805
|
+
const block = text.slice(3, end);
|
|
49806
|
+
const out = {};
|
|
49807
|
+
let currentListKey = null;
|
|
49808
|
+
for (const raw of _splitlines13(block)) {
|
|
49809
|
+
const line = _rstrip3(raw);
|
|
49810
|
+
if (!line || line.startsWith("#")) {
|
|
49811
|
+
continue;
|
|
49812
|
+
}
|
|
49813
|
+
if (currentListKey !== null && line.startsWith(" - ")) {
|
|
49814
|
+
const existing = out[currentListKey];
|
|
49815
|
+
const list = Array.isArray(existing) ? existing : [];
|
|
49816
|
+
if (!Array.isArray(existing)) {
|
|
49817
|
+
out[currentListKey] = list;
|
|
49818
|
+
}
|
|
49819
|
+
list.push(line.slice(4).trim());
|
|
49820
|
+
continue;
|
|
49821
|
+
}
|
|
49822
|
+
currentListKey = null;
|
|
49823
|
+
const m = /^([a-zA-Z_][\w-]*)[ \t\r\f\v]*:[ \t\r\f\v]*(.*)$/u.exec(line);
|
|
49824
|
+
if (!m) {
|
|
49825
|
+
continue;
|
|
49826
|
+
}
|
|
49827
|
+
const key = m[1];
|
|
49828
|
+
let val = m[2].trim();
|
|
49829
|
+
if (val === "") {
|
|
49830
|
+
currentListKey = key;
|
|
49831
|
+
continue;
|
|
49832
|
+
}
|
|
49833
|
+
if (val.startsWith('"') && val.endsWith('"')) {
|
|
49834
|
+
val = val.slice(1, -1);
|
|
49835
|
+
}
|
|
49836
|
+
out[key] = val;
|
|
49837
|
+
}
|
|
49838
|
+
return out;
|
|
49839
|
+
}
|
|
49840
|
+
function _splitlines13(s) {
|
|
49841
|
+
if (s === "") {
|
|
49842
|
+
return [];
|
|
49843
|
+
}
|
|
49844
|
+
return s.split(/\r\n|\r|\n/u);
|
|
49845
|
+
}
|
|
49846
|
+
function _rstrip3(s) {
|
|
49847
|
+
return s.replace(/\s+$/u, "");
|
|
49848
|
+
}
|
|
49849
|
+
function _load_skills(skillsDir) {
|
|
49850
|
+
const skills = [];
|
|
49851
|
+
for (const skillMd of _globSkillMd(skillsDir)) {
|
|
49852
|
+
const fm = _parse_frontmatter2(skillMd);
|
|
49853
|
+
const rawName = fm["name"];
|
|
49854
|
+
const name = _truthyStr(rawName) ? String(rawName) : path74.basename(path74.dirname(skillMd));
|
|
49855
|
+
const rawDesc = fm["description"];
|
|
49856
|
+
const desc = _truthyStr(rawDesc) ? String(rawDesc) : "";
|
|
49857
|
+
let personas = fm["personas"] ?? [];
|
|
49858
|
+
if (typeof personas === "string") {
|
|
49859
|
+
personas = [personas];
|
|
49860
|
+
}
|
|
49861
|
+
const personaList = [...personas];
|
|
49862
|
+
skills.push({
|
|
49863
|
+
name,
|
|
49864
|
+
description: desc,
|
|
49865
|
+
personas: personaList,
|
|
49866
|
+
terms: _tokenize(name + " " + desc)
|
|
49867
|
+
});
|
|
49868
|
+
}
|
|
49869
|
+
return skills;
|
|
49870
|
+
}
|
|
49871
|
+
function _truthyStr(v) {
|
|
49872
|
+
if (typeof v === "string") {
|
|
49873
|
+
return v !== "";
|
|
49874
|
+
}
|
|
49875
|
+
return false;
|
|
49876
|
+
}
|
|
49877
|
+
function _globSkillMd(root) {
|
|
49878
|
+
let names;
|
|
49879
|
+
try {
|
|
49880
|
+
names = fs78.readdirSync(root);
|
|
49881
|
+
} catch {
|
|
49882
|
+
return [];
|
|
49883
|
+
}
|
|
49884
|
+
const dirs = [];
|
|
49885
|
+
for (const name of names) {
|
|
49886
|
+
const dir = path74.join(root, name);
|
|
49887
|
+
const skillMd = path74.join(dir, "SKILL.md");
|
|
49888
|
+
try {
|
|
49889
|
+
if (fs78.statSync(dir).isDirectory() && fs78.statSync(skillMd).isFile()) {
|
|
49890
|
+
dirs.push(name);
|
|
49891
|
+
}
|
|
49892
|
+
} catch {
|
|
49893
|
+
}
|
|
49894
|
+
}
|
|
49895
|
+
dirs.sort();
|
|
49896
|
+
return dirs.map((name) => path74.join(root, name, "SKILL.md"));
|
|
49897
|
+
}
|
|
49898
|
+
function _score3(taskTerms, skill) {
|
|
49899
|
+
if (taskTerms.size === 0) {
|
|
49900
|
+
return 0;
|
|
49901
|
+
}
|
|
49902
|
+
const skillTerms = skill.terms;
|
|
49903
|
+
let inter = 0;
|
|
49904
|
+
for (const t of taskTerms) {
|
|
49905
|
+
if (skillTerms.has(t)) {
|
|
49906
|
+
inter++;
|
|
49907
|
+
}
|
|
49908
|
+
}
|
|
49909
|
+
const overlap = inter / Math.max(taskTerms.size, 1);
|
|
49910
|
+
let personaHit = 0;
|
|
49911
|
+
const taskLower = [...taskTerms].join(" ");
|
|
49912
|
+
for (const persona of skill.personas) {
|
|
49913
|
+
const slug = String(persona).toLowerCase();
|
|
49914
|
+
const parts = slug.split("-");
|
|
49915
|
+
if (taskLower.includes(slug) || parts.some((part) => taskTerms.has(part))) {
|
|
49916
|
+
personaHit = 1;
|
|
49917
|
+
break;
|
|
49918
|
+
}
|
|
49919
|
+
}
|
|
49920
|
+
return pyRound(overlap * 70 + personaHit * 30, 0);
|
|
49921
|
+
}
|
|
49922
|
+
function rank(task, skillsDir) {
|
|
49923
|
+
const taskTerms = _tokenize(task);
|
|
49924
|
+
const skills = _load_skills(skillsDir);
|
|
49925
|
+
const rows = [];
|
|
49926
|
+
for (const s of skills) {
|
|
49927
|
+
const score = _score3(taskTerms, s);
|
|
49928
|
+
if (score > 0) {
|
|
49929
|
+
rows.push([s.name, score, [...s.personas]]);
|
|
49930
|
+
}
|
|
49931
|
+
}
|
|
49932
|
+
rows.sort((a, b) => {
|
|
49933
|
+
if (b[1] !== a[1]) {
|
|
49934
|
+
return b[1] - a[1];
|
|
49935
|
+
}
|
|
49936
|
+
if (a[0] < b[0]) {
|
|
49937
|
+
return -1;
|
|
49938
|
+
}
|
|
49939
|
+
if (a[0] > b[0]) {
|
|
49940
|
+
return 1;
|
|
49941
|
+
}
|
|
49942
|
+
return 0;
|
|
49943
|
+
});
|
|
49944
|
+
return rows;
|
|
49945
|
+
}
|
|
49946
|
+
function _ljust4(s, w) {
|
|
49947
|
+
const len = pyLen(s);
|
|
49948
|
+
return len >= w ? s : s + " ".repeat(w - len);
|
|
49949
|
+
}
|
|
49950
|
+
function _rjust3(n) {
|
|
49951
|
+
const s = String(n);
|
|
49952
|
+
return s.length >= 3 ? s : " ".repeat(3 - s.length) + s;
|
|
49953
|
+
}
|
|
49954
|
+
function _print_human(rowsIn, top) {
|
|
49955
|
+
let rows = rowsIn;
|
|
49956
|
+
if (top) {
|
|
49957
|
+
rows = rows.slice(0, top);
|
|
49958
|
+
}
|
|
49959
|
+
if (rows.length === 0) {
|
|
49960
|
+
return ["(no relevant skills found)"];
|
|
49961
|
+
}
|
|
49962
|
+
const width = Math.max(...rows.map((r) => pyLen(r[0])));
|
|
49963
|
+
const lines = [];
|
|
49964
|
+
for (const [name, score, personas] of rows) {
|
|
49965
|
+
const personaStr = personas.length > 0 ? personas.join(", ") : "\u2014";
|
|
49966
|
+
lines.push(` ${_rjust3(score)} ${_ljust4(name, width)} ${personaStr}`);
|
|
49967
|
+
}
|
|
49968
|
+
return lines;
|
|
49969
|
+
}
|
|
49970
|
+
function _pyJsonStr3(s) {
|
|
49971
|
+
let out = '"';
|
|
49972
|
+
for (const ch of s) {
|
|
49973
|
+
const code = ch.codePointAt(0);
|
|
49974
|
+
if (ch === '"') {
|
|
49975
|
+
out += '\\"';
|
|
49976
|
+
} else if (ch === "\\") {
|
|
49977
|
+
out += "\\\\";
|
|
49978
|
+
} else if (ch === "\n") {
|
|
49979
|
+
out += "\\n";
|
|
49980
|
+
} else if (ch === "\r") {
|
|
49981
|
+
out += "\\r";
|
|
49982
|
+
} else if (ch === " ") {
|
|
49983
|
+
out += "\\t";
|
|
49984
|
+
} else if (ch === "\b") {
|
|
49985
|
+
out += "\\b";
|
|
49986
|
+
} else if (ch === "\f") {
|
|
49987
|
+
out += "\\f";
|
|
49988
|
+
} else if (code < 32) {
|
|
49989
|
+
out += `\\u${code.toString(16).padStart(4, "0")}`;
|
|
49990
|
+
} else if (code < 127) {
|
|
49991
|
+
out += ch;
|
|
49992
|
+
} else if (code <= 65535) {
|
|
49993
|
+
out += `\\u${code.toString(16).padStart(4, "0")}`;
|
|
49994
|
+
} else {
|
|
49995
|
+
const c = code - 65536;
|
|
49996
|
+
const hi = 55296 + (c >> 10);
|
|
49997
|
+
const lo = 56320 + (c & 1023);
|
|
49998
|
+
out += `\\u${hi.toString(16).padStart(4, "0")}\\u${lo.toString(16).padStart(4, "0")}`;
|
|
49999
|
+
}
|
|
50000
|
+
}
|
|
50001
|
+
return out + '"';
|
|
50002
|
+
}
|
|
50003
|
+
function pyJsonDumpsIndent2(obj, level = 0) {
|
|
50004
|
+
if (obj === null) {
|
|
50005
|
+
return "null";
|
|
50006
|
+
}
|
|
50007
|
+
if (typeof obj === "number") {
|
|
50008
|
+
return String(obj);
|
|
50009
|
+
}
|
|
50010
|
+
if (typeof obj === "string") {
|
|
50011
|
+
return _pyJsonStr3(obj);
|
|
50012
|
+
}
|
|
50013
|
+
if (obj === true) {
|
|
50014
|
+
return "true";
|
|
50015
|
+
}
|
|
50016
|
+
if (obj === false) {
|
|
50017
|
+
return "false";
|
|
50018
|
+
}
|
|
50019
|
+
if (Array.isArray(obj)) {
|
|
50020
|
+
if (obj.length === 0) {
|
|
50021
|
+
return "[]";
|
|
50022
|
+
}
|
|
50023
|
+
const pad2 = " ".repeat(2 * (level + 1));
|
|
50024
|
+
const closePad2 = " ".repeat(2 * level);
|
|
50025
|
+
return `[
|
|
50026
|
+
${obj.map((v) => pad2 + pyJsonDumpsIndent2(v, level + 1)).join(",\n")}
|
|
50027
|
+
${closePad2}]`;
|
|
50028
|
+
}
|
|
50029
|
+
const keys = Object.keys(obj);
|
|
50030
|
+
if (keys.length === 0) {
|
|
50031
|
+
return "{}";
|
|
50032
|
+
}
|
|
50033
|
+
const pad = " ".repeat(2 * (level + 1));
|
|
50034
|
+
const closePad = " ".repeat(2 * level);
|
|
50035
|
+
const parts = keys.map(
|
|
50036
|
+
(k) => `${pad}${_pyJsonStr3(k)}: ${pyJsonDumpsIndent2(obj[k], level + 1)}`
|
|
50037
|
+
);
|
|
50038
|
+
return `{
|
|
50039
|
+
${parts.join(",\n")}
|
|
50040
|
+
${closePad}}`;
|
|
50041
|
+
}
|
|
50042
|
+
function _argError10(message) {
|
|
50043
|
+
process.stderr.write(`${PROG5}: error: ${message}
|
|
50044
|
+
`);
|
|
50045
|
+
process.exit(2);
|
|
50046
|
+
}
|
|
50047
|
+
function _parseInt2(raw) {
|
|
50048
|
+
if (!/^[+-]?\d+$/u.test(raw.trim())) {
|
|
50049
|
+
_argError10(`argument --top: invalid int value: '${raw}'`);
|
|
50050
|
+
}
|
|
50051
|
+
return parseInt(raw, 10);
|
|
50052
|
+
}
|
|
50053
|
+
function parse_args7(argv) {
|
|
50054
|
+
const args = {
|
|
50055
|
+
task: "",
|
|
50056
|
+
skills_dir: DEFAULT_SKILLS_DIR,
|
|
50057
|
+
top: 0,
|
|
50058
|
+
json: false,
|
|
50059
|
+
sample: false
|
|
50060
|
+
};
|
|
50061
|
+
for (let i = 0; i < argv.length; i++) {
|
|
50062
|
+
const a = argv[i];
|
|
50063
|
+
if (a === "--json") {
|
|
50064
|
+
args.json = true;
|
|
50065
|
+
} else if (a === "--sample") {
|
|
50066
|
+
args.sample = true;
|
|
50067
|
+
} else if (a === "--task") {
|
|
50068
|
+
const v = argv[++i];
|
|
50069
|
+
if (v === void 0) {
|
|
50070
|
+
_argError10("argument --task: expected one argument");
|
|
50071
|
+
}
|
|
50072
|
+
args.task = v;
|
|
50073
|
+
} else if (a.startsWith("--task=")) {
|
|
50074
|
+
args.task = a.slice("--task=".length);
|
|
50075
|
+
} else if (a === "--skills-dir") {
|
|
50076
|
+
const v = argv[++i];
|
|
50077
|
+
if (v === void 0) {
|
|
50078
|
+
_argError10("argument --skills-dir: expected one argument");
|
|
50079
|
+
}
|
|
50080
|
+
args.skills_dir = v;
|
|
50081
|
+
} else if (a.startsWith("--skills-dir=")) {
|
|
50082
|
+
args.skills_dir = a.slice("--skills-dir=".length);
|
|
50083
|
+
} else if (a === "--top") {
|
|
50084
|
+
const v = argv[++i];
|
|
50085
|
+
if (v === void 0) {
|
|
50086
|
+
_argError10("argument --top: expected one argument");
|
|
50087
|
+
}
|
|
50088
|
+
args.top = _parseInt2(v);
|
|
50089
|
+
} else if (a.startsWith("--top=")) {
|
|
50090
|
+
args.top = _parseInt2(a.slice("--top=".length));
|
|
50091
|
+
} else {
|
|
50092
|
+
_argError10(`unrecognized arguments: ${a}`);
|
|
50093
|
+
}
|
|
50094
|
+
}
|
|
50095
|
+
return args;
|
|
50096
|
+
}
|
|
50097
|
+
function main35(argv = null) {
|
|
50098
|
+
const args = parse_args7(argv ?? process.argv.slice(2));
|
|
50099
|
+
const task = args.sample ? _SAMPLE.task : args.task;
|
|
50100
|
+
if (!task) {
|
|
50101
|
+
_argError10("--task is required (or pass --sample)");
|
|
50102
|
+
}
|
|
50103
|
+
const rows = rank(task, args.skills_dir);
|
|
50104
|
+
if (args.json) {
|
|
50105
|
+
const sliced = args.top ? rows.slice(0, args.top) : rows;
|
|
50106
|
+
const payload = sliced.map(([n, s, p]) => ({ name: n, score: s, personas: p }));
|
|
50107
|
+
process.stdout.write(pyJsonDumpsIndent2({ task, ranked: payload }));
|
|
50108
|
+
process.stdout.write("\n");
|
|
50109
|
+
} else {
|
|
50110
|
+
const lines = _print_human(rows, args.top || null);
|
|
50111
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
50112
|
+
}
|
|
50113
|
+
return 0;
|
|
50114
|
+
}
|
|
50115
|
+
function _isCliEntry32() {
|
|
50116
|
+
if (process.argv[1] === void 0) {
|
|
50117
|
+
return false;
|
|
50118
|
+
}
|
|
50119
|
+
const argvUrl = pathToFileURL35(path74.resolve(process.argv[1])).href;
|
|
50120
|
+
if (import.meta.url === argvUrl) {
|
|
50121
|
+
return true;
|
|
50122
|
+
}
|
|
50123
|
+
try {
|
|
50124
|
+
const here = fs78.realpathSync(fileURLToPath46(import.meta.url));
|
|
50125
|
+
const argv = fs78.realpathSync(path74.resolve(process.argv[1]));
|
|
50126
|
+
return here === argv;
|
|
50127
|
+
} catch {
|
|
50128
|
+
return false;
|
|
50129
|
+
}
|
|
50130
|
+
}
|
|
50131
|
+
var _HERE23, ROOT3, DEFAULT_SKILLS_DIR, TOKEN_RE3, STOPWORDS, PROG5, _SAMPLE, _isMain5;
|
|
50132
|
+
var init_score_skill_relevance = __esm({
|
|
50133
|
+
"src/scripts/skill_tools/score_skill_relevance.ts"() {
|
|
50134
|
+
"use strict";
|
|
50135
|
+
init_value_ladder();
|
|
50136
|
+
_HERE23 = fileURLToPath46(import.meta.url);
|
|
50137
|
+
ROOT3 = path74.resolve(path74.dirname(_HERE23), "..", "..", "..");
|
|
50138
|
+
DEFAULT_SKILLS_DIR = path74.join(ROOT3, ".agent-src.uncondensed", "skills");
|
|
50139
|
+
TOKEN_RE3 = /[a-z][a-z0-9]+/g;
|
|
50140
|
+
STOPWORDS = /* @__PURE__ */ new Set([
|
|
50141
|
+
"the",
|
|
50142
|
+
"a",
|
|
50143
|
+
"an",
|
|
50144
|
+
"and",
|
|
50145
|
+
"or",
|
|
50146
|
+
"but",
|
|
50147
|
+
"of",
|
|
50148
|
+
"for",
|
|
50149
|
+
"with",
|
|
50150
|
+
"to",
|
|
50151
|
+
"in",
|
|
50152
|
+
"on",
|
|
50153
|
+
"at",
|
|
50154
|
+
"by",
|
|
50155
|
+
"from",
|
|
50156
|
+
"as",
|
|
50157
|
+
"is",
|
|
50158
|
+
"are",
|
|
50159
|
+
"was",
|
|
50160
|
+
"were",
|
|
50161
|
+
"be",
|
|
50162
|
+
"been",
|
|
50163
|
+
"this",
|
|
50164
|
+
"that",
|
|
50165
|
+
"these",
|
|
50166
|
+
"those",
|
|
50167
|
+
"it",
|
|
50168
|
+
"its",
|
|
50169
|
+
"use",
|
|
50170
|
+
"when",
|
|
50171
|
+
"even",
|
|
50172
|
+
"via",
|
|
50173
|
+
"via:",
|
|
50174
|
+
"into",
|
|
50175
|
+
"onto",
|
|
50176
|
+
"use:",
|
|
50177
|
+
"skill",
|
|
50178
|
+
"skills",
|
|
50179
|
+
"task",
|
|
50180
|
+
"tasks",
|
|
50181
|
+
"code",
|
|
50182
|
+
"file",
|
|
50183
|
+
"files",
|
|
50184
|
+
"doing",
|
|
50185
|
+
"make",
|
|
50186
|
+
"do",
|
|
50187
|
+
"go",
|
|
50188
|
+
"get",
|
|
50189
|
+
"set",
|
|
50190
|
+
"not",
|
|
50191
|
+
"no",
|
|
50192
|
+
"yes",
|
|
50193
|
+
"any",
|
|
50194
|
+
"some",
|
|
50195
|
+
"all",
|
|
50196
|
+
"one",
|
|
50197
|
+
"two",
|
|
50198
|
+
"new",
|
|
50199
|
+
"old",
|
|
50200
|
+
"user",
|
|
50201
|
+
"users",
|
|
50202
|
+
"our",
|
|
50203
|
+
"your",
|
|
50204
|
+
"their",
|
|
50205
|
+
"they",
|
|
50206
|
+
"we",
|
|
50207
|
+
"you",
|
|
50208
|
+
"i",
|
|
50209
|
+
"me"
|
|
50210
|
+
]);
|
|
50211
|
+
PROG5 = "score_skill_relevance.py";
|
|
50212
|
+
_SAMPLE = {
|
|
50213
|
+
task: "build a livewire component for the user dashboard with reactive state"
|
|
50214
|
+
};
|
|
50215
|
+
_isMain5 = _isCliEntry32();
|
|
50216
|
+
if (_isMain5) {
|
|
50217
|
+
process.exitCode = main35();
|
|
50218
|
+
}
|
|
50219
|
+
}
|
|
50220
|
+
});
|
|
50221
|
+
|
|
50222
|
+
// src/scripts/mcp_server/__main__.ts
|
|
50223
|
+
import * as path76 from "node:path";
|
|
50224
|
+
import { fileURLToPath as fileURLToPath48 } from "node:url";
|
|
49241
50225
|
|
|
49242
50226
|
// src/scripts/mcp_server/index.ts
|
|
49243
50227
|
var __version__ = "0.1.0";
|
|
@@ -49284,9 +50268,9 @@ init_prompts();
|
|
|
49284
50268
|
init_resources();
|
|
49285
50269
|
|
|
49286
50270
|
// src/scripts/mcp_server/tools.ts
|
|
49287
|
-
import * as
|
|
49288
|
-
import * as
|
|
49289
|
-
import { fileURLToPath as
|
|
50271
|
+
import * as fs79 from "node:fs";
|
|
50272
|
+
import * as path75 from "node:path";
|
|
50273
|
+
import { fileURLToPath as fileURLToPath47 } from "node:url";
|
|
49290
50274
|
|
|
49291
50275
|
// src/scripts/chat_history.ts
|
|
49292
50276
|
init_memory_lookup();
|
|
@@ -51519,9 +52503,9 @@ function _strip8(s) {
|
|
|
51519
52503
|
}
|
|
51520
52504
|
function _resolvePath2(p) {
|
|
51521
52505
|
try {
|
|
51522
|
-
return
|
|
52506
|
+
return fs79.realpathSync(p);
|
|
51523
52507
|
} catch {
|
|
51524
|
-
return
|
|
52508
|
+
return path75.resolve(p);
|
|
51525
52509
|
}
|
|
51526
52510
|
}
|
|
51527
52511
|
function _resolveConsumerRoot(override) {
|
|
@@ -51531,14 +52515,14 @@ function _resolveConsumerRoot(override) {
|
|
|
51531
52515
|
return _resolvePath2(process.cwd());
|
|
51532
52516
|
}
|
|
51533
52517
|
function _relativeUnder(target, root) {
|
|
51534
|
-
const rel =
|
|
52518
|
+
const rel = path75.relative(root, target);
|
|
51535
52519
|
if (rel === "") {
|
|
51536
52520
|
return "";
|
|
51537
52521
|
}
|
|
51538
|
-
if (rel.startsWith("..") ||
|
|
52522
|
+
if (rel.startsWith("..") || path75.isAbsolute(rel)) {
|
|
51539
52523
|
return null;
|
|
51540
52524
|
}
|
|
51541
|
-
return rel.split(
|
|
52525
|
+
return rel.split(path75.sep).join("/");
|
|
51542
52526
|
}
|
|
51543
52527
|
function _reprStrList(values) {
|
|
51544
52528
|
return `[${values.map((v) => `'${v}'`).join(", ")}]`;
|
|
@@ -51547,11 +52531,11 @@ function _validateInTreePath(raw, consumerRoot) {
|
|
|
51547
52531
|
const root = _resolvePath2(consumerRoot);
|
|
51548
52532
|
let target;
|
|
51549
52533
|
if (raw === null || raw === void 0 || raw === "") {
|
|
51550
|
-
target =
|
|
51551
|
-
} else if (
|
|
52534
|
+
target = path75.join(root, "agents", "runtime", ".agent-chat-history");
|
|
52535
|
+
} else if (path75.isAbsolute(raw)) {
|
|
51552
52536
|
target = _resolvePath2(raw);
|
|
51553
52537
|
} else {
|
|
51554
|
-
target = _resolvePath2(
|
|
52538
|
+
target = _resolvePath2(path75.join(root, raw));
|
|
51555
52539
|
}
|
|
51556
52540
|
const rel = _relativeUnder(target, root);
|
|
51557
52541
|
if (rel === null) {
|
|
@@ -51589,11 +52573,11 @@ async function _lintSkillsHandler(args, consumerRoot) {
|
|
|
51589
52573
|
if (typeof raw !== "string") {
|
|
51590
52574
|
throw new Error("'paths' entries must be strings");
|
|
51591
52575
|
}
|
|
51592
|
-
const resolved =
|
|
52576
|
+
const resolved = path75.isAbsolute(raw) ? _resolvePath2(raw) : _resolvePath2(path75.join(root, raw));
|
|
51593
52577
|
if (_relativeUnder(resolved, root) === null) {
|
|
51594
52578
|
throw new Error(`path escapes consumer_root: ${resolved}`);
|
|
51595
52579
|
}
|
|
51596
|
-
if (
|
|
52580
|
+
if (fs79.existsSync(resolved)) {
|
|
51597
52581
|
paths.push(resolved);
|
|
51598
52582
|
}
|
|
51599
52583
|
}
|
|
@@ -51630,7 +52614,7 @@ async function _chatHistoryAppendHandler(args, consumerRoot) {
|
|
|
51630
52614
|
if (typeof minSchema !== "number" || !Number.isInteger(minSchema) || typeof minSchema === "boolean") {
|
|
51631
52615
|
throw new Error("'min_schema_version' must be an integer");
|
|
51632
52616
|
}
|
|
51633
|
-
const existingHeader =
|
|
52617
|
+
const existingHeader = fs79.existsSync(target) ? _chReadHeader(target) : null;
|
|
51634
52618
|
const observed = existingHeader !== null && typeof existingHeader === "object" ? _pyInt7(existingHeader.v ?? 0) : SCHEMA_VERSION3;
|
|
51635
52619
|
if (observed < minSchema) {
|
|
51636
52620
|
throw new Error(`chat-history schema ${observed} below required ${minSchema}`);
|
|
@@ -51645,8 +52629,8 @@ async function _chatHistoryAppendHandler(args, consumerRoot) {
|
|
|
51645
52629
|
session: session === void 0 ? null : session
|
|
51646
52630
|
};
|
|
51647
52631
|
}
|
|
51648
|
-
if (!
|
|
51649
|
-
|
|
52632
|
+
if (!fs79.existsSync(target) || _chReadHeader(target) === null) {
|
|
52633
|
+
fs79.mkdirSync(path75.dirname(target), { recursive: true });
|
|
51650
52634
|
_chInit(target);
|
|
51651
52635
|
}
|
|
51652
52636
|
_chAppend(entry, target, session ?? null);
|
|
@@ -51690,7 +52674,7 @@ async function _chatHistoryReadHandler(args, consumerRoot) {
|
|
|
51690
52674
|
if (detail !== "full" && detail !== "index") {
|
|
51691
52675
|
throw new Error("'detail' must be 'index' or 'full'");
|
|
51692
52676
|
}
|
|
51693
|
-
if (!
|
|
52677
|
+
if (!fs79.existsSync(target)) {
|
|
51694
52678
|
return { path: target, entries: [], count: 0 };
|
|
51695
52679
|
}
|
|
51696
52680
|
if (around !== void 0 && around !== null) {
|
|
@@ -51792,8 +52776,8 @@ async function _memoryStatusHandler(_args, consumerRoot) {
|
|
|
51792
52776
|
}
|
|
51793
52777
|
return result;
|
|
51794
52778
|
}
|
|
51795
|
-
var _PACKAGE_ROOT3 =
|
|
51796
|
-
|
|
52779
|
+
var _PACKAGE_ROOT3 = path75.resolve(
|
|
52780
|
+
path75.dirname(fileURLToPath47(import.meta.url)),
|
|
51797
52781
|
"..",
|
|
51798
52782
|
"..",
|
|
51799
52783
|
".."
|
|
@@ -51837,10 +52821,10 @@ async function _memorySignalHandler(args, consumerRoot) {
|
|
|
51837
52821
|
async function _roadmapProgressHandler(args, consumerRoot) {
|
|
51838
52822
|
const dryRun = _pyTruthy6(args.dry_run ?? false);
|
|
51839
52823
|
const root = _resolvePath2(consumerRoot);
|
|
51840
|
-
const roadmapRoot =
|
|
51841
|
-
const target =
|
|
52824
|
+
const roadmapRoot = path75.join(root, "agents", "roadmaps");
|
|
52825
|
+
const target = path75.join(root, "agents", "roadmaps-progress.md");
|
|
51842
52826
|
const urp = await Promise.resolve().then(() => (init_update_roadmap_progress(), update_roadmap_progress_exports));
|
|
51843
|
-
if (!
|
|
52827
|
+
if (!fs79.existsSync(roadmapRoot)) {
|
|
51844
52828
|
return {
|
|
51845
52829
|
written: false,
|
|
51846
52830
|
path: target,
|
|
@@ -51855,7 +52839,7 @@ async function _roadmapProgressHandler(args, consumerRoot) {
|
|
|
51855
52839
|
const stepsDone = roadmaps.reduce((s, r) => s + r.done, 0);
|
|
51856
52840
|
const stepsTotal = roadmaps.reduce((s, r) => s + r.total_active, 0);
|
|
51857
52841
|
if (!dryRun) {
|
|
51858
|
-
|
|
52842
|
+
fs79.writeFileSync(target, content, "utf-8");
|
|
51859
52843
|
}
|
|
51860
52844
|
return {
|
|
51861
52845
|
written: !dryRun,
|
|
@@ -51876,11 +52860,11 @@ async function _roadmapArchiveHandler(_args, consumerRoot) {
|
|
|
51876
52860
|
let dashboardRegenerated = false;
|
|
51877
52861
|
if (archived.length > 0) {
|
|
51878
52862
|
const urp = await Promise.resolve().then(() => (init_update_roadmap_progress(), update_roadmap_progress_exports));
|
|
51879
|
-
const roadmapRoot =
|
|
51880
|
-
if (
|
|
52863
|
+
const roadmapRoot = path75.join(root, "agents", "roadmaps");
|
|
52864
|
+
if (fs79.existsSync(roadmapRoot)) {
|
|
51881
52865
|
const roadmaps = urp.collect(roadmapRoot);
|
|
51882
|
-
|
|
51883
|
-
|
|
52866
|
+
fs79.writeFileSync(
|
|
52867
|
+
path75.join(root, "agents", "roadmaps-progress.md"),
|
|
51884
52868
|
urp.render(roadmaps, urp.collect_bundles(root)),
|
|
51885
52869
|
"utf-8"
|
|
51886
52870
|
);
|
|
@@ -51896,9 +52880,9 @@ async function _roadmapArchiveHandler(_args, consumerRoot) {
|
|
|
51896
52880
|
async function _capabilitiesIndexHandler(args, consumerRoot) {
|
|
51897
52881
|
const check = _pyTruthy6(args.check ?? false);
|
|
51898
52882
|
const cap = await Promise.resolve().then(() => (init_generate_capabilities_index(), generate_capabilities_index_exports));
|
|
51899
|
-
const out =
|
|
52883
|
+
const out = path75.join(_PACKAGE_ROOT3, "CAPABILITIES.yaml");
|
|
51900
52884
|
const content = cap.build();
|
|
51901
|
-
const onDisk =
|
|
52885
|
+
const onDisk = fs79.existsSync(out) ? fs79.readFileSync(out, "utf-8") : "";
|
|
51902
52886
|
const drift = onDisk !== content;
|
|
51903
52887
|
if (check) {
|
|
51904
52888
|
return { check: true, written: false, drift, path: out };
|
|
@@ -51909,7 +52893,7 @@ async function _capabilitiesIndexHandler(args, consumerRoot) {
|
|
|
51909
52893
|
`CAPABILITIES.yaml path escapes consumer_root: ${out} not under ${root}`
|
|
51910
52894
|
);
|
|
51911
52895
|
}
|
|
51912
|
-
|
|
52896
|
+
fs79.writeFileSync(out, content, "utf-8");
|
|
51913
52897
|
return { check: false, written: true, drift, path: out };
|
|
51914
52898
|
}
|
|
51915
52899
|
async function _runDoctorLeg(consumerRoot) {
|
|
@@ -52009,11 +52993,11 @@ async function _councilEstimateHandler(args, consumerRoot) {
|
|
|
52009
52993
|
throw new Error("'depth' must be 'shallow' or 'deep' when provided");
|
|
52010
52994
|
}
|
|
52011
52995
|
const root = _resolvePath2(consumerRoot);
|
|
52012
|
-
const target =
|
|
52996
|
+
const target = path75.isAbsolute(inputRaw) ? _resolvePath2(inputRaw) : _resolvePath2(path75.join(root, inputRaw));
|
|
52013
52997
|
if (_relativeUnder(target, root) === null) {
|
|
52014
52998
|
throw new Error(`path escapes consumer_root: ${target}`);
|
|
52015
52999
|
}
|
|
52016
|
-
if (!
|
|
53000
|
+
if (!fs79.existsSync(target)) {
|
|
52017
53001
|
throw new Error(`input_path not found: ${target}`);
|
|
52018
53002
|
}
|
|
52019
53003
|
const cli = await Promise.resolve().then(() => (init_council_cli(), council_cli_exports));
|
|
@@ -52075,18 +53059,18 @@ async function _runTestsHandler(args, consumerRoot) {
|
|
|
52075
53059
|
if (typeof relPathRaw !== "string" || !_strip8(relPathRaw)) {
|
|
52076
53060
|
throw new Error("'path' must be a non-empty string when provided");
|
|
52077
53061
|
}
|
|
52078
|
-
const resolved =
|
|
53062
|
+
const resolved = path75.isAbsolute(relPathRaw) ? _resolvePath2(relPathRaw) : _resolvePath2(path75.join(root, relPathRaw));
|
|
52079
53063
|
const rel = _relativeUnder(resolved, root);
|
|
52080
53064
|
if (rel === null) {
|
|
52081
53065
|
throw new Error(`path escapes consumer_root: ${resolved}`);
|
|
52082
53066
|
}
|
|
52083
|
-
if (!
|
|
53067
|
+
if (!fs79.existsSync(resolved)) {
|
|
52084
53068
|
throw new Error(`path not found: ${resolved}`);
|
|
52085
53069
|
}
|
|
52086
53070
|
relArg = rel;
|
|
52087
53071
|
}
|
|
52088
|
-
const vitestEntry =
|
|
52089
|
-
if (!
|
|
53072
|
+
const vitestEntry = path75.join(root, "node_modules", "vitest", "vitest.mjs");
|
|
53073
|
+
if (!fs79.existsSync(vitestEntry)) {
|
|
52090
53074
|
throw new Error(
|
|
52091
53075
|
"run_tests pilot supports vitest projects only \u2014 node_modules/vitest/vitest.mjs not found under consumer_root"
|
|
52092
53076
|
);
|
|
@@ -52191,7 +53175,55 @@ async function _readResourceBodyHandler(args, consumerRoot) {
|
|
|
52191
53175
|
body: resource.body
|
|
52192
53176
|
};
|
|
52193
53177
|
}
|
|
53178
|
+
async function _suggestSkillForTaskHandler(args, consumerRoot) {
|
|
53179
|
+
const task = typeof args["task"] === "string" ? args["task"] : "";
|
|
53180
|
+
if (task.trim() === "") {
|
|
53181
|
+
return { status: "error", error: "task must be a non-empty string", suggestions: [] };
|
|
53182
|
+
}
|
|
53183
|
+
const limitRaw = args["limit"];
|
|
53184
|
+
const limit = typeof limitRaw === "number" && Number.isFinite(limitRaw) ? Math.floor(limitRaw) : 5;
|
|
53185
|
+
const catalogue = await Promise.resolve().then(() => (init_skill_catalogue(), skill_catalogue_exports));
|
|
53186
|
+
const skillsDir = catalogue.resolveSkillsRoot(consumerRoot);
|
|
53187
|
+
if (skillsDir === null) {
|
|
53188
|
+
return {
|
|
53189
|
+
status: "no_catalogue",
|
|
53190
|
+
searched: [...catalogue.DEFAULT_CATALOGUE_ROOTS],
|
|
53191
|
+
consumer_root: consumerRoot,
|
|
53192
|
+
suggestions: []
|
|
53193
|
+
};
|
|
53194
|
+
}
|
|
53195
|
+
const { rank: rank2 } = await Promise.resolve().then(() => (init_score_skill_relevance(), score_skill_relevance_exports));
|
|
53196
|
+
const rows = rank2(task, skillsDir).slice(0, Math.max(1, limit));
|
|
53197
|
+
return {
|
|
53198
|
+
status: "ok",
|
|
53199
|
+
skills_root: skillsDir,
|
|
53200
|
+
suggestions: rows.map(([name, score, personas]) => ({ skill: name, score, personas }))
|
|
53201
|
+
};
|
|
53202
|
+
}
|
|
52194
53203
|
var ALLOWLIST = {
|
|
53204
|
+
suggest_skill_for_task: {
|
|
53205
|
+
name: "suggest_skill_for_task",
|
|
53206
|
+
side_effect: "ro",
|
|
53207
|
+
description: "Match a free-form task description to the most relevant skills, ranked by a deterministic keyword scorer over SKILL.md frontmatter. Use when a skill you need is not in the catalogue the host delivered \u2014 a measured host dropped 402 entries from its model-visible list \u2014 so asking by name is impossible while asking by task is not. Read-only: no shell, no writes, and no skill bodies are returned, only names, scores and declared personas.",
|
|
53208
|
+
input_schema: {
|
|
53209
|
+
type: "object",
|
|
53210
|
+
required: ["task"],
|
|
53211
|
+
properties: {
|
|
53212
|
+
task: {
|
|
53213
|
+
type: "string",
|
|
53214
|
+
description: "Free-form description of the task to match skills against."
|
|
53215
|
+
},
|
|
53216
|
+
limit: {
|
|
53217
|
+
type: "integer",
|
|
53218
|
+
minimum: 1,
|
|
53219
|
+
default: 5,
|
|
53220
|
+
description: "Maximum number of skills to return. Defaults to 5."
|
|
53221
|
+
}
|
|
53222
|
+
},
|
|
53223
|
+
additionalProperties: false
|
|
53224
|
+
},
|
|
53225
|
+
handler: _suggestSkillForTaskHandler
|
|
53226
|
+
},
|
|
52195
53227
|
lint_skills: {
|
|
52196
53228
|
name: "lint_skills",
|
|
52197
53229
|
side_effect: "ro",
|
|
@@ -52692,8 +53724,8 @@ function _strCmp3(a, b) {
|
|
|
52692
53724
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
52693
53725
|
}
|
|
52694
53726
|
function _pathlibCompare3(a, b) {
|
|
52695
|
-
const pa = a.split(
|
|
52696
|
-
const pb = b.split(
|
|
53727
|
+
const pa = a.split(path75.sep);
|
|
53728
|
+
const pb = b.split(path75.sep);
|
|
52697
53729
|
const n = Math.min(pa.length, pb.length);
|
|
52698
53730
|
for (let i = 0; i < n; i++) {
|
|
52699
53731
|
const c = _strCmp3(pa[i], pb[i]);
|
|
@@ -52912,18 +53944,18 @@ async function _serveOverSdk(server) {
|
|
|
52912
53944
|
const transport = new StdioServerTransport();
|
|
52913
53945
|
await sdkServer.connect(transport);
|
|
52914
53946
|
}
|
|
52915
|
-
function
|
|
53947
|
+
function main36() {
|
|
52916
53948
|
void run_stdio();
|
|
52917
53949
|
}
|
|
52918
53950
|
|
|
52919
53951
|
// src/scripts/mcp_server/__main__.ts
|
|
52920
|
-
var _selfPath =
|
|
52921
|
-
var _invokedDirectly2 = globalThis.__AC_MCP_BUNDLE_DIRECT === true || process.argv[1] !== void 0 &&
|
|
53952
|
+
var _selfPath = fileURLToPath48(import.meta.url);
|
|
53953
|
+
var _invokedDirectly2 = globalThis.__AC_MCP_BUNDLE_DIRECT === true || process.argv[1] !== void 0 && path76.resolve(process.argv[1]) === path76.resolve(_selfPath);
|
|
52922
53954
|
if (_invokedDirectly2) {
|
|
52923
|
-
|
|
53955
|
+
main36();
|
|
52924
53956
|
}
|
|
52925
53957
|
export {
|
|
52926
|
-
|
|
53958
|
+
main36 as main
|
|
52927
53959
|
};
|
|
52928
53960
|
/*! Bundled license information:
|
|
52929
53961
|
|