clearotron 0.3.2-beta.4 → 0.3.2-beta.5

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/INSTALL.md CHANGED
@@ -331,6 +331,7 @@ terminal and is rewritten on every start.
331
331
  ~/trademark/config/profiles the company profiles
332
332
  ~/trademark/grants.json who may use this install
333
333
  ~/trademark/portal-audit.log what the portal was asked to do
334
+ ~/trademark/telemetry/trademark-mcp-access.jsonl what a connected assistant asked for, and what it was told
334
335
  ~/trademark/portal-local-credential.json the sign-in this install minted for you
335
336
  ```
336
337
 
package/bin/onboard.mjs CHANGED
@@ -2702,6 +2702,71 @@ export async function runCheck() {
2702
2702
  + `Run \`${invoke("start")}\` — it creates the list.`);
2703
2703
  }
2704
2704
  }
2705
+ // ── IS THIS DOOR'S ACCESS LOG BEING WRITTEN, AND WHERE? ───────────────────────────────────────────
2706
+ //
2707
+ // A client's assistant can list runs, read reports and pull artifacts through this door. The record of
2708
+ // what a key did is the only way to answer a client, a lawyer or an incident review afterwards, and a
2709
+ // log nobody can find is a log nobody checks.
2710
+ //
2711
+ // THE OVERRIDE IS READ FROM THE UNIT, NOT FROM THIS PROCESS. `TRADEMARK_MCP_AUDIT_LOG` decides where
2712
+ // the writer appends, and the writer is the service — so this command's own environment is not the
2713
+ // answer and using it would produce a confident report about a file the door never touches. Where the
2714
+ // two disagree, that disagreement is the finding and is said out loud rather than resolved silently.
2715
+ //
2716
+ // WITH NO OVERRIDE THERE ARE TWO CANDIDATES, and which one the writer picked depends on what existed
2717
+ // when IT started — a legacy path is kept if it is already there, so that a compliance trail is not
2718
+ // split in two by a moved default. `auditPaths()` is the module's own reader for exactly this and is
2719
+ // called rather than re-derived; re-deriving that branch here is the defect its source warns about.
2720
+ try {
2721
+ const { auditPaths: auditCandidates } = await import(pathToFileURL(join(REPO, "mcp-server", "lib", "audit.mjs")).href);
2722
+ const seen = hosted ? unitValue(unitEnv, "TRADEMARK_MCP_AUDIT_LOG") : { state: "unset", value: null };
2723
+ if (seen.state === "unknown") {
2724
+ info(couldNotDetermine("TRADEMARK_MCP_AUDIT_LOG", unitEnv) + " The access log's location cannot be named.");
2725
+ } else {
2726
+ const mine = String(process.env.TRADEMARK_MCP_AUDIT_LOG ?? "").trim();
2727
+ if (seen.state === "unset" && mine) {
2728
+ warn(`this shell sets TRADEMARK_MCP_AUDIT_LOG and the units do not, so the door is NOT writing where `
2729
+ + `this command would look. The door's log is at its default; ${mine} is this shell's answer only.`);
2730
+ }
2731
+ const paths = seen.state === "set" ? [seen.value] : auditCandidates();
2732
+ let wrote = null;
2733
+ for (const p of paths) {
2734
+ try { const s = statSync(p); if (s.size > 0) { wrote = p; break; } } catch { /* not this one */ }
2735
+ }
2736
+ if (wrote) {
2737
+ ok(`the client door's access log is being written: ${wrote}`);
2738
+ } else {
2739
+ // NOT-YET-WRITTEN IS NOT UNWRITABLE. A door nobody has called through has no log, and saying it
2740
+ // is broken would be the same lie as calling an unreachable unit inactive.
2741
+ //
2742
+ // NAME THE ONE THE WRITER WOULD PICK, WHICH IS NOT SIMPLY THE FIRST. With no override there are
2743
+ // two candidates and the older is kept only when it is ALREADY THERE, so that a compliance trail
2744
+ // is not split by a moved default. Naming the older one unconditionally would print the
2745
+ // integrator platform's folder at setup on installs that have no such file — a folder this engine
2746
+ // does not require and whose mention was deliberately removed from this command. Where it does
2747
+ // exist it IS the log and is named, because that is then the true answer.
2748
+ const existing = paths.find((c) => { try { statSync(c); return true; } catch { return false; } });
2749
+ const willUse = existing ?? paths[paths.length - 1];
2750
+ const dir = dirname(willUse);
2751
+ let writable = null;
2752
+ try { accessSync(dir, constants.W_OK); writable = true; } catch (e) { writable = e?.code === "ENOENT" ? null : false; }
2753
+ if (writable === false) {
2754
+ blocking(`the client door's access log cannot be written: ${dir} is not writable by this user. `
2755
+ + "Every call through this door would go unrecorded, and an absent record reads as nothing happened.");
2756
+ } else if (writable === null) {
2757
+ info(`no access log yet at ${willUse} and its directory does not exist — the door creates it on the `
2758
+ + "first call. Nothing has come through it, or nothing has since the path last changed.");
2759
+ } else {
2760
+ info(`no access log yet at ${willUse}, and its directory is writable — nothing has come through `
2761
+ + "this door yet. The first call creates it.");
2762
+ }
2763
+ }
2764
+ }
2765
+ } catch (e) {
2766
+ info(`could not check the client door's access log (${e?.code ?? e?.message ?? e}) — this is a report `
2767
+ + "that this command could not look, not that the log is missing.");
2768
+ }
2769
+
2705
2770
  try {
2706
2771
  const { clientDoorState: doorState, describeDoorState, connectKeyReport, CLIENT_DOOR_UNIT: doorUnit } = await import(pathToFileURL(join(REPO, "shared", "client-door.mjs")).href);
2707
2772
  const { loadGrants: readGrantsFile, isRevoked: revokedCheck } = await import(pathToFileURL(join(REPO, "shared", "scope.mjs")).href);
package/bin/start.mjs CHANGED
@@ -449,6 +449,10 @@ export function installPaths(base) {
449
449
  locks: join(base, "locks"),
450
450
  grants: join(base, "grants.json"),
451
451
  audit: join(base, "portal-audit.log"),
452
+ // The connector doors' access log — the record of what a client key did, which is what answers a
453
+ // client or a review afterwards. NAMED IN THE LAYOUT rather than built at the call site, for the
454
+ // reason the store below gives: a demo's isolation must be a property of where things live.
455
+ accessLog: join(base, "telemetry", "trademark-mcp-access.jsonl"),
452
456
  // The saved-search store is a git repository because recipe-service commits every save through
453
457
  // `git add` + `git commit` — that is the product's config-store model, not something invented here.
454
458
  // It is its own directory, NOT `base`, so the commit path never sees the pool, the queue or the
@@ -680,6 +684,16 @@ export function childEnv({ ports, paths, user, portalSecret, tokenSecret, opsTok
680
684
  "PROFILE_AUDIT": "",
681
685
  "RECIPE_AUDIT": "",
682
686
  "CLEAROTRON_FEEDBACK_DIR": "",
687
+ // AN EXPLICIT PATH, NOT "" LIKE THE TWO ABOVE. Empty is unset, and unset is what sends this one to
688
+ // the REAL install's home: its default is computed from `homedir()`, not from any directory a demo
689
+ // controls. So a demo left to fall back writes its access lines into the install beside it, and the
690
+ // demo stops being one directory a reader can delete. Measured as exactly that: a demo run left
691
+ // `telemetry/trademark-mcp-access.jsonl` in the install it booted next to.
692
+ //
693
+ // ONLY IN A DEMO. A real install must NOT have this pinned: with no override the writer keeps an
694
+ // older log where one already exists, so that moving the default does not split a compliance trail
695
+ // in two. Pinning the name here would override that and do the splitting.
696
+ "TRADEMARK_MCP_AUDIT_LOG": paths.accessLog,
683
697
  } : {}),
684
698
  });
