tickmarkr 2.5.8 → 2.6.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.
Files changed (63) hide show
  1. package/dist/adapters/claude-code.js +19 -6
  2. package/dist/adapters/prompt.js +1 -1
  3. package/dist/adapters/qwen.js +30 -3
  4. package/dist/adapters/types.d.ts +3 -0
  5. package/dist/cli/commands/approve.js +15 -3
  6. package/dist/cli/commands/beat.d.ts +2 -0
  7. package/dist/cli/commands/beat.js +28 -29
  8. package/dist/cli/commands/compile.js +11 -0
  9. package/dist/cli/commands/fleet.js +61 -53
  10. package/dist/cli/commands/init.js +1 -1
  11. package/dist/cli/commands/report.js +11 -1
  12. package/dist/cli/commands/verify.d.ts +4 -1
  13. package/dist/cli/commands/verify.js +18 -5
  14. package/dist/cli/help.d.ts +2 -0
  15. package/dist/cli/help.js +6 -4
  16. package/dist/compile/native.js +39 -4
  17. package/dist/config/config.d.ts +41 -3
  18. package/dist/config/config.js +48 -17
  19. package/dist/config/fleet-overlay.js +47 -62
  20. package/dist/drivers/orca.d.ts +1 -1
  21. package/dist/drivers/orca.js +21 -4
  22. package/dist/gates/baseline.d.ts +67 -0
  23. package/dist/gates/baseline.js +172 -10
  24. package/dist/gates/cache.d.ts +8 -0
  25. package/dist/gates/cache.js +26 -13
  26. package/dist/gates/review.d.ts +8 -7
  27. package/dist/gates/review.js +83 -45
  28. package/dist/gates/run-gates.d.ts +4 -1
  29. package/dist/gates/run-gates.js +32 -12
  30. package/dist/gates/test-manifest.d.ts +16 -1
  31. package/dist/gates/test-manifest.js +127 -27
  32. package/dist/gates/test-reporter.js +4 -0
  33. package/dist/graph/graph.d.ts +1 -1
  34. package/dist/graph/graph.js +6 -1
  35. package/dist/graph/schema.d.ts +2 -0
  36. package/dist/graph/schema.js +2 -0
  37. package/dist/route/preference.d.ts +1 -1
  38. package/dist/route/preference.js +10 -39
  39. package/dist/run/daemon.d.ts +7 -1
  40. package/dist/run/daemon.js +237 -53
  41. package/dist/run/git.d.ts +10 -0
  42. package/dist/run/git.js +49 -1
  43. package/dist/run/journal.d.ts +18 -3
  44. package/dist/run/journal.js +141 -17
  45. package/dist/run/merge.d.ts +13 -2
  46. package/dist/run/merge.js +98 -12
  47. package/dist/run/protocol.d.ts +82 -0
  48. package/dist/run/protocol.js +35 -0
  49. package/dist/run/receipt-resolver.d.ts +18 -0
  50. package/dist/run/receipt-resolver.js +132 -0
  51. package/dist/run/supervision.d.ts +14 -1
  52. package/dist/run/supervision.js +122 -24
  53. package/dist/tui/cockpit/evidence-view.d.ts +10 -1
  54. package/dist/tui/cockpit/evidence-view.js +37 -5
  55. package/dist/tui/cockpit/live-runtime.d.ts +4 -0
  56. package/dist/tui/cockpit/live-runtime.js +37 -3
  57. package/dist/tui/cockpit/live-store.d.ts +2 -0
  58. package/dist/tui/ink/fleet-app.d.ts +12 -22
  59. package/dist/tui/ink/fleet-app.js +520 -131
  60. package/package.json +1 -1
  61. package/schema/rungraph.schema.json +7 -0
  62. package/skills/tickmarkr-overseer/SKILL.md +91 -41
  63. package/skills/tickmarkr-overseer/scripts/watch-context.sh +14 -2
