panoma 0.1.0 → 0.1.2

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 (119) hide show
  1. package/README.md +1 -1
  2. package/app/BUILD-INFO.json +2 -2
  3. package/app/apps/web/.next-bundle/BUILD_ID +1 -1
  4. package/app/apps/web/.next-bundle/app-build-manifest.json +128 -128
  5. package/app/apps/web/.next-bundle/app-path-routes-manifest.json +31 -31
  6. package/app/apps/web/.next-bundle/build-manifest.json +2 -2
  7. package/app/apps/web/.next-bundle/prerender-manifest.json +9 -9
  8. package/app/apps/web/.next-bundle/server/app/(app)/agents/page.js +1 -1
  9. package/app/apps/web/.next-bundle/server/app/(app)/agents/page_client-reference-manifest.js +1 -1
  10. package/app/apps/web/.next-bundle/server/app/(app)/ai/page_client-reference-manifest.js +1 -1
  11. package/app/apps/web/.next-bundle/server/app/(app)/bridge/page_client-reference-manifest.js +1 -1
  12. package/app/apps/web/.next-bundle/server/app/(app)/copies/page.js +1 -1
  13. package/app/apps/web/.next-bundle/server/app/(app)/copies/page_client-reference-manifest.js +1 -1
  14. package/app/apps/web/.next-bundle/server/app/(app)/credentials/page_client-reference-manifest.js +1 -1
  15. package/app/apps/web/.next-bundle/server/app/(app)/disk/page_client-reference-manifest.js +1 -1
  16. package/app/apps/web/.next-bundle/server/app/(app)/hidden/page_client-reference-manifest.js +1 -1
  17. package/app/apps/web/.next-bundle/server/app/(app)/p/[slug]/page.js +2 -2
  18. package/app/apps/web/.next-bundle/server/app/(app)/p/[slug]/page_client-reference-manifest.js +1 -1
  19. package/app/apps/web/.next-bundle/server/app/(app)/packages/page.js +2 -2
  20. package/app/apps/web/.next-bundle/server/app/(app)/packages/page_client-reference-manifest.js +1 -1
  21. package/app/apps/web/.next-bundle/server/app/(app)/page_client-reference-manifest.js +1 -1
  22. package/app/apps/web/.next-bundle/server/app/(app)/runs/[id]/page.js +2 -2
  23. package/app/apps/web/.next-bundle/server/app/(app)/runs/[id]/page_client-reference-manifest.js +1 -1
  24. package/app/apps/web/.next-bundle/server/app/(app)/runs/page_client-reference-manifest.js +1 -1
  25. package/app/apps/web/.next-bundle/server/app/(app)/search/page_client-reference-manifest.js +1 -1
  26. package/app/apps/web/.next-bundle/server/app/(app)/twin/look/page_client-reference-manifest.js +1 -1
  27. package/app/apps/web/.next-bundle/server/app/(app)/twin/page_client-reference-manifest.js +1 -1
  28. package/app/apps/web/.next-bundle/server/app/(app)/unsaved/page.js +1 -1
  29. package/app/apps/web/.next-bundle/server/app/(app)/unsaved/page_client-reference-manifest.js +1 -1
  30. package/app/apps/web/.next-bundle/server/app/_not-found/page_client-reference-manifest.js +1 -1
  31. package/app/apps/web/.next-bundle/server/app/api/accounts/route_client-reference-manifest.js +1 -1
  32. package/app/apps/web/.next-bundle/server/app/api/agent/consult/route_client-reference-manifest.js +1 -1
  33. package/app/apps/web/.next-bundle/server/app/api/agent/context/route_client-reference-manifest.js +1 -1
  34. package/app/apps/web/.next-bundle/server/app/api/agent/journal/route_client-reference-manifest.js +1 -1
  35. package/app/apps/web/.next-bundle/server/app/api/agent/keys/route_client-reference-manifest.js +1 -1
  36. package/app/apps/web/.next-bundle/server/app/api/agent/log/route_client-reference-manifest.js +1 -1
  37. package/app/apps/web/.next-bundle/server/app/api/agent/mcp/route_client-reference-manifest.js +1 -1
  38. package/app/apps/web/.next-bundle/server/app/api/agent/notes/route_client-reference-manifest.js +1 -1
  39. package/app/apps/web/.next-bundle/server/app/api/agent/tasks/[id]/route_client-reference-manifest.js +1 -1
  40. package/app/apps/web/.next-bundle/server/app/api/agent/tasks/route_client-reference-manifest.js +1 -1
  41. package/app/apps/web/.next-bundle/server/app/api/ai/route_client-reference-manifest.js +1 -1
  42. package/app/apps/web/.next-bundle/server/app/api/assets/route_client-reference-manifest.js +1 -1
  43. package/app/apps/web/.next-bundle/server/app/api/assignments/launch/route_client-reference-manifest.js +1 -1
  44. package/app/apps/web/.next-bundle/server/app/api/assignments/route_client-reference-manifest.js +1 -1
  45. package/app/apps/web/.next-bundle/server/app/api/catalog/route_client-reference-manifest.js +1 -1
  46. package/app/apps/web/.next-bundle/server/app/api/check/route_client-reference-manifest.js +1 -1
  47. package/app/apps/web/.next-bundle/server/app/api/consultations/route_client-reference-manifest.js +1 -1
  48. package/app/apps/web/.next-bundle/server/app/api/describe/route_client-reference-manifest.js +1 -1
  49. package/app/apps/web/.next-bundle/server/app/api/disk/route_client-reference-manifest.js +1 -1
  50. package/app/apps/web/.next-bundle/server/app/api/enrich/route_client-reference-manifest.js +1 -1
  51. package/app/apps/web/.next-bundle/server/app/api/environment/route_client-reference-manifest.js +1 -1
  52. package/app/apps/web/.next-bundle/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  53. package/app/apps/web/.next-bundle/server/app/api/ingest/route_client-reference-manifest.js +1 -1
  54. package/app/apps/web/.next-bundle/server/app/api/md/apply/route_client-reference-manifest.js +1 -1
  55. package/app/apps/web/.next-bundle/server/app/api/md/context/route_client-reference-manifest.js +1 -1
  56. package/app/apps/web/.next-bundle/server/app/api/md/inspect/route_client-reference-manifest.js +1 -1
  57. package/app/apps/web/.next-bundle/server/app/api/md/repair/route_client-reference-manifest.js +1 -1
  58. package/app/apps/web/.next-bundle/server/app/api/md/review/route_client-reference-manifest.js +1 -1
  59. package/app/apps/web/.next-bundle/server/app/api/north/route_client-reference-manifest.js +1 -1
  60. package/app/apps/web/.next-bundle/server/app/api/notes/route_client-reference-manifest.js +1 -1
  61. package/app/apps/web/.next-bundle/server/app/api/open/route_client-reference-manifest.js +1 -1
  62. package/app/apps/web/.next-bundle/server/app/api/project/route_client-reference-manifest.js +1 -1
  63. package/app/apps/web/.next-bundle/server/app/api/rescan/route_client-reference-manifest.js +1 -1
  64. package/app/apps/web/.next-bundle/server/app/api/roots/route_client-reference-manifest.js +1 -1
  65. package/app/apps/web/.next-bundle/server/app/api/runs/[id]/route_client-reference-manifest.js +1 -1
  66. package/app/apps/web/.next-bundle/server/app/api/runs/route_client-reference-manifest.js +1 -1
  67. package/app/apps/web/.next-bundle/server/app/api/scale/route_client-reference-manifest.js +1 -1
  68. package/app/apps/web/.next-bundle/server/app/api/search/route_client-reference-manifest.js +1 -1
  69. package/app/apps/web/.next-bundle/server/app/api/secrets/route_client-reference-manifest.js +1 -1
  70. package/app/apps/web/.next-bundle/server/app/api/tasks/route_client-reference-manifest.js +1 -1
  71. package/app/apps/web/.next-bundle/server/app/api/today/route_client-reference-manifest.js +1 -1
  72. package/app/apps/web/.next-bundle/server/app/api/twin/assign/route_client-reference-manifest.js +1 -1
  73. package/app/apps/web/.next-bundle/server/app/api/twin/classify/route_client-reference-manifest.js +1 -1
  74. package/app/apps/web/.next-bundle/server/app/api/twin/critique/route_client-reference-manifest.js +1 -1
  75. package/app/apps/web/.next-bundle/server/app/api/twin/design/route_client-reference-manifest.js +1 -1
  76. package/app/apps/web/.next-bundle/server/app/api/twin/distill/route_client-reference-manifest.js +1 -1
  77. package/app/apps/web/.next-bundle/server/app/api/twin/look/route_client-reference-manifest.js +1 -1
  78. package/app/apps/web/.next-bundle/server/app/api/twin/mine/route_client-reference-manifest.js +1 -1
  79. package/app/apps/web/.next-bundle/server/app/api/twin/score/route_client-reference-manifest.js +1 -1
  80. package/app/apps/web/.next-bundle/server/app/api/twin/shot/route_client-reference-manifest.js +1 -1
  81. package/app/apps/web/.next-bundle/server/app/api/twin/sources/route_client-reference-manifest.js +1 -1
  82. package/app/apps/web/.next-bundle/server/app/api/twin/synthesize/route_client-reference-manifest.js +1 -1
  83. package/app/apps/web/.next-bundle/server/app/api/twin/taste/route_client-reference-manifest.js +1 -1
  84. package/app/apps/web/.next-bundle/server/app/api/twin/verdicts/route_client-reference-manifest.js +1 -1
  85. package/app/apps/web/.next-bundle/server/app/api/watch/route_client-reference-manifest.js +1 -1
  86. package/app/apps/web/.next-bundle/server/app/icon/[id]/route_client-reference-manifest.js +1 -1
  87. package/app/apps/web/.next-bundle/server/app-paths-manifest.json +31 -31
  88. package/app/apps/web/.next-bundle/server/chunks/2643.js +1 -0
  89. package/app/apps/web/.next-bundle/server/chunks/2930.js +1 -1
  90. package/app/apps/web/.next-bundle/server/chunks/3677.js +1 -1
  91. package/app/apps/web/.next-bundle/server/chunks/6790.js +1 -1
  92. package/app/apps/web/.next-bundle/server/functions-config-manifest.json +12 -12
  93. package/app/apps/web/.next-bundle/server/middleware-manifest.json +5 -5
  94. package/app/apps/web/.next-bundle/server/pages/500.html +1 -1
  95. package/app/apps/web/.next-bundle/server/pages-manifest.json +1 -1
  96. package/app/apps/web/.next-bundle/server/server-reference-manifest.json +1 -1
  97. package/app/apps/web/.next-bundle/static/chunks/7911-22e5c2227cd664f0.js +1 -0
  98. package/app/apps/web/.next-bundle/static/chunks/app/(app)/{layout-31d29c0c446300c6.js → layout-d7eece5b47fcac36.js} +1 -1
  99. package/app/apps/web/.next-bundle/static/css/6de932bb4718a4fa.css +1 -0
  100. package/app/node_modules/@panoma/db/dist/index.js +6 -2
  101. package/app/package.json +2 -2
  102. package/dist/{ai-command-GXVWRPG5.js → ai-command-XQGHWOY5.js} +1 -1
  103. package/dist/{check-command-OZAOBH66.js → check-command-2SZH5KYN.js} +3 -3
  104. package/dist/{chunk-A7NMMQSL.js → chunk-4ZMDIOH5.js} +2 -2
  105. package/dist/{chunk-WBUYXOB3.js → chunk-ELBBRUIH.js} +3 -3
  106. package/dist/{chunk-Y5BA6DCQ.js → chunk-JLPWKPLM.js} +19 -2
  107. package/dist/{chunk-UFPX4W7T.js → chunk-VP225OGF.js} +70 -10
  108. package/dist/index.js +52 -21
  109. package/dist/{md-command-KAU5D3BI.js → md-command-76RMDZKU.js} +9 -3
  110. package/dist/{next-command-5WF34ATC.js → next-command-KUHZCZPR.js} +3 -3
  111. package/dist/{north-command-Q3BYJOZF.js → north-command-VRD6EQP6.js} +3 -3
  112. package/dist/{review-command-32A4QW2P.js → review-command-ILJVQMZU.js} +1 -1
  113. package/dist/{twin-command-PFZKINMK.js → twin-command-XJEJ6453.js} +3 -3
  114. package/npm-shrinkwrap.json +2 -2
  115. package/package.json +2 -2
  116. package/app/apps/web/.next-bundle/static/chunks/7911-9b61377ca797a490.js +0 -1
  117. package/app/apps/web/.next-bundle/static/css/d0521a5944efa1d9.css +0 -1
  118. /package/app/apps/web/.next-bundle/static/{fNv6G6KHYkmFvg6vUfSi4 → EAuc0Br8TdDur7GG5w5XO}/_buildManifest.js +0 -0
  119. /package/app/apps/web/.next-bundle/static/{fNv6G6KHYkmFvg6vUfSi4 → EAuc0Br8TdDur7GG5w5XO}/_ssgManifest.js +0 -0