685
699
  return {
package/build-info.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "commit": "9bb3ab371e736a3b4a80f2d6dbdd71fd719b173e",
3
- "version": "0.3.2-beta.4"
2
+ "commit": "ed09608753479ab7824e8f5f7dc256c12ca0bc07",
3
+ "version": "0.3.2-beta.5"
4
4
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "ts": "2026-09-04T21:48:51.264Z",
2
+ "ts": "2026-09-16T16:48:57.832Z",
3
3
  "lane": "knockout",
4
4
  "checks": [
5
5
  {
@@ -43,9 +43,33 @@
43
43
  "surface": "findings",
44
44
  "pass": true,
45
45
  "detail": ""
46
+ },
47
+ {
48
+ "id": "reviewer-note-subject",
49
+ "family": "voice",
50
+ "surface": "findings",
51
+ "pass": true,
52
+ "detail": ""
53
+ },
54
+ {
55
+ "id": "plain-language-vocabulary",
56
+ "family": "voice",
57
+ "surface": "findings",
58
+ "pass": false,
59
+ "detail": "the lawyer's vocabulary on lines a reader meets before opening anything — rewrite the sentence in the words the reader already owns, do not swap the word: the batch summary: \"belt-and-braces\" → \"extra\"; the batch summary: \"chunk\" (an engine word — cut it)"
60
+ },
61
+ {
62
+ "id": "plain-language-sentence-length",
63
+ "family": "voice",
64
+ "surface": "findings",
65
+ "pass": false,
66
+ "detail": "a default-visible sentence carrying more than one idea (over 25 words) — split it, conclusion first: the batch summary: 28 words; the batch summary: 28 words; the batch summary: 27 words; the batch summary: 39 words; the batch summary: 26 words; +4 more"
46
67
  }
47
68
  ],
48
- "failures": [],
69
+ "failures": [
70
+ "plain-language-vocabulary",
71
+ "plain-language-sentence-length"
72
+ ],
49
73
  "notApplicable": [
50
74
  {
51
75
  "id": "names-cell-populated",
@@ -1,5 +1,11 @@
1
1
  # clearotron-driver
2
2
 
3
+ ## 0.3.2-beta.5
4
+
5
+ ### Patch Changes
6
+
7
+ - a4ea94d: For operators: The connector access log now records what happened to each call, and records calls that were refused as well as calls that got through. A line also names which door took the call, so a client key and a staff session can be told apart. Before, a call was recorded only as having been made, and a refused one left no line at all. `doctor` now names where that log is being written. It reads that from the service's own settings, not from the shell you are typing in.
8
+
3
9
  ## 0.3.2-beta.4
4
10
 
5
11
  ### Patch Changes
@@ -2,7 +2,7 @@
2
2
  "name": "clearotron-driver",
3
3
  "private": true,
4
4
  "type": "module",
5
- "version": "0.3.2-beta.4",
5
+ "version": "0.3.2-beta.5",
6
6
  "license": "AGPL-3.0-only",
7
7
  "description": "Deterministic driver for the trademark clearance workflow: orchestration in code (fan-out, fan-in barrier, gating, retries); the model does judgment leaves only, through a reasoning CLI spawned per stage.",
8
8
  "engines": {
@@ -6437,8 +6437,10 @@ function injectFrontMatter(path, fields, runDir = null) {
6437
6437
  // spec 62 — the per-field CONFIGURATION PROVENANCE rows for a project run: for each PROJECT_KEY, its effective
6438
6438
  // value (compact) and where it came from (project | customer | house). Read off the frozen sidecar `pr` (both
6439
6439
  // origins and the effective values live there), serialised to a single-line JSON string for the report
6440
- // front-matter, and rendered INTERNAL-ONLY in the scope fold (never on the client export — provenance, not
6441
- // process-exhaust). Absent origins ⇒ [] ⇒ nothing injected (no-project runs are untouched).
6440
+ // front-matter. It was rendered internal-only in the scope fold; the 2026-09-16 redesign takes that fold
6441
+ // off the page, and this row set went with it — it was the one block in there labelled internal, which is
6442
+ // the class that ruling removed. IT IS STILL RECORDED, here and in the workbook, which is where a reader
6443
+ // who wants to know which layer set a knob now finds out. Absent origins ⇒ [] ⇒ nothing injected.
6442
6444
  function originRowsForReport(pr) {
6443
6445
  if (!pr?.origins) return [];
6444
6446
  const short = (s, n = 48) => { const t = String(s ?? "").trim(); return t.length > n ? `${t.slice(0, n - 1)}…` : t; };