@@ -132,10 +132,42 @@ export async function runConsolidatedCockpit(options) {
132
132
  let committedTargets = [];
133
133
  let revision = 0;
134
134
  const listeners = new Set();
135
- const publish = () => { revision++; for (const listener of listeners)
135
+ // Every publish resyncs the key so a view switch never earns a second frame on the next tick.
136
+ const publish = () => { revision++; observed = observationKey(source.snapshot()); for (const listener of listeners)
136
137
  listener(); };
137
- const unsubscribe = source.subscribe(publish);
138
+ let observed = "";
138
139
  const geometry = () => planShell(output.columns ?? 80, output.rows ?? 24, state.shortcutColumns);
140
+ // OBS-1132: the store publishes on every observation tick; the board only re-derives and
141
+ // re-renders when what it would draw changed. Lock and supervision observation continue
142
+ // regardless. Excluded on purpose: sequence, observedAt, metrics and beat ages, which move
143
+ // every tick without changing a visible cell.
144
+ // ponytail: mirrors board.ts `ago` buckets and its ≥118-cell "wide" header — the only clock reader,
145
+ // and only the Run view draws the board, so Home and Evidence never invalidate on the age.
146
+ // The lock is compared by what it says (owner, state, liveness), never by its file stamp: the
147
+ // daemon heartbeat re-touches graph.lock every 10 s without changing a visible cell. Its clock-derived
148
+ // `expired` flag is not drawn by any view either, so a lock ageing past STALE_MS earns no frame.
149
+ const visibleAge = (ms) => ms < 6e4 ? "just now" : ms < 3.6e6 ? `${Math.round(ms / 6e4)}m` : `${Math.round(ms / 3.6e6)}h`;
150
+ const observationKey = (snap) => {
151
+ const last = snap.operator.lastEventAt;
152
+ const clock = state.view === "run" && geometry().bodyColumns >= 118 && last ? visibleAge((options.now ?? Date.now)() - Date.parse(last)) : "";
153
+ return JSON.stringify([
154
+ snap.freshness, snap.actionsEnabled, snap.errors, snap.viewport, snap.inputSequence, clock,
155
+ snap.journal.generation, snap.journal.offset, snap.journal.status, snap.journal.malformedCount, snap.journal.backlogBytes, snap.journal.pending, snap.journal.error,
156
+ snap.graph.identity, snap.graph.status, snap.config.identity, snap.config.status, snap.cache.identity, snap.cache.status,
157
+ snap.lock.value, snap.lock.status, snap.lock.state, snap.lock.alive,
158
+ // D-383: supervision tier state is not drawn by any view; an ARMED→STALE transition earns no
159
+ // frame. Its UNREADABLE case already surfaces through snap.errors above.
160
+ ]);
161
+ };
162
+ observed = observationKey(source.snapshot());
163
+ const unsubscribe = source.subscribe(() => {
164
+ const next = observationKey(source.snapshot());
165
+ if (next !== observed) {
166
+ observed = next;
167
+ publish();
168
+ }
169
+ });
170
+ let frames = 0, derivations = 0;
139
171
  const openEvidence = (identity) => {
140
172
  evidenceNavigation++;
141
173
  selectedEvidence = identity;
@@ -484,7 +516,7 @@ export async function runConsolidatedCockpit(options) {
484
516
  stop(e);
485
517
  return false;
486
518
  }
487
- }, diagnostics: source.diagnostics, stage: edits => { state = { ...state, staged: [...edits] }; publish(); } };
519
+ }, diagnostics: source.diagnostics, stage: edits => { state = { ...state, staged: [...edits] }; publish(); }, frames: () => frames, derivations: () => derivations };
488
520
  options.onDelivery?.(delivery);
489
521
  options.onShellDelivery?.(delivery);
