zyrk 0.8.5 → 0.8.6

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
@@ -534,3 +534,12 @@ and runs real pinned React, Vite, Vitest, and Tailwind builds and HTTP asset
534
534
  checks. It uses native zyrk installation with default deny policy. Recorded
535
535
  results describe the exact tested versions and platform, without a universal
536
536
  framework or cold-install performance claim.
537
+
538
+ ### Inspection output
539
+
540
+ Interactive `doctor`, store status/verification, and collection commands use
541
+ command-specific summaries. A failed doctor result is marked as a failure;
542
+ an unavailable audit result is attention, never a clean audit. Store collection
543
+ previews distinguish eligible, retained, removed, and grace-period entries and
544
+ keep physical reclamation explicitly unavailable when it cannot be measured.
545
+ Redirected output and `--json` preserve their existing data contracts.
package/VERSION CHANGED
@@ -1 +1 @@
1
- v0.8.5
1
+ v0.8.6
@@ -2,6 +2,15 @@ export type TerminalStyle = {
2
2
  isTTY?: boolean;
3
3
  color?: boolean;
4
4
  };
5
+ export type HumanSummary = {
6
+ tone: "success" | "attention" | "failure" | "status";
7
+ heading: string;
8
+ facts: string[];
9
+ next?: string;
10
+ };
11
+ export declare function renderSummary(summary: HumanSummary, style: TerminalStyle): string;
12
+ /** Command facts stay separate from their terminal presentation and JSON data. */
13
+ export declare function commandSummary(command: string, value: Record<string, unknown>): HumanSummary | undefined;
5
14
  /** Render command summaries for people while preserving redirected output. */
6
15
  export declare function renderCommandOutput(command: string, output: string, style?: TerminalStyle): string;
