@tendrilapp/cli 0.1.20 → 0.1.23
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 +8 -0
- package/dist/SKILL.md +24 -10
- package/dist/tendril-mcp.js +18 -5
- package/dist/tendril.js +1043 -276
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,4 +9,12 @@ Figma design systems → verified React components.
|
|
|
9
9
|
{ "mcpServers": { "tendril": { "command": "tendril-mcp" } } }
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
Working in Claude Code? Your agent can install the permission
|
|
13
|
+
allowlist for you — it will offer, or ask it to run
|
|
14
|
+
`tendril permissions` (one approval replaces a prompt per call).
|
|
15
|
+
|
|
16
|
+
After every verify, open the eye check: `tendril inspect <bundleDir>`
|
|
17
|
+
renders magnified recorded-vs-rendered crops of every small detail —
|
|
18
|
+
scores measure pixels; the sheet shows shape.
|
|
19
|
+
|
|
12
20
|
Verification is local, account-less, and network-less — always.
|
package/dist/SKILL.md
CHANGED
|
@@ -39,16 +39,30 @@ user must reload the session to apply; say that out loud. Offer ONCE
|
|
|
39
39
|
per session; never run it unoffered (it edits the user's settings),
|
|
40
40
|
and if declined, proceed without mentioning it again.
|
|
41
41
|
|
|
42
|
-
Long generator/score waits: silence is not a health signal
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
Long generator/score waits: silence is not a health signal, and POLL
|
|
43
|
+
cadence is not RELAY cadence (run 13: rounds landed 6–11 minutes apart,
|
|
44
|
+
so a correct 30s poll still left the user in 9-minute silences they
|
|
45
|
+
flagged as unacceptable). Two duties: relay each round's result the
|
|
46
|
+
moment `<candidateDir>/score-history.jsonl` gains a line ("round 3
|
|
47
|
+
scored: 15/21 at floor 0.885"), AND when more than ~60 seconds pass
|
|
48
|
+
with no round, emit a liveness line from the candidate dir's file
|
|
49
|
+
mtimes, which move while the generator is WRITING (thinking pauses are quiet — that is normal, not frozen) ("still
|
|
50
|
+
working — styles.css touched 20s ago"). The history file APPEARS ONLY
|
|
51
|
+
AFTER THE FIRST completed score, so its absence early is normal, not
|
|
52
|
+
frozen. A healthy run can take 30+ minutes; never kill on elapsed time
|
|
53
|
+
alone — count staleness from the LAST CHANGE to any signal, and when
|
|
54
|
+
past ~20 minutes of true staleness, ask the user before killing.
|
|
55
|
+
|
|
56
|
+
Before concluding "inherent limitation" on a stuck score: enumerate the
|
|
57
|
+
rendering inputs you have NOT verified — are the declared font faces
|
|
58
|
+
actually resolved (the kit's cached faces and weights vs what the CSS
|
|
59
|
+
asks for), computed styles vs authored styles, and
|
|
60
|
+
an `(lcd-text-enabled)` experiment mark in the environment stamp — and
|
|
61
|
+
check them first (platform AA itself is pinned greyscale in every
|
|
62
|
+
canonical mount). Run 13's "inherent
|
|
63
|
+
fidelity gap" was a missing font weight one check away; a stop rule is
|
|
64
|
+
for avoiding thrash, never for converting an unverified hypothesis into
|
|
65
|
+
a final answer.
|
|
52
66
|
|
|
53
67
|
Batch runs (several components in one session):
|
|
54
68
|
- Cap concurrent recorders at FOUR. All recorders share one Figma
|
package/dist/tendril-mcp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// packages/mcp/src/bin.ts
|
|
3
|
+
// ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/mcp/src/bin.ts
|
|
4
4
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
5
5
|
import path2 from "node:path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -8,7 +8,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
8
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
9
|
import { z as z2 } from "zod";
|
|
10
10
|
|
|
11
|
-
// packages/mcp/src/server.ts
|
|
11
|
+
// ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/mcp/src/server.ts
|
|
12
12
|
import { execFile } from "node:child_process";
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
14
14
|
import { existsSync, mkdtempSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
@@ -363,16 +363,29 @@ function serverStale() {
|
|
|
363
363
|
return false;
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
|
+
var STDERR_SECTION = "--- CLI stderr (remediation) ---";
|
|
367
|
+
function resultBody(result) {
|
|
368
|
+
const out = result.stdout.trim() === "" ? "" : result.stdout;
|
|
369
|
+
const err = result.stderr.trim() === "" ? "" : result.stderr;
|
|
370
|
+
if (result.ok || out === "" || err === "") return out === "" ? err : out;
|
|
371
|
+
return `${out.replace(/\n+$/, "")}
|
|
372
|
+
${STDERR_SECTION}
|
|
373
|
+
${err}`;
|
|
374
|
+
}
|
|
366
375
|
function toolResult(result) {
|
|
367
376
|
const stale = serverStale() ? `
|
|
368
377
|
{"serverStale":true,"remediation":"packages/mcp changed since this server started \u2014 reload the Tendril MCP server before trusting this result or reporting a bug against it"}` : "";
|
|
369
|
-
const body = (result
|
|
378
|
+
const body = resultBody(result) + stale;
|
|
370
379
|
if (result.exitCode === 5) {
|
|
371
380
|
return { content: [{ type: "text", text: `${body}
|
|
372
381
|
{"exitCode":5,"note":"HONEST below-target result \u2014 the report and bundle are valid; this is not a tool failure. Either sub-bar scores, or (at --bar cert) a config demoted by absent-ink clusters despite at-bar numbers \u2014 the report names which."}` }] };
|
|
382
|
+
}
|
|
383
|
+
if (result.exitCode === 4) {
|
|
384
|
+
return { content: [{ type: "text", text: `${body}
|
|
385
|
+
{"exitCode":4,"note":"HONEST outcome \u2014 the CLI completed its work and stopped at a decision reserved for a HUMAN; nothing failed and re-running changes nothing. Show the output above plus the remediation to the user, get their answer, then proceed exactly as the remediation says \u2014 never confirm on their behalf."}` }] };
|
|
373
386
|
}
|
|
374
387
|
const text = result.ok ? body : `${body}
|
|
375
|
-
{"exitCode":${result.exitCode},"note":"CLI exit-code contract: 3 input,
|
|
388
|
+
{"exitCode":${result.exitCode},"note":"CLI exit-code contract: 3 input, 6 fonts unproven, 7 recording incomplete"}`;
|
|
376
389
|
return { content: [{ type: "text", text }], ...result.ok ? {} : { isError: true } };
|
|
377
390
|
}
|
|
378
391
|
var STATUS_PROMPT = {
|
|
@@ -410,7 +423,7 @@ var IMPLEMENT_PROMPT = {
|
|
|
410
423
|
].join("\n")
|
|
411
424
|
};
|
|
412
425
|
|
|
413
|
-
// packages/mcp/src/bin.ts
|
|
426
|
+
// ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/mcp/src/bin.ts
|
|
414
427
|
var version = "dev";
|
|
415
428
|
try {
|
|
416
429
|
version = JSON.parse(readFileSync2(path2.join(path2.dirname(fileURLToPath2(import.meta.url)), "..", "package.json"), "utf8")).version ?? "dev";
|