490
522
  resize = () => {
@@ -530,6 +562,7 @@ export async function runConsolidatedCockpit(options) {
530
562
  function App() {
531
563
  useSyncExternalStore(listener => { listeners.add(listener); return () => { listeners.delete(listener); }; }, () => revision);
532
564
  const stdinContext = useStdin();
565
+ useLayoutEffect(() => { frames++; });
533
566
  useLayoutEffect(() => {
534
567
  const emitter = stdinContext.internal_eventEmitter;
535
568
  leafInput = emitter;
@@ -565,6 +598,7 @@ export async function runConsolidatedCockpit(options) {
565
598
  stop(error);
566
599
  }
567
600
  });
601
+ derivations++;
568
602
  const snap = source.snapshot();
569
603
  const p = geometry();
570
604
  const nextDecisionsKey = `${snap.journal.generation}:${snap.journal.offset}:${snap.graph.identity}`;
@@ -147,6 +147,7 @@ export declare function createLiveStore(options: LiveStoreOptions): {
147
147
  kind: "fixture";
148
148
  paths: string[];
149
149
  })[] | undefined;
150
+ outOfScope?: string[] | undefined;
150
151
  routingHints?: {
151
152
  pin?: {
152
153
  via: string;
@@ -248,6 +249,7 @@ export declare function createLiveStore(options: LiveStoreOptions): {
248
249
  kind: "fixture";
249
250
  paths: string[];
250
251
  })[] | undefined;
252
+ outOfScope?: string[] | undefined;
251
253
  routingHints?: {
252
254
  pin?: {
253
255
  via: string;
@@ -1,14 +1,10 @@
1
1
  import { type AuthHealth, type WorkerAdapter } from "../../adapters/types.js";
2
- import type { MapEntry, RoutingMode, Tier, TickmarkrConfig } from "../../config/config.js";
2
+ import { type DenyScopeKey, type InitialDenyProps, type MapEntry, type RoutingMode, type StagedDenyKey, type Tier, type TickmarkrConfig } from "../../config/config.js";
3
3
  import { type Shape } from "../../graph/schema.js";
4
4
  export type FleetSteeringKey = "review" | "consult";
5
- export type FleetEditorState = {
6
- denyAdapters: string[];
7
- denyModels: string[];
5
+ export type FleetEditorState = Record<DenyScopeKey, string[]> & {
8
6
  /** OBS-1046: the staged routing.allow complement, distinct from the authored deny lists above */
9
7
  allowOut?: string[];
10
- denyWorkersAdapters: string[];
11
- denyWorkersModels: string[];
12
8
  classifications: FleetClassification[];
13
9
  selectedMode: RoutingMode;
14
10
  map: Record<string, MapEntry>;
@@ -63,15 +59,15 @@ export type FleetModelEvidence = {
63
59
  /** OBS-972/FL-1: a floating alias's resolved concrete model id (e.g. "opus" → "claude-opus-5") */
64
60
  identity?: string;
65
61
  };
66
- /** The four staged deny sets every preview and the staged routing policy are computed from. */
67
- export type FleetStagedDeny = {
68
- adapters: string[];
69
- models: string[];
70
- workersAdapters: string[];
71
- workersModels: string[];
62
+ /** OBS-1099 add.1: the staged deny list of every schema-enumerated scope — keyed by the scope
63
+ * key minus its `deny` prefix (denyWorkersAdapters → workersAdapters) — every preview and the
64
+ * staged routing policy are computed from; a scope the schema gains is a key here, not a hand field. */
65
+ export type FleetStagedDeny = Record<StagedDenyKey, string[]> & {
72
66
  /** OBS-1046: the staged routing.allow complement; absent ⇒ the session's initial one */
73
67
  allowOut?: string[];
74
68
  };
69
+ /** every scope's staged list, empty — the "every policy scope open" probe the picker lifts against */
70
+ export declare const openStagedDeny: () => FleetStagedDeny;
75
71
  export type FleetModelGroup = {
76
72
  adapter: string;
77
73
  vendor?: string;
@@ -112,6 +108,8 @@ export type FleetCandidateOption = {
112
108
  via: string;
113
109
  model: string;
114
110
  };
111
+ /** ranked only after the shape's advisory floor was dropped (candidates.ts) — never lift-eligible */
112
+ belowFloor?: boolean;
115
113
  };
116
114
  export declare function formatDoctorAge(ageMs: number | null): string;
117
115
  export type FleetReach = "in" | "out-workers" | "out-all" | "out-allow" | "unknown";
@@ -123,15 +121,11 @@ export type FleetStagedRouting = {
123
121
  ok: false;
124
122
  error: string;
125
123
  };
126
- export declare function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels, initialAllowOut, initialDenyWorkersAdapters, initialDenyWorkersModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, stagedRouting, entry, initialJudge, judgeSeats, viewRows, frameColumns, frameRows, }: {
124
+ export declare function FleetApp({ ageMs, agents, initialAllowOut, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, stagedRouting, entry, initialJudge, judgeSeats, viewRows, frameColumns, frameRows, ...initialDenyProps }: InitialDenyProps & {
127
125
  ageMs: number | null;
128
126
  agents: AgentCli[];
129
- initialDenyAdapters: string[];
130
- initialDenyModels: string[];
131
127
  /** OBS-1046: adapter ids and adapter:model keys routing.allow leaves out of the fleet */
132
128
  initialAllowOut?: string[];
133
- initialDenyWorkersAdapters?: string[];
134
- initialDenyWorkersModels?: string[];
135
129
  modelGroups: FleetModelGroup[];
136
130
  initialMode: RoutingMode;
137
131
  modeOptions: FleetModeOption[];
@@ -163,16 +157,12 @@ export declare function FleetApp({ ageMs, agents, initialDenyAdapters, initialDe
163
157
  /** terminal height — set only on a real TTY so the footer sticks to the bottom */
164
158
  frameRows?: number;
165
159
  }): import("react").JSX.Element;
166
- export declare function runFleetInkEditor({ ageMs, adapters, health, initialDenyAdapters, initialDenyModels, initialAllowOut, initialDenyWorkersAdapters, initialDenyWorkersModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, stagedRouting, entry, initialJudge, judgeSeats, initialInput, input, output, debug, }: {
160
+ export declare function runFleetInkEditor({ ageMs, adapters, health, initialAllowOut, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, stagedRouting, entry, initialJudge, judgeSeats, initialInput, input, output, debug, ...initialDenyProps }: InitialDenyProps & {
167
161
  ageMs: number | null;
168
162
  adapters: WorkerAdapter[];
169
163
  health: Record<string, AuthHealth>;
170
- initialDenyAdapters: string[];
171
- initialDenyModels: string[];
172
164
  /** OBS-1046: adapter ids and adapter:model keys routing.allow leaves out of the fleet */
173
165
  initialAllowOut?: string[];
174
- initialDenyWorkersAdapters?: string[];
175
- initialDenyWorkersModels?: string[];
176
166
  modelGroups: FleetModelGroup[];
177
167
  initialMode: RoutingMode;
178
168
  modeOptions: FleetModeOption[];