7
16
  /** Make stable CLI diagnostics easier to scan without changing their content. */
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/cli/terminal.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAQjE,8EAA8E;AAC9E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,aAAkB,GACxB,MAAM,CA0BR;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,aAAkB,GACxB,MAAM,CAUR"}
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/cli/terminal.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,aAAa,GACnB,MAAM,CAQR;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,YAAY,GAAG,SAAS,CAgG1B;AAQD,8EAA8E;AAC9E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,aAAkB,GACxB,MAAM,CA4BR;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,aAAkB,GACxB,MAAM,CAUR"}
@@ -1,3 +1,94 @@
1
+ export function renderSummary(summary, style) {
2
+ const marker = { success: "✓", attention: "!", failure: "✖", status: "›" }[summary.tone];
3
+ const color = { success: 32, attention: 33, failure: 31, status: 2 }[summary.tone];
4
+ return `${paint(marker, color, style)} ${summary.heading}\n${summary.facts.map((fact) => ` ${fact}\n`).join("")}${summary.next ? ` Next: ${summary.next}\n` : ""}`;
5
+ }
6
+ /** Command facts stay separate from their terminal presentation and JSON data. */
7
+ export function commandSummary(command, value) {
8
+ if (command === "doctor" &&
9
+ typeof value.ok === "boolean" &&
10
+ Array.isArray(value.diagnostics)) {
11
+ const diagnostics = value.diagnostics;
12
+ return {
13
+ tone: !value.ok
14
+ ? "failure"
15
+ : diagnostics.length
16
+ ? "attention"
17
+ : "success",
18
+ heading: !value.ok
19
+ ? "Project needs attention"
20
+ : diagnostics.length
21
+ ? "Project checks passed with warnings"
22
+ : "Project checks passed",
23
+ facts: diagnostics.length
24
+ ? diagnostics.map((d) => `${d.severity}: ${d.code}: ${d.message}`)
25
+ : ["Lock, links, build readiness, and store safety checked."],
26
+ ...(!value.ok
27
+ ? {
28
+ next: "Review these diagnostics before choosing install or repair.",
29
+ }
30
+ : {}),
31
+ };
32
+ }
33
+ if (command.startsWith("store") && typeof value.initialized === "boolean") {
34
+ return {
35
+ tone: "status",
36
+ heading: value.initialized
37
+ ? "Shared store status"
38
+ : "Shared store is not initialized",
39
+ facts: value.initialized
40
+ ? [
41
+ `Retention roots: ${value.retentionRoots ?? "unavailable"}`,
42
+ `Logical bytes: ${value.logicalBytes ?? "unavailable"}`,
43
+ `Allocated bytes estimate: ${value.allocatedBytesEstimate ?? "unavailable"}`,
44
+ String(value.allocationMethod ??
45
+ "Physical allocation measurement unavailable."),
46
+ "Private builds, fetch caches, and exclusive reclaimable bytes are not measured here.",
47
+ ]
48
+ : ["No store content has been inspected."],
49
+ };
50
+ }
51
+ if (command.startsWith("store") && value.verified === true)
52
+ return {
53
+ tone: "success",
54
+ heading: "Shared store verification passed",
55
+ facts: [
56
+ `Sources: ${value.sources}; objects: ${value.objects}; realizations: ${value.realizations}`,
57
+ ],
58
+ };
59
+ if (command.startsWith("store") &&
60
+ typeof value.dryRun === "boolean" &&
61
+ Array.isArray(value.candidates))
62
+ return {
63
+ tone: "status",
64
+ heading: value.dryRun
65
+ ? "Store collection preview"
66
+ : "Store collection complete",
67
+ facts: [
68
+ `Eligible entries: ${value.candidates.length}; removed: ${value.removed}; retained: ${value.retained}`,
69
+ `Within grace period: ${value.graceRetained}`,
70
+ `Selected logical bytes: ${value.logicalBytesSelected}; physical bytes reclaimed: ${value.physicalBytesReclaimed}`,
71
+ ...(Array.isArray(value.retentionReasons)
72
+ ? value.retentionReasons.map(String)
73
+ : []),
74
+ ],
75
+ ...(value.dryRun
76
+ ? { next: "Review eligibility; run zyrk store gc to apply collection." }
77
+ : {}),
78
+ };
79
+ if (value.status === "unavailable")
80
+ return {
81
+ tone: "attention",
82
+ heading: `${command} is unavailable`,
83
+ facts: [
84
+ "No clean result can be established.",
85
+ ...Object.entries(value)
86
+ .filter(([key]) => !["schemaVersion", "status", "command"].includes(key))
87
+ .map(([key, item]) => `${key}: ${JSON.stringify(item)}`),
88
+ ],
89
+ };
90
+ return undefined;
91
+ }
1
92
  function paint(value, code, style) {
2
93
  return style.isTTY && style.color !== false
3
94
  ? `\u001b[${code}m${value}\u001b[0m`
@@ -15,6 +106,9 @@ export function renderCommandOutput(command, output, style = {}) {
15
106
  value = undefined;
16
107
  }
17
108
  if (value && typeof value === "object" && !Array.isArray(value)) {
109
+ const semantic = commandSummary(command, value);
110
+ if (semantic)
111
+ return renderSummary(semantic, style);
18
112
  const summary = { ...value };
19
113
  delete summary.schemaVersion;
20
114
  delete summary.status;
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/commands/project.ts"],"names":[],"mappings":"AA6DA,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAqMF,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAgRjB"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/commands/project.ts"],"names":[],"mappings":"AA6DA,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AA2MF,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAgRjB"}
@@ -138,7 +138,9 @@ function emit(options, result, human) {
138
138
  command: options.command,
139
139
  ...result,
140
140
  }) + "\n"
141
- : renderCommandOutput(options.command, `${human}\n`, {
141
+ : renderCommandOutput(options.command, options.command === "doctor" && options.stdout.isTTY
142
+ ? JSON.stringify(result)
143
+ : `${human}\n`, {
142
144
  ...(options.stdout.isTTY === undefined
143
145
  ? {}
144
146
  : { isTTY: options.stdout.isTTY }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zyrk",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "Storage-efficient Node package manager: one verified store per user, shared across projects through links.",
5
5
  "license": "MIT",
6
6
  "type": "module",