@@ -59,6 +59,15 @@ var MESSAGES = {
59
59
  "today.title": "Today",
60
60
  "today.waiting": "Waiting on you",
61
61
  "today.born": "New in the catalog",
62
+ /*
63
+ The first visit has no previous visit, and for weeks it was told the same sentence as everyone
64
+ else. `visit.json` does not exist until someone has looked, `visitWindow` answers null, and
65
+ `period` turned that null into "since you last looked" for a person who had never looked — the
66
+ very first line of the product, and a comparison with nothing. Null is not "a long time ago"
67
+ either: with no mark, `getDailyReport` opens a window of exactly one day, so this names the
68
+ window instead of inventing the comparison.
69
+ */
70
+ "today.firstLook": "in the last day, on your first look",
62
71
  "today.sinceLastVisit": "since you last looked",
63
72
  "today.sinceToday": "since today at {time}",
64
73
  "today.sinceYesterday": "since yesterday at {time}",
@@ -100,7 +109,14 @@ var MESSAGES = {
100
109
  "card.health": "Health",
101
110
  "card.unsaved": "Unsaved",
102
111
  "card.howToRun": "How to run it",
103
- "card.copies": "({n} copies)",
112
+ /*
113
+ A family of two folders holds exactly one copy, which is the commonest first find on any disk:
114
+ `findDuplicateFamilies` discards a group only when it has fewer than two **members**, and the
115
+ copies are the members minus the canonical one. So this printed «(1 copies)» — and the plurals
116
+ guard could not see it, because an exemption there claimed that a group of one copy is never
117
+ formed. It is formed by every single duplicated pair. The exemption went with this fix.
118
+ */
119
+ "card.copies": "({n} cop{ies})",
104
120
  "card.analyzed": "files analyzed: {files} \xB7 in {ms}ms",
105
121
  "card.truncated": " (truncated)",
106
122
  "card.agents": "Agents",
@@ -143,7 +159,7 @@ var MESSAGES = {
143
159
  "families.title": "Copies grouped",
144
160
  "families.main": "main",
145
161
  "families.detected": "Copies found",
146
- "families.summary": "{families} families \xB7 {folders} duplicate folders \xB7 {size} of repeated code",
162
+ "families.summary": "{families} famil{fs} \xB7 {folders} duplicate folder{ds} \xB7 {size} of repeated code",
147
163
  "families.alive": "\u2713 alive",
148
164
  "families.copy": "\xB7 copy",
149
165
  "families.noGit": "no git",
@@ -193,7 +209,15 @@ var MESSAGES = {
193
209
  "scan.nextApp": "The next step is the app: npx panoma up",
194
210
  "scan.catalogAt": "Your catalog is at {api}",
195
211
  "scan.projects": "{n} project{s}",
196
- "scan.looksLikeCopies": "{n} look like copies \xB7 use -d to see them",
212
+ /*
213
+ A pair of keys and not a form gap, because the figure drags three words at once: with a single
214
+ copy the sentence needs «looks», «a copy» and «it», and no suffix does that to a verb, a noun
215
+ and a pronoun in the same pass. The singular spells the number out rather than printing it —
216
+ «1 looks like a copy» would be the same bug wearing the bandage — and it reads after the count
217
+ that opens the line: «12 projects · one looks like a copy».
218
+ */
219
+ "scan.looksLikeCopiesOne": "one looks like a copy \xB7 use -d to see it",
220
+ "scan.looksLikeCopiesMany": "{n} look like copies \xB7 use -d to see them",
197
221
  "scan.seeFullCard": "use -v for the full report",
198
222
  /*
199
223
  Two keys and not a form hole, because with a commit the noun does not change by itself: the
@@ -230,9 +254,21 @@ var MESSAGES = {
230
254
  "enrich.unresolvable": "{n} unpublished (private, local or renamed)",
231
255
  "enrich.retry": "{n} failed and will be retried",
232
256
  "enrich.portfolio": "Portfolio state",
233
- "enrich.outdated": "{n} direct dependencies outdated",
234
- "enrich.advisories": "{n} security advisories",
235
- "enrich.affect": "affect {n} version{s} in use",
257
+ /*
258
+ «dependency» and «advisory» lose the y when they grow, so the gap carries both halves, the same
259
+ shape `cli.catalogUpdated` uses for «technology» and «family». One stale package used to read
260
+ «1 direct dependencies outdated», and one stale package is exactly what a portfolio of one
261
+ project has.
262
+ */
263
+ "enrich.outdated": "{n} direct dependenc{ies} outdated",
264
+ "enrich.advisories": "{n} security advisor{ies}",
265
+ /*
266
+ A participle and not a conjugated verb. This half is printed right after `enrich.advisories`
267
+ and its subject is that other count, which this sentence never receives: with one advisory it
268
+ said «1 security advisory affect 2 versions in use». «affecting» has no number to agree with,
269
+ so the seam between the two keys stops being a place where the grammar can break.
270
+ */
271
+ "enrich.affect": "affecting {n} version{s} in use",
236
272
  "enrich.noVulns": "no known vulnerabilities",
237
273
  "disk.measuring": "Measuring each project\u2019s disk usage\u2026",
238
274
  "disk.total": "{total} in total \xB7 {reclaimable} regenerates itself",
@@ -355,7 +391,7 @@ var MESSAGES = {
355
391
  "md.checking": "Checking the instructions file against the disk\u2026",
356
392
  "md.noDocs": "There is no AGENTS.md or CLAUDE.md here.",
357
393
  "md.noDocsHint": "panoma md init creates AGENTS.md with panoma's context block.",
358
- "md.fileHead": "{file} \xB7 {tokens} tokens \xB7 {lines} lines",
394
+ "md.fileHead": "{file} \xB7 {tokens} token{ts} \xB7 {lines} line{ls}",
359
395
  "md.managedTag": "has panoma's block",
360
396
  "md.clean": "everything it claims exists",
361
397
  "md.findingCount": "{n} claim{s} no longer true",
@@ -393,9 +429,33 @@ var MESSAGES = {
393
429
  "md.broken": "The block is broken: {reason}",
394
430
  "cli.httpError": "The catalog returned {status}. {detail}",
395
431
  "cli.ingestRejected": "The catalog rejected the ingest ({status}). {detail}",
396
- "cli.removed": "{n} no longer existed and were retired",
397
- "cli.catalogUpdated": "Catalog updated: {projects} project{ps}, {technologies} technologies, {packages} packages, {families} families",
398
- "cli.excluded": "{n} were skipped for living outside the catalog, as you asked",
432
+ /*
433
+ A pair each, because the word the number drags here is a verb: «1 were skipped» is the
434
+ number-at-the-end bug in its worst shape, and a noun suffix never reaches «was». The noun that
435
+ was missing goes in too — a bare figure followed by a verb left the reader guessing what had
436
+ been retired.
437
+ */
438
+ "cli.removedOne": "{n} project no longer existed and was retired",
439
+ "cli.removedMany": "{n} projects no longer existed and were retired",
440
+ /*
441
+ The three sentences npx needs, and none of them says «trial».
442
+ What runs under `npx panoma` is this same package, byte for byte: nothing is limited and
443
+ nothing expires. What is temporary is the command, and saying anything stronger would be a
444
+ lie the rest of this product does not tell.
445
+ */
446
+ "npx.hooksRefused": "Hooks need a panoma that is still here tomorrow.",
447
+ "npx.hooksRefusedWhy": "This copy runs from npx, which keeps it for one command and then lets it go. A hook written\n now would call a command that stops existing the moment this one ends \u2014 and hooks stay quiet\n by design, so nothing would ever tell you.",
448
+ "npx.hooksRefusedHow": "Install it and try again: npm i -g panoma",
449
+ "npx.upEphemeral": "running from npx \xB7 to keep the command: npm i -g panoma",
450
+ "cli.catalogUpdated": "Catalog updated: {projects} project{ps}, {technologies} technolog{ts}, {packages} package{ks}, {families} famil{fs}",
451
+ /*
452
+ «as you asked» is literal and was checked before it was kept: the rows come from the
453
+ `exclusions` table, `excludeProject` writes them when someone takes a project out of the
454
+ catalog from the web —typing its name to confirm— and `ingestPortfolio` reads them to skip
455
+ those roots. The CLI never writes there; it only reports what the ingest left out.
456
+ */
457
+ "cli.excludedOne": "{n} project was skipped for living outside the catalog, as you asked",
458
+ "cli.excludedMany": "{n} projects were skipped for living outside the catalog, as you asked",
399
459
  "cli.reslugged": "{n} changed address when unique names were handed out",
400
460
  "search.nothingTracked": "No git-tracked file contains \u201C{term}\u201D.",
401
461
  "disk.walking": "Walking each project\u2019s tree. This takes several minutes\u2026",
package/dist/index.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  entryCommand,
4
4
  helpText,
5
5
  todayCommand
6
- } from "./chunk-WBUYXOB3.js";
6
+ } from "./chunk-ELBBRUIH.js";
7
7
  import {
8
8
  openCommand
9
- } from "./chunk-A7NMMQSL.js";
9
+ } from "./chunk-4ZMDIOH5.js";
10
10
  import {
11
11
  catalogFetch,
12
12
  cliEntry,
@@ -18,12 +18,12 @@ import {
18
18
  panomaCommand,
19
19
  unreachable,
20
20
  upCommand
21
- } from "./chunk-Y5BA6DCQ.js";
21
+ } from "./chunk-JLPWKPLM.js";
22
22
  import {
23
23
  plural,
24
24
  riskText,
25
25
  say
26
- } from "./chunk-UFPX4W7T.js";
26
+ } from "./chunk-VP225OGF.js";
27
27
  import {
28
28
  HOOKS_BRAND,
29
29
  MCP_FILE_MODE,
@@ -255,7 +255,19 @@ async function hooksCommand(directory, api, action) {
255
255
  );
256
256
  return 1;
257
257
  }
258
- const { argv, aviso } = await panomaCommand();
258
+ const { argv, aviso, efimero } = await panomaCommand();
259
+ if (efimero) {
260
+ process.stderr.write(
261
+ `
262
+ ${pc.yellow(say("npx.hooksRefused"))}
263
+ ${pc.dim(say("npx.hooksRefusedWhy"))}
264
+
265
+ ${pc.cyan(say("npx.hooksRefusedHow"))}
266
+
267
+ `
268
+ );
269
+ return 1;
270
+ }
259
271
  if (aviso) process.stderr.write(`${pc.yellow("!")} ${pc.dim(aviso)}
260
272
  `);
261
273
  const paraGit = asShellLine([...argv, "scan", ".", "--save", "--api", api]);
@@ -870,7 +882,9 @@ function renderFamilies(families, baseDir) {
870
882
  ` ${say("families.detected")} ${pc2.dim(
871
883
  say("families.summary", {
872
884
  families: families.length,
885
+ fs: plural(families.length, "ies", "y"),
873
886
  folders: totalCopies,
887
+ ds: plural(totalCopies),
874
888
  size: formatBytes(totalBytes)
875
889
  })
876
890
  )}`
@@ -878,7 +892,10 @@ function renderFamilies(families, baseDir) {
878
892
  ""
879
893
  ];
880
894
  for (const family of families) {
881
- lines.push(` ${pc2.bold(pc2.cyan(family.name))} ${pc2.dim(say("card.copies", { n: family.copies.length }))}`);
895
+ const copies = family.copies.length;
896
+ lines.push(
897
+ ` ${pc2.bold(pc2.cyan(family.name))} ${pc2.dim(say("card.copies", { n: copies, ies: plural(copies, "ies", "y") }))}`
898
+ );
882
899
  lines.push(
883
900
  ` ${pc2.green(say("families.alive"))} ${relativePath(family.canonical.root, baseDir).padEnd(48)} ${pc2.dim(family.canonicalReason)}`
884
901
  );
@@ -1008,11 +1025,11 @@ ${pc3.dim(say("error.seeHelp"))}
1008
1025
  if (command === void 0) return conAviso(await entryCommand(parsed.api));
1009
1026
  if (command === "today") return todayCommand(parsed.api);
1010
1027
  if (command === "next") {
1011
- const { nextCommand } = await import("./next-command-5WF34ATC.js");
1028
+ const { nextCommand } = await import("./next-command-KUHZCZPR.js");
1012
1029
  return nextCommand(parsed.api, parsed.positionals.slice(1));
1013
1030
  }
1014
1031
  if (command === "north") {
1015
- const { northCommand } = await import("./north-command-Q3BYJOZF.js");
1032
+ const { northCommand } = await import("./north-command-VRD6EQP6.js");
1016
1033
  return northCommand(parsed);
1017
1034
  }
1018
1035
  if (command === "open") {
@@ -1032,7 +1049,7 @@ ${pc3.dim(say("error.seeHelp"))}
1032
1049
  `));
1033
1050
  return 1;
1034
1051
  }
1035
- const { checkCommand } = await import("./check-command-OZAOBH66.js");
1052
+ const { checkCommand } = await import("./check-command-2SZH5KYN.js");
1036
1053
  return checkCommand(parsed.api, query);
1037
1054
  }
1038
1055
  let escanear = command === "scan";
@@ -1060,14 +1077,14 @@ ${pc3.dim(say("error.seeHelp"))}
1060
1077
  );
1061
1078
  }
1062
1079
  if (command === "ai") {
1063
- const { aiCommand } = await import("./ai-command-GXVWRPG5.js");
1080
+ const { aiCommand } = await import("./ai-command-XQGHWOY5.js");
1064
1081
  return aiCommand(parsed);
1065
1082
  }
1066
1083
  if (command === "md") {
1067
1084
  const target2 = resolve3(
1068
1085
  expandTilde(parsed.positionals[2] ?? ".")
1069
1086
  );
1070
- const { mdCommand } = await import("./md-command-KAU5D3BI.js");
1087
+ const { mdCommand } = await import("./md-command-76RMDZKU.js");
1071
1088
  return mdCommand(parsed.positionals[1], target2, parsed.api);
1072
1089
  }
1073
1090
  if (command === "disk") return reportDisk(parsed.api);
@@ -1118,12 +1135,12 @@ ${pc3.dim(say("error.seeHelp"))}
1118
1135
  return createAgentKey(parsed.api, name, parsed.install);
1119
1136
  }
1120
1137
  if (command === "twin") {
1121
- const { twinCommand } = await import("./twin-command-PFZKINMK.js");
1138
+ const { twinCommand } = await import("./twin-command-XJEJ6453.js");
1122
1139
  return twinCommand(parsed);
1123
1140
  }
1124
1141
  if (command === "review") {
1125
1142
  const target2 = resolve3(expandTilde(parsed.positionals[1] ?? "."));
1126
- const { reviewCommand } = await import("./review-command-32A4QW2P.js");
1143
+ const { reviewCommand } = await import("./review-command-ILJVQMZU.js");
1127
1144
  return reviewCommand(target2);
1128
1145
  }
1129
1146
  if (!escanear) {
@@ -1239,7 +1256,11 @@ ${helpText()}
1239
1256
  }
1240
1257
  }
1241
1258
  const totalCopies = families.reduce((sum, f) => sum + f.copies.length, 0);
1242
- const hint = totalCopies > 0 ? pc3.yellow(say("scan.looksLikeCopies", { n: totalCopies })) : say("scan.seeFullCard");
1259
+ const hint = totalCopies > 0 ? pc3.yellow(
1260
+ say(totalCopies === 1 ? "scan.looksLikeCopiesOne" : "scan.looksLikeCopiesMany", {
1261
+ n: totalCopies
1262
+ })
1263
+ ) : say("scan.seeFullCard");
1243
1264
  const cuantos = say("scan.projects", {
1244
1265
  n: analyses.length,
1245
1266
  s: plural(analyses.length)
@@ -1369,20 +1390,30 @@ async function saveToCatalog(api, analyses, families, scope, origins) {
1369
1390
  projects: result.projects,
1370
1391
  ps: plural(result.projects),
1371
1392
  technologies: result.technologies,
1393
+ // «technology» and «family» do not pluralize with an `s`, so the gap carries both halves.
1394
+ ts: plural(result.technologies, "ies", "y"),
1372
1395
  packages: result.packages,
1373
- families: result.families
1396
+ ks: plural(result.packages),
1397
+ families: result.families,
1398
+ fs: plural(result.families, "ies", "y")
1374
1399
  })}
1375
1400
  `
1376
1401
  )
1377
1402
  );
1378
1403
  if (result.removed) {
1379
- process.stderr.write(pc3.dim(` ${say("cli.removed", { n: result.removed })}
1380
- `));
1404
+ process.stderr.write(
1405
+ pc3.dim(
1406
+ ` ${say(result.removed === 1 ? "cli.removedOne" : "cli.removedMany", { n: result.removed })}
1407
+ `
1408
+ )
1409
+ );
1381
1410
  }
1382
1411
  if (result.excluded) {
1383
1412
  process.stderr.write(
1384
- pc3.dim(` ${say("cli.excluded", { n: result.excluded })}
1385
- `)
1413
+ pc3.dim(
1414
+ ` ${say(result.excluded === 1 ? "cli.excludedOne" : "cli.excludedMany", { n: result.excluded })}
1415
+ `
1416
+ )
1386
1417
  );
1387
1418
  }
1388
1419
  if (result.reslugged) {
@@ -1570,8 +1601,8 @@ async function enrichCatalog(api, force) {
1570
1601
  result.failed > 0 ? ` ${pc3.yellow(say("enrich.retry", { n: result.failed }))}` : "",
1571
1602
  "",
1572
1603
  ` ${pc3.bold(say("enrich.portfolio"))}`,
1573
- ` ${say("enrich.outdated", { n: pc3.yellow(String(result.outdated)) })}`,
1574
- result.advisories > 0 ? ` ${pc3.red(say("enrich.advisories", { n: result.advisories }))} ${say("enrich.affect", { n: result.vulnerablePackages, s: plural(result.vulnerablePackages) })}` : ` ${pc3.green(say("enrich.noVulns"))}`,
1604
+ ` ${say("enrich.outdated", { n: pc3.yellow(String(result.outdated)), ies: plural(result.outdated, "ies", "y") })}`,
1605
+ result.advisories > 0 ? ` ${pc3.red(say("enrich.advisories", { n: result.advisories, ies: plural(result.advisories, "ies", "y") }))} ${say("enrich.affect", { n: result.vulnerablePackages, s: plural(result.vulnerablePackages) })}` : ` ${pc3.green(say("enrich.noVulns"))}`,
1575
1606
  ""
1576
1607
  ].filter(Boolean).join("\n") + "\n"
1577
1608
  );
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  catalogFetch,
3
3
  unreachable
4
- } from "./chunk-Y5BA6DCQ.js";
4
+ } from "./chunk-JLPWKPLM.js";
5
5
  import {
6
6
  plural,
7
7
  say
8
- } from "./chunk-UFPX4W7T.js";
8
+ } from "./chunk-VP225OGF.js";
9
9
  import {
10
10
  CLAUDE_BRIDGE,
11
11
  TASTE_CAP,
@@ -73,7 +73,13 @@ async function check(target) {
73
73
  for (const file of report.files) {
74
74
  const managed = file.managed ? pc.dim(` \xB7 ${say("md.managedTag")}`) : "";
75
75
  out.push(
76
- ` ${pc.bold(say("md.fileHead", { file: file.file, tokens: file.tokens, lines: file.lines }))}${managed}`
76
+ ` ${pc.bold(say("md.fileHead", {
77
+ file: file.file,
78
+ tokens: file.tokens,
79
+ ts: plural(file.tokens),
80
+ lines: file.lines,
81
+ ls: plural(file.lines)
82
+ }))}${managed}`
77
83
  );
78
84
  if (file.findings.length === 0) {
79
85
  out.push(` ${pc.green(say("md.clean"))}`);
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  reportUrl
3
- } from "./chunk-WBUYXOB3.js";
3
+ } from "./chunk-ELBBRUIH.js";
4
4
  import {
5
5
  catalogFetch,
6
6
  unreachable
7
- } from "./chunk-Y5BA6DCQ.js";
7
+ } from "./chunk-JLPWKPLM.js";
8
8
  import {
9
9
  plural,
10
10
  say
11
- } from "./chunk-UFPX4W7T.js";
11
+ } from "./chunk-VP225OGF.js";
12
12
  import "./chunk-K27F6QDR.js";
