@tendrilapp/cli 0.1.21 → 0.1.24
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 +15 -8
- package/dist/tendril-mcp.js +15 -2
- package/dist/tendril.js +1433 -532
- 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
|
@@ -43,13 +43,18 @@ Long generator/score waits: silence is not a health signal, and POLL
|
|
|
43
43
|
cadence is not RELAY cadence (run 13: rounds landed 6–11 minutes apart,
|
|
44
44
|
so a correct 30s poll still left the user in 9-minute silences they
|
|
45
45
|
flagged as unacceptable). Two duties: relay each round's result the
|
|
46
|
-
moment `<candidateDir>/score-history.jsonl` gains a
|
|
47
|
-
scored: 15/21 at floor 0.885"), AND when more than ~60
|
|
48
|
-
with no round, emit a liveness line from the candidate
|
|
49
|
-
mtimes, which move while the generator is WRITING (thinking
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
moment `<candidateDir>/score-history.jsonl` gains a `round-scored` line
|
|
47
|
+
("round 3 scored: 15/21 at floor 0.885"), AND when more than ~60
|
|
48
|
+
seconds pass with no round, emit a liveness line from the candidate
|
|
49
|
+
dir's file mtimes, which move while the generator is WRITING (thinking
|
|
50
|
+
pauses are quiet — that is normal, not frozen) ("still
|
|
51
|
+
working — styles.css touched 20s ago"). Every history line carries an
|
|
52
|
+
`event`: `round-start` lands the moment a score BEGINS and has no
|
|
53
|
+
numbers — relay it as "round 3 scoring started", never as a result —
|
|
54
|
+
and `round-scored` carries that round's pass/total/floor/mean. So the
|
|
55
|
+
file appears with the first score's START; before that, its absence
|
|
56
|
+
means scoring has not begun yet, which early on is normal, not frozen.
|
|
57
|
+
A healthy run can take 30+ minutes; never kill on elapsed time
|
|
53
58
|
alone — count staleness from the LAST CHANGE to any signal, and when
|
|
54
59
|
past ~20 minutes of true staleness, ask the user before killing.
|
|
55
60
|
|
|
@@ -57,7 +62,9 @@ Before concluding "inherent limitation" on a stuck score: enumerate the
|
|
|
57
62
|
rendering inputs you have NOT verified — are the declared font faces
|
|
58
63
|
actually resolved (the kit's cached faces and weights vs what the CSS
|
|
59
64
|
asks for), computed styles vs authored styles, and
|
|
60
|
-
|
|
65
|
+
an `(lcd-text-enabled)` experiment mark in the environment stamp — and
|
|
66
|
+
check them first (platform AA itself is pinned greyscale in every
|
|
67
|
+
canonical mount). Run 13's "inherent
|
|
61
68
|
fidelity gap" was a missing font weight one check away; a stop rule is
|
|
62
69
|
for avoiding thrash, never for converting an unverified hypothesis into
|
|
63
70
|
a final answer.
|
package/dist/tendril-mcp.js
CHANGED
|
@@ -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 = {
|