@tendrilapp/cli 0.1.39 → 0.1.41

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/dist/SKILL.md CHANGED
@@ -7,8 +7,8 @@ description: MUST be used to implement, build, code up, recreate, or port a UI c
7
7
 
8
8
  Tendril's pipeline: RECORD the design's ground truth from Figma →
9
9
  GENERATE an implementation (you propose; Tendril's local ruler judges)
10
- → VERIFY with per-config scores and evidence images → publish to the
11
- user's Tendril portal.
10
+ → VERIFY with per-config scores and evidence images → HAND OVER the
11
+ bundle with its persisted report and evidence beside it.
12
12
 
13
13
  Non-negotiables (the CLI enforces these; do not fight them):
14
14
  - Only `tendril_engine_score` / `tendril verify` output counts as a
@@ -198,7 +198,10 @@ Batch runs (several components in one session):
198
198
  real faces is the only path to certification.
199
199
  3. Record each planned rep with FOUR tool calls: make the THREE
200
200
  Figma MCP calls in protocol order — get_metadata, then
201
- get_design_context (excludeScreenshot=true), then get_screenshot
201
+ get_design_context (excludeScreenshot=true), then get_screenshot
202
+ (ALWAYS with contentsOnly: true and maxDimension: 4096 — without
203
+ isolation the export bakes in the editor's component-set chrome,
204
+ which scores as ink no implementation can paint) —
202
205
  and then ONE `tendril_record_ingest_rep` carrying all three:
203
206
  metadata and context response text passed VERBATIM — responses
204
207
  often arrive as MULTIPLE output blocks (block counts vary BY
@@ -376,8 +379,24 @@ printed estimate.
376
379
  `tendril_verify` on any bundle directory recomputes everything —
377
380
  scores, behaviors, composition — and writes evidence images
378
381
  (render/ref/diff per config) next to the bundle. It is free and needs
379
- no account, always. Show the user the summary line and where the
380
- evidence lives.
382
+ no account, always.
383
+
384
+ It also PERSISTS its report to `verify-evidence/verify-report.json`,
385
+ with machine-specific paths stripped so the directory can be handed to
386
+ someone else as-is. Per config the report NAMES the evidence actually
387
+ on disk — or `null` where a scoring path produced a score with no
388
+ pixels, which is a real outcome and not a bug.
389
+
390
+ The verdict, the pixels and the diff-colour legend join into one offline
391
+ sheet at `verify-evidence/inspect.html`. That sheet comes from the CLI
392
+ and has no MCP tool of its own, so OFFER to run
393
+ `npx @tendrilapp/cli inspect <bundle-dir>` rather than asking the user
394
+ to type it, and say what it produces before you run it.
395
+
396
+ Point the user at that sheet, not at terminal scrollback: a verdict
397
+ nobody can re-read beside the evidence it describes cannot be handed to
398
+ anyone. Note the ORDER — `inspect` writes crops into the evidence
399
+ directory it documents, so run it after `verify`, never before.
381
400
 
382
401
  NEVER re-score a bundle against a DIFFERENT recording set than the one
383
402
  it is bound to — scoring rewrites the bundle's verification identity
@@ -88,10 +88,24 @@ var TOOLS = [
88
88
  {
89
89
  name: "tendril_doctor",
90
90
  annotations: { readOnlyHint: true },
91
- description: "Machine readiness + version status in one shot: installed vs latest version (with publish date and update remediation), browser identity, font-cache state, Figma desktop MCP reachability. Use to self-diagnose before recording/scoring, or whenever versions are in question. Exit 1 = something not ready; the report says exactly what and how to fix it.",
91
+ description: "Machine readiness + version status in one shot: installed vs latest version (with publish date and update remediation), browser identity, font-cache state, Figma desktop MCP reachability, and whether this machine holds a LIVE portal session (checked against the portal itself; informational \u2014 publishing needs it, verification never does; when absent, offer tendril_login). Use to self-diagnose before recording/scoring, or whenever versions are in question. Exit 1 = something not ready; the report says exactly what and how to fix it.",
92
92
  schema: z.object({}),
93
93
  argv: () => ["doctor"]
94
94
  },
95
+ {
96
+ name: "tendril_login",
97
+ description: "Connect this machine to the user's Tendril portal account WITHOUT the user touching a terminal \u2014 phase one of the browser-approve sign-in. Starts the handshake, opens their browser to the approve page, and returns a verification link plus a short code. RELAY BOTH to the user verbatim: they click Approve on the page, and they must check the page shows EXACTLY this code (that check is the phishing defence \u2014 an attacker can send someone else's approve link). Then call tendril_login_wait to finish. Offer this whenever tendril_doctor reports no portal session and the user wants to publish or share; publishing needs it, verification never does.",
98
+ schema: z.object({
99
+ portal: optStr("portal origin override for self-hosted portals (defaults to https://app.trytendril.com)")
100
+ }),
101
+ argv: (i) => ["login", "--device-start", ...typeof i["portal"] === "string" ? ["--to", i["portal"]] : []]
102
+ },
103
+ {
104
+ name: "tendril_login_wait",
105
+ description: "Phase two of the browser-approve sign-in: waits (up to ten minutes, with live progress) for the user to click Approve on the page tendril_login opened, then stores the session on this machine. Call it right after relaying the link and code. A denial, a lapse, and success each come back as their own sentence; confirm the result to the user, and on success they are ready to publish.",
106
+ schema: z.object({}),
107
+ argv: () => ["login", "--device-wait"]
108
+ },
95
109
  {
96
110
  name: "tendril_record_next",
97
111
  annotations: { readOnlyHint: true },
@@ -112,7 +126,7 @@ var TOOLS = [
112
126
  },
113
127
  {
114
128
  name: "tendril_record_ingest_rep",
115
- description: "Ingest a rep's ENTIRE recording in ONE call \u2014 the get_metadata response, the get_design_context response, and the get_screenshot image_url together. Make the three Figma calls first, in protocol order (get_metadata, then get_design_context with excludeScreenshot=true, then get_screenshot), then pass all three here VERBATIM. PREFER THIS over three separate ingest/fetch calls: one approvable operation per rep instead of three. Pieces land independently: on a partial failure the error names exactly which piece(s) to re-record \u2014 the rest are already on disk. The response carries `next` and, for design context, `assets` (auto-fetched server-side; only listed failures need record_asset).",
129
+ description: "Ingest a rep's ENTIRE recording in ONE call \u2014 the get_metadata response, the get_design_context response, and the get_screenshot image_url together. Make the three Figma calls first, in protocol order (get_metadata, then get_design_context with excludeScreenshot=true, then get_screenshot with contentsOnly=true and maxDimension=4096 \u2014 isolation keeps the editor's component-set chrome out of the padded export, where it would otherwise score as unpaintable reference ink), then pass all three here VERBATIM. PREFER THIS over three separate ingest/fetch calls: one approvable operation per rep instead of three. Pieces land independently: on a partial failure the error names exactly which piece(s) to re-record \u2014 the rest are already on disk. The response carries `next` and, for design context, `assets` (auto-fetched server-side; only listed failures need record_asset).",
116
130
  schema: z.object({
117
131
  setDir: str("recording set directory"),
118
132
  rep: str("planned rep slug"),