tickmarkr 1.41.0 → 1.42.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/README.md CHANGED
@@ -1,4 +1,9 @@
1
- <p align="center"><img src="assets/wordmark-dark.png" alt="tickmarkr" width="640"></p>
1
+ ```
2
+ ▄▄████
3
+ ▄▄████▀▀
4
+ ████▄▄▄▄████▀▀ tickmarkr
5
+ ▀▀████▀▀ spec in, verified work out.
6
+ ```
2
7
 
3
8
  # tickmarkr
4
9
 
package/dist/brand.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  export declare const BANNER: string;
2
+ /** ANSI-stripped, trailing-space-trimmed twin of BANNER — README hero and other plain surfaces. */
3
+ export declare const PLAIN_BANNER: string;
2
4
  export declare function bannerShell(): string;
package/dist/brand.js CHANGED
@@ -9,6 +9,8 @@ export const BANNER = [
9
9
  ` ${g(35, "▀▀████▀▀")} spec in, verified work out.`,
10
10
  "",
11
11
  ].join("\n");
12
+ /** ANSI-stripped, trailing-space-trimmed twin of BANNER — README hero and other plain surfaces. */
13
+ export const PLAIN_BANNER = BANNER.replace(/\x1b\[[0-9;]*m/g, "").replace(/[ \t]+$/gm, "");
12
14
  // Shell one-liner that prints the banner inside a pane before a gate command runs. ESC bytes are
13
15
  // carried as printf %b escapes (never raw control bytes in a command string crossing the herdr socket).
14
16
  export function bannerShell() {
@@ -1,2 +1,5 @@
1
1
  import type { WorkerAdapter } from "../../adapters/types.js";
2
- export declare function doctor(_argv: string[], cwd?: string, adapters?: WorkerAdapter[]): Promise<string>;
2
+ export type DoctorOpts = {
3
+ banner?: boolean;
4
+ };
5
+ export declare function doctor(_argv: string[], cwd?: string, adapters?: WorkerAdapter[], opts?: DoctorOpts): Promise<string>;
@@ -1,6 +1,7 @@
1
1
  import { writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { allAdapters, probeAll, probeModels, readAutoPrefer, servableExclusions, servabilityLine, writeDoctor } from "../../adapters/registry.js";
4
+ import { BANNER } from "../../brand.js";
4
5
  import { tickmarkrDir, stateDirName } from "../../graph/graph.js";
5
6
  import { modelLints, suggestOverlay, ttyVisual } from "../../adapters/model-lints.js";
6
7
  import { DEFAULT_CONFIG, loadConfig, overlayPreferShapes } from "../../config/config.js";
@@ -30,7 +31,7 @@ function stylize(out) {
30
31
  .replace(/\bunauthed:/, color("unauthed:", 33));
31
32
  }).join("\n");
32
33
  }
33
- export async function doctor(_argv, cwd = process.cwd(), adapters = allAdapters()) {
34
+ export async function doctor(_argv, cwd = process.cwd(), adapters = allAdapters(), opts = {}) {
34
35
  const cfg = loadConfig(cwd);
35
36
  // stderr, live: auth probes are real LLM calls (up to 30s per configured model) and the CLI
36
37
  // otherwise prints nothing until the end — silence here reads as a hang (v1.33.1)
@@ -158,5 +159,6 @@ export async function doctor(_argv, cwd = process.cwd(), adapters = allAdapters(
158
159
  const modelSummary = modelStatus.length || preferStatus.length
159
160
  ? `\nmodel status:\n${[...modelStatus, ...preferStatus].join("\n")}`
160
161
  : "";
161
- return stylize(`tickmarkr doctor — capability matrix:\n${rows.join("\n")}${modelSummary}${drift}\nwrote ${stateDirName(cwd)}/doctor.json`);
162
+ const body = stylize(`tickmarkr doctor — capability matrix:\n${rows.join("\n")}${modelSummary}${drift}\nwrote ${stateDirName(cwd)}/doctor.json`);
163
+ return opts.banner !== false && visual() ? BANNER + body : body;
162
164
  }
@@ -5,8 +5,10 @@ import { parseArgs } from "node:util";
5
5
  import { allAdapters, formatDoctorAgeForInit, formatDoctorReport, initDoctorReuse } from "../../adapters/registry.js";
6
6
  import { configTemplate, DEFAULT_CONFIG, globalConfigDir, loadConfig } from "../../config/config.js";
7
7
  import { LEGACY_PREFIX, specTemplate } from "../../compile/native.js";
8
+ import { BANNER } from "../../brand.js";
8
9
  import { tickmarkrDir } from "../../graph/graph.js";
9
10
  import { doctor } from "./doctor.js";
11
+ const visual = () => process.stdout.isTTY === true && process.env.NO_COLOR === undefined;
10
12
  const AGENT_SKILLS = ["tickmarkr-loop", "tickmarkr-auto"];
11
13
  const DOCS_BEGIN = "<!-- tickmarkr:agent-docs begin -->";
12
14
  const DOCS_END = "<!-- tickmarkr:agent-docs end -->";
@@ -138,6 +140,13 @@ async function runInitWizard(cwd) {
138
140
  }
139
141
  }
140
142
  export async function init(argv, cwd = process.cwd()) {
143
+ let bannerEmitted = false;
144
+ const emitBanner = () => {
145
+ if (visual() && !bannerEmitted) {
146
+ bannerEmitted = true;
147
+ process.stdout.write(BANNER);
148
+ }
149
+ };
141
150
  const { values } = parseArgs({
142
151
  args: argv,
143
152
  options: {
@@ -183,10 +192,11 @@ export async function init(argv, cwd = process.cwd()) {
183
192
  const { reuse, ageMs, health } = initDoctorReuse(cwd, fresh);
184
193
  const doc = reuse && health && ageMs !== null
185
194
  ? `using probe results from ${formatDoctorAgeForInit(ageMs)} ago — run tickmarkr doctor to refresh (or init --fresh)\n${formatDoctorReport(cwd, loadConfig(cwd), health, allAdapters(), { wrote: false })}`
186
- : await doctor([], cwd);
195
+ : await doctor([], cwd, undefined, { banner: false });
187
196
  const interactive = process.stdin.isTTY === true && process.stdout.isTTY === true && !(values.yes ?? false);
188
197
  if (!repoConfigExists) {
189
198
  if (interactive) {
199
+ emitBanner();
190
200
  const wizard = await runInitWizard(cwd);
191
201
  writeFileSync(repoConfigPath, configTemplate(wizard.overlay));
192
202
  notes.push(`wrote ${repoConfigPath}`);
@@ -200,5 +210,8 @@ export async function init(argv, cwd = process.cwd()) {
200
210
  }
201
211
  if (values.agent)
202
212
  await installAgentFiles(cwd, values.force ?? false, values.docs ?? false, notes);
203
- return `${notes.join("\n")}\n${doc}\nnext: edit tickmarkr.spec.md, then tickmarkr compile tickmarkr.spec.md && tickmarkr plan && tickmarkr run`;
213
+ const body = `${notes.join("\n")}\n${doc}\nnext: edit tickmarkr.spec.md, then tickmarkr compile tickmarkr.spec.md && tickmarkr plan && tickmarkr run`;
214
+ if (visual() && !bannerEmitted)
215
+ return BANNER + body;
216
+ return body;
204
217
  }
@@ -202,11 +202,15 @@ export class HerdrDriver {
202
202
  const token = newest ? canonicalizeLegacyName(newest.name, "").taskId : undefined;
203
203
  const glyph = newest ? await this.glyphFor(newest) : "";
204
204
  const label = token ? `${entry.label} · ${token}${glyph}` : entry.label;
205
+ const cmd = `tab rename ${shq(entry.tabId)} ${shq(label)}`;
206
+ const ok = async () => (await this.herdr(cmd)).code === 0;
207
+ if (await ok() || await ok())
208
+ return;
205
209
  try {
206
- await this.herdr(`tab rename ${shq(entry.tabId)} ${shq(label)}`);
210
+ await this.notify(`tickmarkr tab relabel failed: ${entry.tabId} ${label}`);
207
211
  }
208
212
  catch {
209
- /* cosmetic only — a relabel failure never blocks membership or teardown (v1.18 invariant) */
213
+ /* OBS-45: cosmetic only — a relabel failure never blocks membership or teardown (v1.18 invariant) */
210
214
  }
211
215
  }
212
216
  // VIS-13: at most one glyph on the hot token. ✋ wins — the driver observes the member blocked live
package/package.json CHANGED
@@ -1,9 +1,21 @@
1
1
  {
2
2
  "name": "tickmarkr",
3
- "version": "1.41.0",
3
+ "version": "1.42.0",
4
4
  "description": "Spec in, verified work out.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
+ "keywords": [
8
+ "ai",
9
+ "agents",
10
+ "orchestration",
11
+ "automation",
12
+ "cli"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/alzahrani-khalid/tickmarkr.git"
17
+ },
18
+ "homepage": "https://github.com/alzahrani-khalid/tickmarkr",
7
19
  "engines": {
8
20
  "node": ">=20"
9
21
  },