tickmarkr 2.3.0 → 2.4.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/dist/adapters/catalog-remote.d.ts +1 -4
- package/dist/adapters/catalog-remote.js +52 -42
- package/dist/adapters/catalog.js +5 -3
- package/dist/adapters/claude-code.d.ts +1 -1
- package/dist/adapters/claude-code.js +8 -5
- package/dist/adapters/model-lints.d.ts +9 -5
- package/dist/adapters/model-lints.js +56 -15
- package/dist/adapters/model-windows.js +11 -0
- package/dist/adapters/prompt.js +1 -0
- package/dist/adapters/qwen.d.ts +5 -0
- package/dist/adapters/qwen.js +153 -0
- package/dist/adapters/types.d.ts +1 -0
- package/dist/adapters/types.js +1 -0
- package/dist/cli/commands/compile.js +32 -6
- package/dist/cli/commands/doctor.d.ts +4 -3
- package/dist/cli/commands/doctor.js +20 -6
- package/dist/cli/commands/fleet.d.ts +4 -0
- package/dist/cli/commands/fleet.js +53 -14
- package/dist/cli/commands/plan.js +29 -5
- package/dist/cli/commands/status.d.ts +1 -0
- package/dist/cli/commands/status.js +45 -1
- package/dist/cli/commands/verify.d.ts +1 -0
- package/dist/cli/commands/verify.js +5 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/compile/collateral.d.ts +2 -9
- package/dist/compile/collateral.js +2 -9
- package/dist/compile/index.d.ts +4 -1
- package/dist/compile/index.js +41 -7
- package/dist/compile/native.d.ts +4 -2
- package/dist/compile/native.js +55 -6
- package/dist/compile/ownership.js +34 -9
- package/dist/config/config.d.ts +1 -0
- package/dist/config/config.js +51 -5
- package/dist/drivers/herdr.d.ts +1 -0
- package/dist/drivers/herdr.js +11 -1
- package/dist/drivers/orca.d.ts +14 -1
- package/dist/drivers/orca.js +114 -15
- package/dist/drivers/types.d.ts +10 -0
- package/dist/gates/baseline.js +26 -7
- package/dist/gates/review.d.ts +4 -2
- package/dist/gates/review.js +24 -13
- package/dist/gates/run-gates.d.ts +5 -2
- package/dist/gates/run-gates.js +34 -17
- package/dist/route/preference.d.ts +4 -0
- package/dist/route/preference.js +40 -0
- package/dist/route/router.js +15 -2
- package/dist/run/consult.d.ts +1 -0
- package/dist/run/consult.js +34 -7
- package/dist/run/daemon.d.ts +4 -0
- package/dist/run/daemon.js +128 -50
- package/dist/run/git.d.ts +2 -0
- package/dist/run/git.js +36 -5
- package/dist/run/journal.js +4 -1
- package/dist/tui/ink/fleet-app.d.ts +4 -0
- package/dist/tui/ink/fleet-app.js +45 -16
- package/package.json +59 -1
|
@@ -68,6 +68,10 @@ export type FleetModelGroup = {
|
|
|
68
68
|
detectedAt?: string;
|
|
69
69
|
suggestion?: FleetModelSuggestion;
|
|
70
70
|
evidence?: FleetModelEvidence;
|
|
71
|
+
classifyModel?: string;
|
|
72
|
+
variants?: string[];
|
|
73
|
+
foldedModels?: string[];
|
|
74
|
+
score?: number;
|
|
71
75
|
}>;
|
|
72
76
|
};
|
|
73
77
|
export type FleetClassification = {
|
|
@@ -96,7 +96,8 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
96
96
|
};
|
|
97
97
|
const groupRows = (group) => {
|
|
98
98
|
const rows = group.rows.map((row) => {
|
|
99
|
-
const staged = ui.classifications.find((classification) => classification.adapter === group.adapter
|
|
99
|
+
const staged = ui.classifications.find((classification) => classification.adapter === group.adapter
|
|
100
|
+
&& (classification.model === row.model || classification.model === row.classifyModel));
|
|
100
101
|
return {
|
|
101
102
|
adapter: group.adapter,
|
|
102
103
|
model: row.model,
|
|
@@ -105,10 +106,14 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
105
106
|
suggestion: row.suggestion,
|
|
106
107
|
evidence: row.evidence,
|
|
107
108
|
channel: group.channel,
|
|
109
|
+
classifyModel: row.classifyModel,
|
|
110
|
+
variants: row.variants,
|
|
111
|
+
foldedModels: row.foldedModels,
|
|
112
|
+
score: row.score,
|
|
108
113
|
denied: ui.denyModels.has(`${group.adapter}:${row.model}`),
|
|
109
114
|
};
|
|
110
115
|
});
|
|
111
|
-
const known = new Set(rows.
|
|
116
|
+
const known = new Set(rows.flatMap((row) => row.classifyModel ? [row.model, row.classifyModel] : [row.model]));
|
|
112
117
|
for (const staged of ui.classifications) {
|
|
113
118
|
if (staged.adapter === group.adapter && !known.has(staged.model)) {
|
|
114
119
|
rows.push({
|
|
@@ -125,10 +130,21 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
125
130
|
const matches = (label, f) => f === "" || label.toLowerCase().includes(f.toLowerCase());
|
|
126
131
|
// Operator directive 2026-08-13: retired shapes (dated snapshots, previews, non-worker SKUs,
|
|
127
132
|
// legacy families) hide by DEFAULT. `a` reveals them; a CLASSIFIED row is never hidden.
|
|
128
|
-
const modelRows = (f = ui.filter) =>
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
const modelRows = (f = ui.filter) => {
|
|
134
|
+
const rows = scopedGroups().flatMap(groupRows).filter((row) => matches(`${row.adapter}/${row.model} ${(row.foldedModels ?? []).join(" ")}`, f)
|
|
135
|
+
&& (ui.showAll || row.tier !== undefined || retiredModelReason(row.model) === null));
|
|
136
|
+
const classified = rows.filter((row) => row.tier !== undefined);
|
|
137
|
+
const unclassified = rows.filter((row) => row.tier === undefined).sort((a, b) => Number(!!b.suggestion) - Number(!!a.suggestion)
|
|
138
|
+
|| (b.detectedAt ?? "").localeCompare(a.detectedAt ?? "")
|
|
139
|
+
|| (b.score ?? Number.NEGATIVE_INFINITY) - (a.score ?? Number.NEGATIVE_INFINITY)
|
|
140
|
+
|| `${a.adapter}/${a.model}`.localeCompare(`${b.adapter}/${b.model}`));
|
|
141
|
+
return [...classified, ...unclassified];
|
|
142
|
+
};
|
|
143
|
+
const hiddenModelCount = (f = ui.filter) => scopedGroups().flatMap(groupRows)
|
|
144
|
+
.filter((row) => matches(`${row.adapter}/${row.model} ${(row.foldedModels ?? []).join(" ")}`, f)).length
|
|
131
145
|
- modelRows(f).length;
|
|
146
|
+
const foldedModelCount = (f = ui.filter) => modelRows(f)
|
|
147
|
+
.reduce((count, row) => count + Math.max((row.foldedModels?.length ?? 1) - 1, 0), 0);
|
|
132
148
|
/** rail counts mirror the list's retired-hide (never the text filter) so numbers agree on screen */
|
|
133
149
|
const visibleCount = (scope) => {
|
|
134
150
|
const groups = scope === -1 ? enabledGroups() : (modelGroups[scope] ? [modelGroups[scope]] : []);
|
|
@@ -232,14 +248,17 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
232
248
|
return;
|
|
233
249
|
// OBS-508: catalog evidence prefills the flow — the tier cursor lands on the suggested band and
|
|
234
250
|
// (when the operator keeps that band) the provenance note arrives pre-typed. Free to override.
|
|
235
|
-
const
|
|
251
|
+
const source = group.rows.find((row) => row.model === model);
|
|
252
|
+
const suggestion = source?.suggestion ?? null;
|
|
253
|
+
const classifyModel = source?.classifyModel ?? model;
|
|
236
254
|
const tierAt = suggestion ? Math.max(TIERS.indexOf(suggestion.tier), 0) : 0;
|
|
237
255
|
const firstTouch = !group.rows.some((row) => row.tier !== undefined)
|
|
238
256
|
&& !ui.classifications.some((c) => c.adapter === adapter);
|
|
239
257
|
const base = {
|
|
240
258
|
kind: "classify",
|
|
241
259
|
adapter,
|
|
242
|
-
model,
|
|
260
|
+
model: classifyModel,
|
|
261
|
+
...(classifyModel !== model ? { displayModel: model } : {}),
|
|
243
262
|
channelAt: 0,
|
|
244
263
|
tierAt,
|
|
245
264
|
note: "",
|
|
@@ -966,7 +985,7 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
966
985
|
const group = modelGroups[ui.adapterAt];
|
|
967
986
|
const suggested = rows
|
|
968
987
|
.filter((candidate) => candidate.adapter === group.adapter && !candidate.tier && candidate.suggestion !== undefined)
|
|
969
|
-
.map((candidate) => ({ model: candidate.model, suggestion: candidate.suggestion }));
|
|
988
|
+
.map((candidate) => ({ model: candidate.classifyModel ?? candidate.model, suggestion: candidate.suggestion }));
|
|
970
989
|
if (!suggested.length) {
|
|
971
990
|
ui.notice = "no catalog tier suggestions among the visible unclassified models — evidence comes from the cached catalogs (AA index / API pricing)";
|
|
972
991
|
bump();
|
|
@@ -1101,6 +1120,9 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
1101
1120
|
const parts = [
|
|
1102
1121
|
`${row.adapter}:${row.model}`,
|
|
1103
1122
|
row.tier ?? "unclassified",
|
|
1123
|
+
row.variants?.length ? `variants ${row.variants.join(", ")}` : "",
|
|
1124
|
+
row.classifyModel ? `classify writes ${row.classifyModel}` : "",
|
|
1125
|
+
row.foldedModels?.length ? `${row.foldedModels.length} gateway ids folded: ${row.foldedModels.join(", ")}` : "",
|
|
1104
1126
|
row.evidence?.unauthed !== undefined ? `UNAUTHED — ${row.evidence.unauthed}` : "",
|
|
1105
1127
|
row.evidence?.contextWindow !== undefined ? `${fmtCtx(row.evidence.contextWindow)} ctx` : "",
|
|
1106
1128
|
row.evidence?.outputWindow !== undefined ? `${fmtCtx(row.evidence.outputWindow)} out` : "",
|
|
@@ -1120,7 +1142,8 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
1120
1142
|
const nameW = bodyW - 4 - 11 - 6 - (showPrice ? 12 : 0) - (showProbe ? 7 : 0);
|
|
1121
1143
|
// OBS-531: deep router ids (omp/prime-agent) clip tail-preserving — the LAST segment is the
|
|
1122
1144
|
// distinguishing half; end-clipping rendered ten identical "prime-agent/anthropic/claude-…" rows.
|
|
1123
|
-
const
|
|
1145
|
+
const folded = row.foldedModels?.length ?? 1;
|
|
1146
|
+
const name = clipPathTail(`${row.adapter}/${row.model}${folded > 1 ? ` ×${folded}` : ""}`, nameW);
|
|
1124
1147
|
const prefixLen = Math.min(name.length, row.adapter.length + 1);
|
|
1125
1148
|
return (_jsxs(Text, { wrap: "truncate", children: [_jsx(Pointer, { on: selected }), row.denied
|
|
1126
1149
|
? _jsx(Glyph, { kind: "off" })
|
|
@@ -1174,7 +1197,9 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
1174
1197
|
if (overlay.kind === "classify") {
|
|
1175
1198
|
const subject = overlay.bulk
|
|
1176
1199
|
? `${overlay.adapter} · ${overlay.bulk.rows.length} suggested models`
|
|
1177
|
-
:
|
|
1200
|
+
: overlay.displayModel
|
|
1201
|
+
? `${overlay.adapter}:${overlay.displayModel} · writes ${overlay.model}`
|
|
1202
|
+
: `${overlay.adapter}:${overlay.model}`;
|
|
1178
1203
|
return (_jsxs(OverlayPanel, { title: `classify · ${subject}`, width: bodyW, children: [overlay.stage === "channel" && (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: ["first touch for ", overlay.adapter, " \u2014 how is this CLI billed?"] }), _jsx(Text, { children: " " }), CHANNELS.map((channel, index) => (_jsxs(Text, { children: [_jsx(Pointer, { on: overlay.channelAt === index }), _jsx(Text, { bold: overlay.channelAt === index, children: padCell(channel, 5) }), _jsx(Text, { dimColor: true, children: channel === "sub" ? "flat-rate subscription quota" : "metered API billing" })] }, channel)))] })), overlay.stage === "tier" && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: overlay.suggestion
|
|
1179
1204
|
? `catalog suggests ${overlay.suggestion.tier} — keep it and the provenance note arrives pre-typed`
|
|
1180
1205
|
: "pick the capability band this model routes as" }), _jsx(Text, { children: " " }), TIERS.map((tier, index) => (_jsxs(Text, { children: [_jsx(Pointer, { on: overlay.tierAt === index }), overlay.suggestion?.tier === tier ? _jsx(Glyph, { kind: "on" }) : _jsx(Text, { children: " " }), _jsx(Text, { bold: overlay.tierAt === index, children: ` ${padCell(tier, 9)}` }), _jsx(Text, { dimColor: true, children: tier === "frontier" ? "strongest band — integrity shapes" : tier === "mid" ? "capable daily driver" : "fast + cheap" })] }, tier)))] })), overlay.stage === "note" && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: "benchmark provenance (required) \u2014 where does this tier claim come from?" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [_jsx(Text, { color: INK.brand, children: "> " }), _jsx(Text, { children: clip(overlay.note, bodyW - 6) || "" }), _jsx(Text, { color: INK.brand, children: "\u2588" })] })] }))] }));
|
|
@@ -1220,6 +1245,15 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
1220
1245
|
const selectedSeat = ui.judgeSeat ?? judgeKeepRow;
|
|
1221
1246
|
return (_jsxs(OverlayPanel, { title: "pick \u00B7 judge", width: bodyW, children: [_jsx(Text, { dimColor: true, children: "one seat judges acceptance criteria \u2014 failover stays runtime (GATE-09)" }), _jsx(SearchRow, { filter: ui.filter, active: true }), above > 0 && _jsx(ElisionMark, { count: above, side: "above" }), visible.map((label, index) => (_jsxs(Text, { children: [_jsx(Pointer, { on: start + index === overlay.at }), label === selectedSeat ? _jsx(Glyph, { kind: "on" }) : _jsx(Text, { children: " " }), _jsx(Text, { bold: start + index === overlay.at, children: ` ${clip(label, bodyW - 10)}` })] }, label))), below > 0 && _jsx(ElisionMark, { count: below, side: "below" })] }));
|
|
1222
1247
|
})();
|
|
1248
|
+
const modelVisibilityLine = () => {
|
|
1249
|
+
const hidden = hiddenModelCount();
|
|
1250
|
+
const folded = foldedModelCount();
|
|
1251
|
+
return [
|
|
1252
|
+
...(folded ? [`${folded} same-model gateway id${folded === 1 ? "" : "s"} folded`] : []),
|
|
1253
|
+
...(hidden ? [`${hidden} retired/preview/non-worker hidden — a shows all`] : []),
|
|
1254
|
+
...(ui.showAll ? ["showing retired models — a hides them again"] : []),
|
|
1255
|
+
].join(" · ");
|
|
1256
|
+
};
|
|
1223
1257
|
const listNode = (() => {
|
|
1224
1258
|
if (overlayNode)
|
|
1225
1259
|
return overlayNode;
|
|
@@ -1230,7 +1264,7 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
1230
1264
|
? "All models"
|
|
1231
1265
|
: modelGroups[ui.adapterAt]?.adapter ?? "";
|
|
1232
1266
|
const scopeDenied = ui.adapterAt !== -1 && ui.deny.has(modelGroups[ui.adapterAt]?.adapter ?? "");
|
|
1233
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { bold: true, children: scopeLabel }), _jsx(Text, { dimColor: true, children: ` ${rows.length}` })] }), _jsx(SearchRow, { filter: ui.filter, active: ui.searching, hint: "/ to search" }), scopeDenied && _jsx(Text, { color: INK.warn, children: `${modelGroups[ui.adapterAt]?.adapter} is out of the fleet — Space on its rail row adds it back` }), above > 0 && _jsx(ElisionMark, { count: above, side: "above" }), visible.map((row, index) => renderModelRow(row, ui.focus === "list" && start + index === ui.listAt)), below > 0 && _jsx(ElisionMark, { count: below, side: "below", hint: "/ to search" }), rows.length === 0 && !scopeDenied && _jsx(Text, { dimColor: true, children: " no models match" })] }));
|
|
1267
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { bold: true, children: scopeLabel }), _jsx(Text, { dimColor: true, children: ` ${rows.length}` })] }), _jsx(SearchRow, { filter: ui.filter, active: ui.searching, hint: "/ to search" }), modelVisibilityLine() && _jsx(Text, { dimColor: true, children: ` ${modelVisibilityLine()}` }), scopeDenied && _jsx(Text, { color: INK.warn, children: `${modelGroups[ui.adapterAt]?.adapter} is out of the fleet — Space on its rail row adds it back` }), above > 0 && _jsx(ElisionMark, { count: above, side: "above" }), visible.map((row, index) => renderModelRow(row, ui.focus === "list" && start + index === ui.listAt)), below > 0 && _jsx(ElisionMark, { count: below, side: "below", hint: "/ to search" }), rows.length === 0 && !scopeDenied && _jsx(Text, { dimColor: true, children: " no models match" })] }));
|
|
1234
1268
|
}
|
|
1235
1269
|
if (ui.view === "shapes") {
|
|
1236
1270
|
const rows = shapeList();
|
|
@@ -1266,11 +1300,6 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
1266
1300
|
: "unclassified — Space/Enter classifies; unclassified models are never routed");
|
|
1267
1301
|
}
|
|
1268
1302
|
}
|
|
1269
|
-
const hidden = hiddenModelCount();
|
|
1270
|
-
if (hidden > 0 && lines.length < 2)
|
|
1271
|
-
lines.push(`${hidden} retired/preview/non-worker hidden — a shows all`);
|
|
1272
|
-
if (ui.showAll && lines.length < 2)
|
|
1273
|
-
lines.push("showing retired models — a hides them again");
|
|
1274
1303
|
return lines;
|
|
1275
1304
|
}
|
|
1276
1305
|
if (ui.view === "shapes") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tickmarkr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Spec in, verified work out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,5 +57,63 @@
|
|
|
57
57
|
"tsx": "^4.19.0",
|
|
58
58
|
"typescript": "^5.6.0",
|
|
59
59
|
"vitest": "^3.0.0"
|
|
60
|
+
},
|
|
61
|
+
"tickmarkrExport": {
|
|
62
|
+
"publicPaths": {
|
|
63
|
+
"exact": [
|
|
64
|
+
".gitignore",
|
|
65
|
+
".oxlintrc.json",
|
|
66
|
+
"CHANGELOG.md",
|
|
67
|
+
"CODE_OF_CONDUCT.md",
|
|
68
|
+
"CONTRIBUTING.md",
|
|
69
|
+
"FLEET.md",
|
|
70
|
+
"LICENSE",
|
|
71
|
+
"README.md",
|
|
72
|
+
"RELEASING.md",
|
|
73
|
+
"SECURITY.md",
|
|
74
|
+
"package-lock.json",
|
|
75
|
+
"package.json",
|
|
76
|
+
"tickmarkr.spec.md",
|
|
77
|
+
"tsconfig.json",
|
|
78
|
+
"vitest.config.ts",
|
|
79
|
+
".github/pull_request_template.md",
|
|
80
|
+
"scripts/assert-test-file-count.sh",
|
|
81
|
+
"scripts/emit-schema.ts",
|
|
82
|
+
"scripts/probe-rig.mjs",
|
|
83
|
+
"specs/export-selftest.spec.md"
|
|
84
|
+
],
|
|
85
|
+
"prefixes": [
|
|
86
|
+
".github/ISSUE_TEMPLATE/",
|
|
87
|
+
".github/workflows/",
|
|
88
|
+
"assets/",
|
|
89
|
+
"docs/codebase/",
|
|
90
|
+
"fixtures/",
|
|
91
|
+
"schema/",
|
|
92
|
+
"skills/tickmarkr-auto/",
|
|
93
|
+
"skills/tickmarkr-loop/",
|
|
94
|
+
"skills/tickmarkr-overseer/",
|
|
95
|
+
"src/",
|
|
96
|
+
"tests/"
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
"excludedPaths": [
|
|
100
|
+
".planning",
|
|
101
|
+
"specs",
|
|
102
|
+
".tickmarkr",
|
|
103
|
+
".overseer",
|
|
104
|
+
".claude",
|
|
105
|
+
"docs",
|
|
106
|
+
"ASSESSMENT-*.md",
|
|
107
|
+
".gitignore",
|
|
108
|
+
"scripts/measure-trailer-width.mjs",
|
|
109
|
+
"scripts/scan-scope-corpus.mjs",
|
|
110
|
+
"scripts/repro-obs96.mjs",
|
|
111
|
+
"CLAUDE.md",
|
|
112
|
+
"scripts/export-public.sh",
|
|
113
|
+
"scripts/verify-export.sh",
|
|
114
|
+
"tests/scripts/verify-export.test.ts",
|
|
115
|
+
".github/workflows/ci.yml",
|
|
116
|
+
"**/*.local.*"
|
|
117
|
+
]
|
|
60
118
|
}
|
|
61
119
|
}
|