tickmarkr 1.90.3 → 1.90.4

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.
@@ -40,4 +40,19 @@ export declare function packageManagerFinding(cwd: string, probe?: (pm: string)
40
40
  verdict: "pass" | "fail";
41
41
  detail: string;
42
42
  } | undefined;
43
+ /**
44
+ * Q142s: tickmarkr guarded every binary except its own. Exhibit (operator machine,
45
+ * 2026-08-12): an orphaned npm-prefix root at ~/.local held tickmarkr AND tkr at
46
+ * 1.85.0 beside the live 1.90.3 — two seats disagreed about the tool's version and
47
+ * were BOTH right about their own PATH order (a consultant reported "no verify
48
+ * command" — verify shipped in 1.90.0 — while the overseer saw it present). Checks
49
+ * EVERY bin name the package declares: the first sweep of that machine missed `tkr`.
50
+ */
51
+ export declare function selfShadowFinding(ownVersion: string, cwd?: string, resolve?: (bin: string, cwd: string) => {
52
+ resolved?: string;
53
+ all: string[];
54
+ }, versionOf?: (path: string) => string | undefined): {
55
+ verdict: "pass" | "fail";
56
+ detail: string;
57
+ } | undefined;
43
58
  export declare function doctor(_argv: string[], cwd?: string, adapters?: WorkerAdapter[], opts?: DoctorOpts): Promise<string>;
@@ -3,7 +3,8 @@ import { spawnSync } from "node:child_process";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { detectPackageManager } from "../../gates/baseline.js";
6
- import { allAdapters, binaryShadowWarnings, detectCandidateClis, flagDriftWarnings, modelAliasExclusions, modelAliasLine, probeAll, probeModels, servableExclusions, servabilityLine, writeDoctor } from "../../adapters/registry.js";
6
+ import { version } from "./version.js";
7
+ import { allAdapters, binaryShadowWarnings, detectCandidateClis, flagDriftWarnings, modelAliasExclusions, modelAliasLine, probeAll, probeModels, resolveShellBinary, servableExclusions, servabilityLine, writeDoctor } from "../../adapters/registry.js";
7
8
  import { CLAUDE_ALIAS_IDENTITY_STAMPS, claudeCode, resolveClaudeAliasIdentity } from "../../adapters/claude-code.js";
8
9
  import { BANNER, dim, fail, kvRow, legend, ok, rule, statusRow, title } from "../../brand.js";
9
10
  import { tickmarkrDir, stateDirName } from "../../graph/graph.js";
@@ -170,6 +171,40 @@ export function packageManagerFinding(cwd, probe = (pm) => spawnSync(pm, ["--ver
170
171
  detail: `repo uses ${pm} but the binary does not resolve in this environment — every auto-detected gate command will die before running any suite (fix: corepack enable, or install ${pm} on the daemon's PATH)`,
171
172
  };
172
173
  }
174
+ /**
175
+ * Q142s: tickmarkr guarded every binary except its own. Exhibit (operator machine,
176
+ * 2026-08-12): an orphaned npm-prefix root at ~/.local held tickmarkr AND tkr at
177
+ * 1.85.0 beside the live 1.90.3 — two seats disagreed about the tool's version and
178
+ * were BOTH right about their own PATH order (a consultant reported "no verify
179
+ * command" — verify shipped in 1.90.0 — while the overseer saw it present). Checks
180
+ * EVERY bin name the package declares: the first sweep of that machine missed `tkr`.
181
+ */
182
+ export function selfShadowFinding(ownVersion, cwd = process.cwd(), resolve = resolveShellBinary, versionOf = (p) => {
183
+ const r = spawnSync(p, ["version"], { encoding: "utf8", timeout: 5_000, shell: false });
184
+ return r.status === 0 ? r.stdout.trim().split("\n")[0] : undefined;
185
+ }) {
186
+ const hits = new Map(); // path -> version
187
+ for (const bin of ["tickmarkr", "tkr"]) {
188
+ for (const p of resolve(bin, cwd).all) {
189
+ if (!hits.has(p))
190
+ hits.set(p, versionOf(p) ?? "?");
191
+ }
192
+ }
193
+ if (hits.size === 0)
194
+ return undefined; // no install on PATH (repo checkout) — nothing to shadow
195
+ const stale = [...hits].filter(([, v]) => v !== ownVersion);
196
+ if (stale.length === 0) {
197
+ return { verdict: "pass", detail: `single install root at ${ownVersion} (${[...hits.keys()].join(", ")})` };
198
+ }
199
+ const listing = stale.map(([p, v]) => `${p} → ${v}`).join(", ");
200
+ // One mismatched hit and it's the one running? Impossible — it would report ownVersion.
201
+ // Mismatch therefore means a SECOND root: a shell or daemon with a different PATH
202
+ // order runs a different tickmarkr than this one, silently.
203
+ return {
204
+ verdict: "fail",
205
+ detail: `stale tickmarkr/tkr binaries on PATH: ${listing} (running ${ownVersion}) — a seat with different PATH order silently runs the old binary; remove the stale install root`,
206
+ };
207
+ }
173
208
  export async function doctor(_argv, cwd = process.cwd(), adapters = allAdapters(), opts = {}) {
174
209
  if (_argv.length === 1 && _argv[0] === "--refresh-catalog") {
175
210
  const refreshed = await refreshCatalogCommand({ repoRoot: cwd, now: opts.catalogNow });
@@ -265,6 +300,10 @@ export async function doctor(_argv, cwd = process.cwd(), adapters = allAdapters(
265
300
  const pmRow = packageManagerFinding(cwd);
266
301
  if (pmRow)
267
302
  rows.push(alignedStatusRow(pmRow.verdict, "package-manager", pmRow.detail));
303
+ // Q142s: tickmarkr's own binary gets the shadow check every adapter binary already had.
304
+ const shadowRow = selfShadowFinding(await version(), cwd);
305
+ if (shadowRow)
306
+ rows.push(alignedStatusRow(shadowRow.verdict, "tickmarkr-binary", shadowRow.detail));
268
307
  // v1.22 T5: workspace-trust pre-flight — per installed adapter: trusted | seeded | action-required | n/a.
269
308
  // action-required names the exact one-time command (or dialog) the operator must run once.
270
309
  rows.push(legend("workspace trust:"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tickmarkr",
3
- "version": "1.90.3",
3
+ "version": "1.90.4",
4
4
  "description": "Spec in, verified work out.",
5
5
  "type": "module",
6
6
  "license": "MIT",