13
13
 
14
14
  // src/next-command.ts
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  reportUrl
3
- } from "./chunk-WBUYXOB3.js";
3
+ } from "./chunk-ELBBRUIH.js";
4
4
  import {
5
5
  catalogFetch,
6
6
  unreachable
7
- } from "./chunk-Y5BA6DCQ.js";
7
+ } from "./chunk-JLPWKPLM.js";
8
8
  import {
9
9
  plural,
10
10
  say
11
- } from "./chunk-UFPX4W7T.js";
11
+ } from "./chunk-VP225OGF.js";
12
12
  import "./chunk-K27F6QDR.js";
13
13
 
14
14
  // src/north-command.ts
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  plural,
3
3
  say
4
- } from "./chunk-UFPX4W7T.js";
4
+ } from "./chunk-VP225OGF.js";
5
5
 
6
6
  // src/review-command.ts
7
7
  import pc from "picocolors";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  sinceMs
3
- } from "./chunk-WBUYXOB3.js";
3
+ } from "./chunk-ELBBRUIH.js";
4
4
  import {
5
5
  catalogFetch,
6
6
  unreachable
7
- } from "./chunk-Y5BA6DCQ.js";
7
+ } from "./chunk-JLPWKPLM.js";
8
8
  import {
9
9
  plural,
10
10
  say
11
- } from "./chunk-UFPX4W7T.js";
11
+ } from "./chunk-VP225OGF.js";
12
12
  import "./chunk-K27F6QDR.js";
13
13
 
14
14
  // src/twin-command.ts
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "panoma",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "panoma",
9
- "version": "0.1.0",
9
+ "version": "0.1.2",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.71.0",
12
12
  "ignore": "^6.0.2",
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "panoma",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "description": "The local catalog of your projects: everything on your disk, ready to pick up — by you or by your agents.",
7
7
  "homepage": "https://panoma.ai",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/panomahq/panoma.git",
10
+ "url": "git+https://github.com/PanomaAI/panoma.git",
11
11
  "directory": "apps/cli"
12
12
  },
13
13
  "keywords": [