fenix-claude-plugin 0.1.3 → 0.2.0

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 (52) hide show
  1. package/.claude-plugin/plugin.json +13 -13
  2. package/.mcp.json +11 -11
  3. package/README.md +33 -40
  4. package/artifacts/collections.html +149 -0
  5. package/artifacts/fenix-workspace.html +1285 -0
  6. package/artifacts/oa-editor.html +210 -0
  7. package/artifacts/patent-editor.html +325 -0
  8. package/artifacts/review-workspace.html +1135 -0
  9. package/commands/fenix-install.md +19 -11
  10. package/commands/fenix-setup.md +18 -13
  11. package/package.json +16 -16
  12. package/skills/fenix-application/SKILL.md +35 -12
  13. package/skills/fenix-application/VERSION +1 -1
  14. package/skills/fenix-application/references/claim1-method-drafting.md +1 -1
  15. package/skills/fenix-application/references/claims.md +4 -5
  16. package/skills/fenix-application/references/disclosure.md +116 -10
  17. package/skills/fenix-application/references/editors.md +222 -51
  18. package/skills/fenix-application/references/figure-description.md +1 -1
  19. package/skills/fenix-application/references/figure-strategy.md +166 -0
  20. package/skills/fenix-application/references/figures-guidance.md +1 -1
  21. package/skills/fenix-application/references/figures.md +51 -14
  22. package/skills/fenix-application/references/patent-review-checklist.md +3 -1
  23. package/skills/fenix-application/references/patent-review.md +6 -2
  24. package/skills/fenix-application/references/patent-safe.md +1 -1
  25. package/skills/fenix-application/references/patent.md +9 -9
  26. package/skills/fenix-application/references/spec-guidance.md +1 -1
  27. package/skills/fenix-application/references/spec.md +17 -7
  28. package/skills/fenix-application/scripts/figure_strategy_server.py +136 -0
  29. package/skills/fenix-diagram/SKILL.md +54 -0
  30. package/skills/fenix-diagram/VERSION +1 -0
  31. package/skills/fenix-diagram/references/diagram-svg-guide.md +271 -0
  32. package/skills/fenix-office-action/SKILL.md +6 -4
  33. package/skills/fenix-office-action/VERSION +1 -1
  34. package/skills/fenix-office-action/references/oa-analysis.md +14 -4
  35. package/skills/fenix-office-action/references/oa-drafting.md +98 -21
  36. package/skills/fenix-office-action/references/oa-response.md +13 -13
  37. package/skills/fenix-project/SKILL.md +4 -3
  38. package/skills/fenix-project/VERSION +1 -1
  39. package/skills/fenix-project/references/create-project.md +11 -1
  40. package/artifacts/claims-editor.html +0 -205
  41. package/artifacts/figures-editor.html +0 -237
  42. package/artifacts/oa-arguments-editor.html +0 -216
  43. package/artifacts/practice-dashboard.html +0 -469
  44. package/artifacts/project-overview.html +0 -481
  45. package/artifacts/sections-editor.html +0 -205
  46. package/artifacts/user-dashboard.html +0 -368
  47. package/skills/fenix-application/CUSTOMIZE.md +0 -1
  48. package/skills/fenix-application/assets/claims_editor.html +0 -86
  49. package/skills/fenix-application/assets/figures_editor.html +0 -86
  50. package/skills/fenix-application/assets/spec_editor.html +0 -86
  51. package/skills/fenix-office-action/CUSTOMIZE.md +0 -1
  52. package/skills/fenix-project/CUSTOMIZE.md +0 -1
@@ -1,71 +1,242 @@
1
1
  # Editors — how to drive them
2
2
 
3
- **Version: 21**
3
+ **Version: 48**
4
4
 
5
- There are two ways to run the claims / figures / sections editors. **Prefer the live editors in Cowork**; use the clipboard editors elsewhere. **You never need to open or read any editor HTML** — everything you need is below.
5
+ The Fenix editors are **pages served by the MCP into one installed wrapper artifact**. They load and
6
+ save Fenix data themselves, so a full claim/figure/section/disclosure set never passes back through
7
+ chat — far faster and far cheaper in tokens.
6
8
 
7
- ## Live editors (preferred in Cowork)
9
+ There is **one** installed artifact, the Fenix workspace shell. It knows nothing about patents; it
10
+ fetches a page by address and runs it. New pages and new features never require a reinstall, because
11
+ the shell's grant is `{read, write}` and does not change.
8
12
 
9
- In a Cowork host, use the **self-saving live editor artifacts** instead of the clipboard editors. They load and save themselves, so the full claim/figure/section set never has to pass back through chat — far faster and far cheaper in tokens.
13
+ ## The one rule
10
14
 
11
- To open one:
12
- 1. Call `get_live_artifacts({ name: "claims-editor" })` (or `"figures-editor"`, `"sections-editor"`).
13
- 2. Take the returned `html` and substitute its two placeholders before writing it: `__PROJECT_ID__` → the target Fenix project id, and `__SERVER_PREFIX__` → your MCP connector's tool prefix (the part before the tool name in a fully-qualified tool id — e.g. if your tools appear as `mcp__abc123__get_project`, the prefix is `mcp__abc123__`; bare tool names do not resolve when the host namespaces MCP tools). Then write it to the returned `fileName` and open it as a live HTML artifact for the user.
14
- 3. That's it — the artifact loads the project's current claims/figures/sections itself (via `get_project`) and, on **Save**, writes them back itself (via `save_project`). **Do NOT pre-fill it, and do NOT call `save_project` for it yourself.**
15
+ **You never write, edit, or substitute anything into an artifact's HTML. Ever.**
15
16
 
16
- **When the user pastes a `[CLAIMS SAVED - claimsRev N]` block** (or `[FIGURES SAVED - figuresRev N]` / `[SECTIONS SAVED - sectionsRev N]`), the editor has **already saved to Fenix**:
17
- - **Do NOT call `save_project` again** — it is already persisted.
18
- - Update your working copy from the block: it gives the **full text of every changed/added** item, the **numbers of removed** items, and the **numbers left unchanged**. Apply that delta to the set you already had.
19
- - Note the rev (`claimsRev`/`figuresRev`/`sectionsRev`). `get_project` returns the current rev for each; if yours is behind, reload to re-sync.
17
+ Not a connector prefix, not a project id, not a docket number. This is not a style preference it is
18
+ a correctness rule with three independent reasons:
20
19
 
21
- If the host is **not** Cowork (no live artifacts, or the user can't run them), fall back to the clipboard editors below.
20
+ 1. **A remote push destroys grants.** Updating an installed MCP artifact from a chat session wipes
21
+ its connector grants *irreversibly*; recovering means a fresh desktop-side install. An edit you
22
+ make to "help" costs the user their working editor.
23
+ 2. **A baked-in prefix is wrong everywhere else.** Tool namespacing differs per host
24
+ (`mcp__Fenix__…` in a cloud session, `mcp__<connector-id>__…` on the desktop). A value correct in
25
+ your session resolves to nothing in theirs.
26
+ 3. **The shell already knows.** It discovers the prefix itself and asks the server which page to
27
+ open. Anything you inline is a stale duplicate of something it can look up.
22
28
 
23
- ## Clipboard editors (fallback non-Cowork hosts)
29
+ The single exception is the **courier** (below), whose entire purpose is to be rewritten.
24
30
 
25
- This skill also ships three accordion HTML editors in `assets/`. Open one with pre-filled data:
26
- 1. Take the editor file (`assets/<editor>.html`) as-is — do not parse it.
27
- 2. Replace the line `var INITIAL_CONTENT="";` with `var INITIAL_CONTENT=<JSON>;`, where `<JSON>` is the data for that editor in the shape below (a JSON string the editor will `JSON.parse`, or an inlined array/object — both work).
28
- 3. Save the working copy and open it for the user.
31
+ ## The two tools
29
32
 
30
- The header has an **Expand all / Collapse all** toggle; each row has **Remove**; there is an **+ Add** button. The user clicks **Copy for Save**, which copies a clipboard payload prefixed with `[EDITOR SUBMIT - <type>]`. The user pastes it back into chat; you strip the prefix line and call `save_project`.
33
+ This server has exactly two tools, `read` and `write`. Everything is a resource on one of them.
31
34
 
32
- ## claims_editor.html
33
- INITIAL_CONTENT = array of claim objects in the Fenix schema:
34
35
  ```
35
- [
36
- { "claimNumber": "1", "claimStatus": "original", "claimType": "independent",
37
- "claimText": ["A system comprising:", "a processor; and", "a memory."],
38
- "parent": "", "independentParent": "" },
39
- { "claimNumber": "2", "claimStatus": "original", "claimType": "dependent",
40
- "claimText": ["The system of claim 1, wherein the processor is multi-core."],
41
- "parent": "1", "independentParent": "1" }
42
- ]
36
+ read { resource, name?, options?, haveVersions?, haveRev?, noContextUpdate?, ops? }
37
+ write { resource, action?, options?, noContextUpdate?, ops? }
43
38
  ```
44
- - `claimText` is an array of lines (one entry per line of the claim body).
45
- Output: `[EDITOR SUBMIT - claims]` then a JSON array of the same schema. Strip the prefix; call `save_project({ type: "claims", claims: [...] })`.
46
39
 
47
- ## figures_editor.html
48
- INITIAL_CONTENT = array of figure objects:
40
+ **Batching.** Both take `ops: [...]` — an array of the same shape they take singly — and do the lot
41
+ in one call. Omit it for a single action. Reads in a batch run in parallel; writes run in order, and
42
+ one failing op does not stop the rest or discard the others' results. Every call pays the same fixed
43
+ cost (the host hop, authentication, a database connection) whatever it asks for, so two questions in
44
+ one call is close to half the cost of two calls. Batch by default when you know what you need:
45
+
46
+ ```
47
+ read { ops: [ {resource:"context"}, {resource:"project", options:{projectId, include:["claims"]}} ] }
48
+ ```
49
+
50
+ Call `read {resource:"schema"}` for the full directory of resources, actions and their parameters —
51
+ prefer that over guessing. `read {resource:"schema", name:"project"}` documents one.
52
+
53
+ The mappings you will use most:
54
+
55
+ | The tool that used to exist | Call instead |
56
+ |---|---|
57
+ | get&#95;context | `read {resource:"context"}` |
58
+ | set&#95;context | `write {resource:"context", options:{ids:{projectId}, label}}` |
59
+ | get&#95;project | `read {resource:"project", options:{projectId, include}}` |
60
+ | save&#95;project | `write {resource:"project", action:"save", options:{…}}` |
61
+ | get&#95;claim&#95;limitations | `read {resource:"claim-limitations", options:{projectId}}` |
62
+ | update&#95;claim&#95;limitation | `write {resource:"claim-limitation", options:{…}}` |
63
+ | list&#95;active&#95;projects | `read {resource:"projects"}` |
64
+ | get&#95;docket | `read {resource:"docket"}` |
65
+
66
+ Any tool not listed: `read {resource:"schema"}` names them all.
67
+
68
+ ## The working context — and what moves it
69
+
70
+ The working context is the record of what this person is working on. **The open Fenix workspace
71
+ follows it.** It polls every few seconds and, unless the user has switched `follow` off on its status
72
+ line, it *navigates* when the context moves. So moving the context is not bookkeeping — it changes
73
+ what is on the user's screen, within seconds, while they are looking at it.
74
+
75
+ Know which of your calls do that:
76
+
77
+ | Call | Moves the context? |
78
+ |---|---|
79
+ | `write {…}` — any resource, any action | **Yes.** Every write folds its object ids in. |
80
+ | `read {…}` — any resource | **No.** Reads never move it. |
81
+ | `read {resource:"page", name:"…/<id>"}` | **Yes** — arriving at an address *is* navigating. |
82
+ | `write {resource:"context", options:{ids:{projectId}}}` | **Yes** — that is its whole job. |
83
+ | anything with `noContextUpdate: true` | **No.** |
84
+
85
+ Reads used to move it too. They no longer do, so context tracks what is being **worked on** rather
86
+ than what was last **looked at** — reading fifty matters to answer a question no longer drags the
87
+ user's workspace across all fifty.
88
+
89
+ **Turning it off.** `noContextUpdate: true` suppresses the move. Put it on a single call, or on the
90
+ envelope of a batch where it applies to every op unless an op says otherwise:
91
+
92
+ ```
93
+ write { noContextUpdate: true, ops: [ … ] } // a sweep: change data, leave the user alone
94
+ ```
95
+
96
+ Use it whenever the work is not the user's attention: automations, migrations, background
97
+ housekeeping, or any loop over many matters. A 3am feed sweep is not navigation.
98
+
99
+ Conversely, when you **do** want the user taken somewhere, say so deliberately with
100
+ `write {resource:"context", options:{ids:{projectId}, label:"<matter number>"}}` rather than relying
101
+ on a side effect of some other write.
102
+
103
+ **Reading it cheaply.** `read {resource:"context"}` returns `{session, sessions, rev, url}`. Pass
104
+ `haveRev` with the `rev` you last saw and an unchanged context answers `{notModified:true, rev}` with
105
+ no payload — that is how the workspace polls every few seconds without cost. `url` is the website
106
+ address the context points at.
107
+
108
+ ## Opening an editor
109
+
110
+ 1. **Bind the matter first:** `write {resource:"context", options:{ids:{projectId}, label:"<matter
111
+ number>"}}`. The shell reads context on load and opens on whatever you bound. This replaces the
112
+ old `__DOCKET__` substitution.
113
+ 2. **Tell the user to open the installed Fenix workspace** from the artifacts sidebar. If they don't
114
+ have it, they install it once from a **desktop-side** session — remote `create_artifact` /
115
+ `update_artifact` never populate the tool allowlist, so a chat-installed MCP artifact cannot call
116
+ tools no matter how it is built.
117
+
118
+ **If the workspace is already open, step 2 happens by itself.** It follows the context, so binding
119
+ the matter moves it there within a few seconds — no reload, and nothing to ask them to click. Say
120
+ what you have opened rather than telling them to go and open it. (Only if they have switched `follow`
121
+ off does it wait, showing an "open →" offer instead.)
122
+
123
+ To switch matters, write the context again — the open workspace follows. Do not push a new copy.
124
+
125
+ **Writing the file, when you do install one.** The html is large, so the fetch that returns it is
126
+ usually persisted to a **file** rather than shown in the conversation. Read the bytes from that file
127
+ and write them out programmatically. Never hand-transcribe an artifact, and never reconstruct one
128
+ from what you can see of it — it must be byte-exact. A copy that is subtly wrong fails at runtime in
129
+ ways that look like a Fenix bug: a truncated script, a mangled escape, a meta block that no longer
130
+ parses and therefore grants nothing. If it comes back inline instead, write it through verbatim; if
131
+ it looks truncated, fetch it again rather than filling the gap.
132
+
133
+ **There is no grant prompt.** Nothing appears on first open and nothing is waiting to be approved. If
134
+ you tell a user to expect one, they will sit waiting for a dialog that does not exist instead of
135
+ reporting the code that says what is actually wrong. A copy with no permissions is FX02 — a
136
+ desktop-side reinstall — not a prompt someone missed.
137
+
138
+ ## Addressing a page
139
+
140
+ Pages are addressed the way the website addresses them, and **the id is always last**:
141
+
49
142
  ```
50
- [
51
- { "number": "1", "type": "Flowchart", "briefDescription": "...",
52
- "steps": [ { "number": "100", "label": "receive", "text": "receiving a request" } ], "components": [] },
53
- { "number": "2", "type": "Device", "briefDescription": "...",
54
- "steps": [], "components": [ { "number": "200", "label": "processor", "text": "a processor" } ] }
55
- ]
143
+ tools/patent/claims/<projectId>
144
+ tools/oa/arguments/<projectId>
145
+ collections/projects (the list)
146
+ collections/projects/<id> (one matter)
147
+ collections/deadlines
148
+ dashboards/home
56
149
  ```
57
- - `type` is "Flowchart" | "Device" | "Placeholder".
58
- - Flowchart figures use `steps`; Device figures use `components`. Each row is `{ number, label, text }`.
59
- - There is no per-figure introductory-sentence field. The figure's introductory/opening sentence is generated from its `briefDescription` during spec drafting — do not collect or pass it.
60
- Output: `[EDITOR SUBMIT - figures]` then a JSON array of figure objects. Strip the prefix; call `save_project({ type: "figures", figures: [...] })`.
61
150
 
62
- ## spec_editor.html
63
- INITIAL_CONTENT = a sections object: key = section name, value = `{ "paragraphs": string[] }`. Each figure description is its own section (e.g. "FIG. 1").
151
+ Opening an address that carries an id also **moves the working context to it** — arriving somewhere
152
+ is the same event as navigating there. So handing the user a full address is an alternative to
153
+ writing context first, not a step after it.
154
+
155
+ ## The patent editor
156
+
157
+ One page family, four views — **Disclosure, Claims, Figures, Specification** — matching the website's
158
+ tabs, reached as `tools/patent/<view>/<projectId>`. It saves per group with revision checks, so it
159
+ will not silently overwrite work done elsewhere, and it polls for changes: if the user is mid-edit it
160
+ tells them rather than replacing what they typed.
161
+
162
+ It is deliberately simpler than the website. It does **not** do feature/limitation linking, component
163
+ association, claim-type conversion, or DOCX import. Those stay on the web tool, and where the user
164
+ needs them, that is what you tell them to open. What the editor does not model, **you** do through
165
+ the tools: `read {resource:"claim-limitations"}` and `write {resource:"claim-limitation"}` address
166
+ limitations by `N.i` and handle links, `modifies`, and match confirmation.
167
+
168
+ ### Disclosure view
169
+
170
+ You build the document first, then open the editor on it. Read every disclosure document the user
171
+ gave you, split them into paragraphs, and for each write the patent-adapted wording and choose the
172
+ section it belongs in. Save with `write {resource:"project", action:"save", options:{type:
173
+ "disclosure", disclosure}}`, then have them open the editor to revise. Item shape (one per
174
+ paragraph):
175
+
176
+ ```json
177
+ { "_localId": "d1", "type": "text",
178
+ "originalText": "verbatim paragraph from the source document",
179
+ "text": "the same content, adapted to patent language",
180
+ "insertedInSection": "Background",
181
+ "source": "Disclosure.docx" }
64
182
  ```
65
- {
66
- "Field of the Invention": { "paragraphs": ["<p>The present disclosure relates to ...</p>"] },
67
- "FIG. 1": { "paragraphs": ["<p>FIG. 1 illustrates ...</p>", "<p>In block 100, ...</p>"] }
68
- }
183
+
184
+ ⚠️ **There are two different "disclosures", and only one of them reaches the patent.**
185
+ A project save with `type: "disclosure"` writes the item array to the **patent** record — this is the
186
+ one the Disclosure view reads and the one whose text flows into the spec sections. The bare
187
+ project-level `disclosure` field (a save with **no** `type`) writes to the **project** record, which
188
+ the Disclosure view never reads. Passing the disclosure that way looks like it worked and changes
189
+ nothing the user can see. Always pass `type: "disclosure"`.
190
+
191
+ - **`insertedInSection` IS the include flag.** A section name means the paragraph flows into that
192
+ spec section; `""` means the item is kept on the record but excluded from the patent.
193
+ - **A save REPLACES the whole array.** The editor carries non-text items (images, stencils) through
194
+ untouched — if you save the disclosure yourself, do the same, or you will delete them.
195
+ - Load it back with `read {resource:"project", options:{projectId, include:["disclosure"]}}`.
196
+ - When the user pastes a `[DISCLOSURE SAVED - disclosureRev N]` block, it is **already saved** — do
197
+ not call the save again; just apply the delta to your working copy.
198
+
199
+ ## The courier — the one artifact you may rewrite
200
+
201
+ A ~1KB, grant-free artifact (`mcpTools: []`) whose only job is to carry a value into the device's
202
+ shared artifact storage. Because it holds no grants, re-pushing it costs nothing — which is exactly
203
+ why it, and never an editor, is the thing that gets rewritten.
204
+
205
+ Its source contains a single `PAYLOAD` block. Rewrite that, push it, and have the user **open it** —
206
+ delivery happens on page load, not on push. Its on-screen "payload #N written" line is the check.
207
+
208
+ ```js
209
+ const PAYLOAD = {
210
+ seq: 2, // MUST change every push — receivers dedup on it
211
+ prefix: null, // connector prefix; null = leave alone
212
+ banner: null,
213
+ matterNum: null,
214
+ projectId: null
215
+ };
69
216
  ```
70
- - In the editor, a blank line separates paragraphs; on submit each paragraph is wrapped in `<p>...</p>`.
71
- Output: `[EDITOR SUBMIT - sections]` then a JSON sections object. Strip the prefix; call `save_project({ type: "sections", sections: {...} })`.
217
+
218
+ Rules: change `seq` every time; a field left `null` is not written, so a payload never clobbers what
219
+ it doesn't name; keep payloads small (the storage quota is shared by every artifact); put no secrets
220
+ in it (every installed artifact can read the same origin).
221
+
222
+ In normal operation the courier is **not needed** — the shell discovers the connector prefix itself
223
+ and caches it for the whole fleet. It earns its keep in one situation: the connector was re-added, so
224
+ every cached and hinted prefix is stale. See FX04 below.
225
+
226
+ ## When the user says it isn't working
227
+
228
+ The shell self-diagnoses and shows a code. Ask for the code — it is five characters and the user can
229
+ read it off the screen. There is also a **Copy details** button that puts the full diagnostic on
230
+ their clipboard; ask for that when the code alone isn't enough.
231
+
232
+ | Code | Meaning | What to do |
233
+ |---|---|---|
234
+ | **FX01** | Not a live artifact — a file preview or chat chip | Have them open the artifact from the sidebar |
235
+ | **FX02** | Never fully installed (no tool allowlist) | Needs a one-time **desktop-side** install |
236
+ | **FX03** | Self-healed after a connector change | Nothing — informational |
237
+ | **FX04** | Connector lost or re-added; no valid prefix anywhere | Send a courier carrying the new `prefix`, or have them paste it into the courier's manual field |
238
+ | **FX05** | Fenix server or data error | Read the message in the strip; a back-end problem, not a wiring one |
239
+
240
+ Never respond to any of these by editing the artifact's HTML. Never retry name variants either —
241
+ if the allowlist is empty, no spelling of a tool name will resolve. FX02 and FX04 are
242
+ install/connector problems; the others are not wiring problems at all.
@@ -1,6 +1,6 @@
1
1
  # Figure Description Protocol
2
2
 
3
- **Version: 21**
3
+ **Version: 48**
4
4
 
5
5
  You are a patent drafting assistant. Your task is to write a detailed textual description of a figure (e.g., FIG. 1) for inclusion in the Detailed Description section of a patent application.
6
6
 
@@ -0,0 +1,166 @@
1
+ # Figure Strategy — the interactive strategy document
2
+
3
+ **Version: 48**
4
+
5
+ A **figure strategy** is a one-page, editable worksheet you build BEFORE drafting figures. The user
6
+ sees every proposed figure at a glance — a picture of what it will look like, what it shows, and its
7
+ components — and edits it directly. You then read their edits back and turn the result into the
8
+ figure set.
9
+
10
+ Use it when the user wants to plan the figures collaboratively, when there are **source documents**
11
+ (a disclosure, related applications, prior specs) to draw from, or when they ask for a "figure
12
+ strategy". It replaces guessing the figure list and reading it out in chat.
13
+
14
+ This is a **planning** artifact. It is not a Fenix entity: it is not saved by `write {resource:"project", action:"save"}` and has
15
+ no rev. It ends by producing the figures array that Phase 1 of `references/figures.md` saves.
16
+
17
+ ---
18
+
19
+ ## ⚠️ Read-back: a browser CANNOT write to the HTML file it loaded
20
+
21
+ **The trap:** you write `figure-strategy.html` to the sandbox, the user opens it, types into it — and
22
+ you re-read the file and see **your original markup**. Their edits are in the browser's memory, not
23
+ on disk. A page loaded from `file://` has no way to write back to itself. If you assume otherwise you
24
+ will silently draft from the wrong plan and the user will not know why.
25
+
26
+ So the page **must be given a way to hand its state back**. Pick the first option that fits the host:
27
+
28
+ ### A. Cowork — the artifact talks to Fenix itself (preferred there)
29
+ In Cowork, `window.cowork` is available and live artifacts call MCP tools directly. Follow
30
+ `references/editors.md`. The figure strategy has no Fenix entity of its own, so once the user is
31
+ happy, have the page emit the finished figures and let the normal figures flow save them — or just
32
+ have the user paste the summary block the page prints.
33
+
34
+ ### B. Local sandbox — serve it and POST the state back (use this for a local HTML file)
35
+ This is the pattern that makes "the assistant can read anything the user entered" actually true.
36
+
37
+ 1. Write `figure-strategy.html` and `figure-strategy.json` (the initial state) into the sandbox.
38
+ 2. Run the bundled server: `python3 scripts/figure_strategy_server.py --dir <that dir> [--port 8765]`
39
+ 3. Give the user the URL it prints (`http://127.0.0.1:8765/`). **Do not tell them to open the
40
+ `.html` file directly** — opened as `file://` the save round-trip cannot work.
41
+ 4. The page **autosaves on every edit** (debounced): it `POST`s its whole state to `/save`, and the
42
+ server writes it to `figure-strategy.json`.
43
+ 5. You then **read `figure-strategy.json`** whenever you want the user's current plan. That file —
44
+ never the HTML — is the source of truth.
45
+
46
+ Re-read the JSON right before you act on it. The user may have kept editing while you were talking.
47
+
48
+ ### C. No server available — export or paste (fallback)
49
+ Give the page a **Copy JSON** button (writes the state to the clipboard) and an **Export JSON**
50
+ button (`Blob` + `<a download>`, which works even on `file://`). The user pastes the JSON into chat,
51
+ or tells you where the download landed (usually `~/Downloads/figure-strategy.json`) and you read it.
52
+ Higher friction and it costs tokens, so prefer B.
53
+
54
+ **Do not rely on the File System Access API** (`showSaveFilePicker`). It is Chromium-only and needs a
55
+ secure context — it does not work from a `file://` page. It *does* work when the page is served over
56
+ localhost, but then option B is already available and is simpler and browser-agnostic.
57
+
58
+ ---
59
+
60
+ ## Layout — three columns, near-full width
61
+
62
+ One row per proposed figure. Size the table to a standard screen: `width: 100%` with a
63
+ `max-width: 1600px`, and let column 3 take the slack. Keep rows aligned to a grid so the eye can scan
64
+ down a column.
65
+
66
+ | # | Column | Width | Contents |
67
+ |---|--------|-------|----------|
68
+ | 1 | **Icon / image** | ~240–320px, fixed | The visual: a snapshot cropped from a source document, or a generated SVG preview. Fixed width so every row's art lines up. |
69
+ | 2 | **Description** | ~28–32% | An **editable text field** (`<textarea>`) — a short description of what this figure shows about the invention. 1–3 sentences. This becomes the figure's `briefDescription`. |
70
+ | 3 | **Components** | remaining (widest) | An **editable list** of the figure's components/steps. Add / remove / reorder rows. Each row is a label plus optional text. Numbers are NOT edited here — they are derived (see Numbering). |
71
+
72
+ Also per row: the figure **type** (`Flowchart` / `Device` / `Placeholder`) and a control to
73
+ **add, remove and reorder** whole figures. Reordering is the whole point of the exercise — make it
74
+ easy.
75
+
76
+ Every editable control writes into the state object and triggers the debounced autosave. If an edit
77
+ cannot reach `figure-strategy.json`, the document is decorative and you have lost the user's work.
78
+
79
+ ---
80
+
81
+ ## Source documents and previews
82
+
83
+ The user may bring **several** sources — the disclosure, related applications, an earlier spec. Ask
84
+ for all of them up front, and record which source each proposed figure came from (show it as a
85
+ caption under the icon, and keep it in the state as `source`). It tells the user *why* a figure is
86
+ being proposed, and tells you where to go back for detail.
87
+
88
+ ### Start from the figures the sources ALREADY have
89
+
90
+ **Before you propose a single new figure, scan every source document for figures that already
91
+ exist** — block diagrams, architecture diagrams, schematics, flowcharts, plots, graphs. The
92
+ inventor has usually already drawn the invention; proposing a fresh figure set while ignoring their
93
+ drawings is how a strategy worksheet ends up describing a different invention from the disclosure.
94
+
95
+ Every existing figure becomes a worksheet row, before any new ones:
96
+
97
+ - **Preview** — a snapshot crop of the actual drawing, embedded as a `data:` URI.
98
+ - **Provenance** — say exactly where it came from, e.g. "Figure 1 of the disclosure", "FIG. 3 of
99
+ US 11,123,456". Put it in the caption and in the state's `source`.
100
+ - **Type** — a diagram-type source (block diagram, architecture, schematic) becomes a **Device** or
101
+ **Flowchart** row whose components/steps **mirror the blocks in the source figure**: take the
102
+ labels off the drawing rather than inventing your own. A data graph or plot (a results chart, a
103
+ loss curve) becomes a **Placeholder** row flagged as **custom art** — it cannot be generated by
104
+ the Visio renderer and needs a draftsperson.
105
+
106
+ Only once every source figure is on the worksheet do you add the new ones — claim flowcharts, the
107
+ apparatus/system diagram, and any figure the claims need but the disclosure lacks.
108
+
109
+ Column 1's visual comes from one of two places:
110
+
111
+ - **Snapshot** — a crop of an actual drawing from a source document (a figure from a related
112
+ application, a whiteboard photo in the disclosure). Embed it as a `data:` URI so the HTML stays
113
+ self-contained and survives being moved.
114
+ - **Dynamic SVG** — for a figure that does not exist yet, generate a preview in the Fenix drawing
115
+ style. Follow `references/diagram-svg-guide.md` in the **fenix-diagram** skill (square-cornered
116
+ steps, rounded input/output boxes, filled arrows, S-curve lead lines, reference numerals). Inline
117
+ the SVG so it scales cleanly and can be regenerated when the components change.
118
+
119
+ A preview is a sketch, not the final drawing. Say so on the page. The real drawing comes from
120
+ `read {resource:"patent-document", options:{type:"drawings"}}` after the figures are saved.
121
+
122
+ ---
123
+
124
+ ## State shape (what the page reads and writes)
125
+
126
+ Keep it flat and close to the Fenix figure shape so the handoff is mechanical:
127
+
128
+ ```json
129
+ {
130
+ "matter": "8828-700",
131
+ "sources": [{ "id": "disc", "name": "Disclosure.docx" }],
132
+ "figures": [
133
+ {
134
+ "id": "f1",
135
+ "type": "Device",
136
+ "source": "disc",
137
+ "preview": { "kind": "svg", "content": "<svg .../>" },
138
+ "description": "The overall media generation system and its major components.",
139
+ "components": [{ "label": "processor", "text": "execute the instructions" }]
140
+ }
141
+ ]
142
+ }
143
+ ```
144
+
145
+ `preview.kind` is `"svg"` or `"image"` (a `data:` URI). Do not put figure or element **numbers** in
146
+ this file — they are derived on the way out, and holding stale numbers here invites the renumbering
147
+ bugs the figures workflow exists to prevent.
148
+
149
+ ---
150
+
151
+ ## Handing off to the figures workflow
152
+
153
+ When the user is done:
154
+
155
+ 1. **Re-read `figure-strategy.json`** — do not use the copy you had in context.
156
+ 2. Confirm the final list with them — **END TURN** — do not skip this.
157
+ 3. Convert each entry to a figure object: `description` → `briefDescription`; `components` →
158
+ `components` (type `Device`) or `steps` (type `Flowchart`). Content MUST go under `steps` or
159
+ `components`, never a generic `elements` list, or the figure prints as a blank page (see
160
+ `references/figures.md`, "Figure object shape").
161
+ 4. **Number everything now**, in final order: figures sequential and gap-free; each element derived
162
+ from its figure's number (flowchart `N00, N05, ...`; device `N05, N10, ...`). This is the
163
+ Renumbering invariant — the strategy document deliberately carries no numbers, so apply them here.
164
+ 5. `write {resource:"project", action:"save", options:{type: "figures", figures: allFigures}}` — include **every** figure, existing and
165
+ new.
166
+ 6. Continue at Phase 2 of `references/figures.md` to fill in each figure's content.
@@ -1,6 +1,6 @@
1
1
  # Figures Guidance
2
2
 
3
- **Version: 21**
3
+ **Version: 48**
4
4
 
5
5
  ## Figure List
6
6
 
@@ -1,44 +1,81 @@
1
1
  # Figures Workflow
2
2
 
3
- **Version: 21**
3
+ **Version: 48**
4
4
 
5
5
  ## ⚠️ Renumbering invariant (applies at EVERY point in the process)
6
- Figures are numbered **sequentially with no gaps** (FIG. 1, 2, 3, ...), and **every element number is derived from its figure's number** -- flowchart steps `N00, N05, N10, ...` and device components `N05, N10, ...`, where `N` is the figure number (see `## Numbering` and `references/figures-guidance.md`).
6
+ Figures are numbered **sequentially with no gaps** (FIG. 1, 2, 3, ...), and **every element number is derived from its figure's number** -- flowchart steps and device components alike run `N05, N10, N15, ...`, where `N` is the figure number. `N00` is NOT an element: it is the figure's own numeral ("the system 100"), so nothing starts at `N00` (see `## Numbering`).
7
7
 
8
8
  **So ANY time the figure set changes -- a figure is ADDED, REMOVED, reordered, or template figures are IMPORTED (at intake, in Phase 1, in Phase 2, or via the editor) -- you MUST renumber BEFORE saving:**
9
9
  1. Renumber the **figures** so they remain sequential and gap-free.
10
- 2. Renumber **every affected figure's steps/components** to match its new figure number -- e.g. if FIG. 2 becomes FIG. 3, its `205, 210, ...` components become `305, 310, ...`.
10
+ 2. Renumber **every affected figure's steps/components** to match its new figure number -- e.g. if FIG. 2 becomes FIG. 3, its `205, 210, ...` components become `305, 310, ...`. Change ONLY the figure-number prefix; **keep each element's two-digit suffix exactly as it was** (`220` -> `320`, never `315`). The suffix is what the drawing draws, so re-sequencing it to close a gap breaks the match with the artwork.
11
11
 
12
12
  Never leave a figure or an element number out of sync with its figure's position. **Importing template figures is the most common trap** -- the template's figure and element numbers will not line up with your set, so renumber them in. This is not optional and not only an end-of-phase step: renumber the moment the set changes, every time.
13
13
 
14
14
  ## Phase 1 -- List
15
- 0. **Ask up front how the user wants to start the figure list** -- e.g. "Want to start the figures from a template, from a figure-strategy document you have, or draft them from scratch?" Three options:
16
- - **From a template:** `list_patent_templates` -> let the user pick -> import with `save_project({ templateId })` so the template's figures become the starting set, **then renumber the imported figures and all their steps/components into your set** (see the Renumbering invariant -- template numbers will not match). (Skip this option if a template/source was already imported during intake.)
17
- - **From a figure strategy document:** if the user has a document describing the intended figures (which figures, what each illustrates, key steps/components), ask them to provide or upload it, then read it and use it to build the figure list (interpret it against `references/figures-guidance.md`).
15
+ 0. **Ask up front how the user wants to start the figure list** -- e.g. "Want to start the figures from a template, plan them together in a figure-strategy worksheet, from a figure-strategy document you already have, or draft them from scratch?" Four options:
16
+ - **From a template:** `read {resource:"patent-templates"}` -> let the user pick -> import with `write {resource:"project", action:"save", options:{templateId}}` so the template's figures become the starting set, **then renumber the imported figures and all their steps/components into your set** (see the Renumbering invariant -- template numbers will not match). (Skip this option if a template/source was already imported during intake.)
17
+ - **Build a figure-strategy worksheet (recommended when there are source documents):** an editable
18
+ 3-column HTML worksheet -- a preview image/SVG of each proposed figure, a short description, and
19
+ an editable component list -- built from the user's disclosure and any related applications. The
20
+ user edits it directly and you read their edits back. Read `references/figure-strategy.md` and
21
+ follow it; it hands you the figure list, then continue from step 1.
22
+ **A `file://` page cannot save itself** -- serve it with `scripts/figure_strategy_server.py` and
23
+ read `figure-strategy.json`, or the user's edits are invisible to you.
24
+ - **From a figure strategy document:** if the user already has a document describing the intended figures (which figures, what each illustrates, key steps/components), ask them to provide or upload it, then read it and use it to build the figure list (interpret it against `references/figures-guidance.md`).
18
25
  - **From scratch:** plan the figure list from the disclosure.
19
26
  Then continue from step 1.
20
- 1. `get_project({ projectId, include: ["figures"] })` -- note ALL figures including Placeholders
27
+ 1. `read {resource:"project", options:{projectId, include: ["figures"]}}` -- note ALL figures including Placeholders
21
28
  2. Use `references/figures-guidance.md` for figure list planning
22
29
  3. Number new figures from max(existing)+1
23
30
  4. Show ALL figures -- **END TURN** -- confirm
24
- 5. `save_project({ type: "figures", figures: allFigures })` -- never omit existing figures
31
+ 5. `write {resource:"project", action:"save", options:{type: "figures", figures: allFigures}}` -- never omit existing figures
25
32
 
26
33
  ## Phase 2 -- Content (one figure at a time)
27
34
  Skip Placeholders (type="Placeholder" or empty steps/components).
28
35
  For each: read `references/figures-guidance.md` -> generate -> show -- **END TURN** -> confirm, then move to the next figure.
29
- **Do NOT save after each figure** -- it is slow. Accumulate the confirmed figures and **save the whole set once** at the end of the pass with `save_project({ type: "figures", figures: allFigures })` (include every figure, existing + new).
36
+ **Do NOT save after each figure** -- it is slow. Accumulate the confirmed figures and **save the whole set once** at the end of the pass with `write {resource:"project", action:"save", options:{type: "figures", figures: allFigures}}` (include every figure, existing + new).
37
+
38
+ ## Figure object shape (get this right or the figure renders BLANK)
39
+ The Visio renderer reads a figure's content from the **`steps`** array (flowcharts) or the **`components`** array (device diagrams) — **not** a generic `elements` list. Content put under any other key renders as a blank page.
40
+ - **Flowchart** → `type: "Flowchart"`, content in `steps`.
41
+ - **Device / component diagram** → `type: "Device"`, content in `components`.
42
+ - Element shape (both): `{ "number", "label", "text", "type": "step" | "component" }`.
43
+ - Valid figure `type` values: `Flowchart`, `Device`, `Placeholder`. **There is no `"Diagram"` type** — it renders nothing.
44
+
45
+ ```json
46
+ { "number": "13", "type": "Flowchart", "briefDescription": "...",
47
+ "steps": [ { "number": "1305", "label": "receive", "text": "receiving the message", "type": "step" } ], "components": [] }
48
+ { "number": "15", "type": "Device", "briefDescription": "...",
49
+ "steps": [], "components": [ { "number": "1505", "label": "receiver", "text": "a receiver", "type": "component" } ] }
50
+ ```
51
+
52
+ **Verify before printing:** run `calculate_figure_layout.py` — every flowchart must show a non-empty `steps` list and every device `componentCount > 0`. An empty `steps: []` / `components: []` in the layout output means the content is under the wrong key and the figure will print blank.
30
53
 
31
54
  ## Numbering
32
- - Flowchart steps: 100, 105, 110...
33
- - Device components: figureNum05, figureNum10... (never figureNum00)
55
+
56
+ A reference numeral is `<figure number><two-digit suffix>`. The suffix is the element's identity;
57
+ the figure number is just a prefix.
58
+
59
+ - Flowchart steps: `N05, N10, N15, ...`
60
+ - Device components: `N05, N10, N15, ...`
61
+ - **`N00` is never an element.** It is the FIGURE's own numeral -- the thing the figure as a whole is
62
+ called ("the system 100", "the method 400"). Numbering a step `100` collides with it: the spec
63
+ then uses one numeral for two different things, and the drawing labels the wrong shape. Both step
64
+ and component numbering start at `N05`.
34
65
  - Every element needs `type`: "step" or "component"
35
66
 
67
+ **The suffix is permanent.** When a figure moves -- FIG. 2 becomes FIG. 3 -- only the PREFIX
68
+ changes: `205, 210, 220` becomes `305, 310, 320`. Do not renumber the suffixes into a tidy
69
+ sequence. They are what the drawing draws (each shape in the Visio stencil carries its own fixed
70
+ suffix), so closing a gap in the spec silently breaks the correspondence with the artwork. Gaps are
71
+ normal and are often deliberate.
72
+
36
73
  ## ElementSchema
37
74
  `{ type, label, number, text, name, action, angle, flipX, flipY }`
38
75
 
39
76
  ## Editor (accordion)
40
- **Always ask the user whether they want to open the figures editor to review/edit all figures at once** -- e.g. "Want me to open the figures editor so you can review them all together?" Only open it if they say yes. **In Cowork, prefer the live figures editor:** `get_live_artifacts({ name: "figures-editor" })`, substitute `__PROJECT_ID__` (project id) and `__SERVER_PREFIX__` (your MCP tool prefix, e.g. `mcp__<id>__` see `references/editors.md`) in the returned HTML, and open it it loads the current figures and **saves them itself**; when the user pastes a `[FIGURES SAVED - figuresRev N]` block, apply that delta and do **not** call `save_project` again (see `references/editors.md`). **Otherwise (non-Cowork), open `assets/figures_editor.html`** with `INITIAL_CONTENT` set to the full figures JSON array. Each figure is a collapsible accordion item; opening one reveals its number, type, brief description, and a steps/components table with add/remove rows. There is no introductory-sentence field -- the figure's introductory/opening sentence is generated from its brief description during spec drafting. The user can also add/remove whole figures -- **after any add/remove, renumber the figures and their steps/components** (see the Renumbering invariant) before saving. On `[EDITOR SUBMIT - figures]`, strip the prefix and call `save_project({ type: "figures", figures: [...] })` with the returned array.
77
+ **Always ask the user whether they want to open the figures editor to review/edit all figures at once** -- e.g. "Want me to open the figures editor so you can review them all together?" Only open it if they say yes. To open it: call `write {resource:"context", options:{ids: { projectId }, label: "<matter number>"}}` to bind the matter, then tell the user to open the **installed Fenix Patent Editor** (Figures view) from their artifacts sidebar. **Never write, edit, or substitute anything into the artifact**; see `references/editors.md`. When the user pastes a `[FIGURES SAVED - figuresRev N]` block, apply that delta and do **not** call `write {resource:"project", action:"save"}` again. The editor has no introductory-sentence field -- the figure's introductory/opening sentence is generated from its brief description during spec drafting. **After any add/remove of whole figures, renumber the figures and their steps/components** (see the Renumbering invariant) before they are saved.
41
78
 
42
79
  ## After all figures
43
- Run `scripts/calculate_figure_layout.py` with the figures JSON -> check `warnings` array and `readyToPrint` flag. **Do NOT print automatically.** Only call `print_patent(type=drawings)` if the user explicitly asks for the drawings file. After figures are saved and the layout is clean, simply tell the user the figures are ready and ask whether they want the drawings file generated.
44
- **When you do run `print_patent(type=drawings)`, always show the user the returned download URL/link in your reply** -- do not run the print silently. Surface the link (e.g. "Drawings ready: <url>") so they can open it.
80
+ Run `scripts/calculate_figure_layout.py` with the figures JSON -> check `warnings` array and `readyToPrint` flag. **Do NOT print automatically.** Only call `read {resource:"patent-document", options:{type:"drawings"}}` if the user explicitly asks for the drawings file. After figures are saved and the layout is clean, simply tell the user the figures are ready and ask whether they want the drawings file generated.
81
+ **When you do run `read {resource:"patent-document", options:{type:"drawings"}}`, always show the user the returned download URL/link in your reply** -- do not run the print silently. Surface the link (e.g. "Drawings ready: <url>") so they can open it.
@@ -1,4 +1,4 @@
1
- # Pre-Filing Checklist (16 items)
1
+ # Pre-Filing Checklist (18 items)
2
2
 
3
3
  | # | Check | Notes |
4
4
  | --- | --- | --- |
@@ -18,6 +18,8 @@
18
18
  | 14 | Reference numerals consistent | Same numeral = same element. No orphans. |
19
19
  | 15 | Cross-reference to provisional/foreign priority | For rewrites. |
20
20
  | 16 | Equations correct and formatted | Check against disclosure documents. |
21
+ | 17 | Fonts standard and embeddable | Flag any non-standard / web font (e.g. Google Sans, Roboto). The USPTO requires legible standard fonts (Times New Roman, Arial, Courier) fully embedded in the PDF -- MPEP 608.01 / 37 CFR 1.52(b). Non-standard or non-embedded fonts are rejected at Patent Center upload or draw a Notice to File Corrected Application Papers. |
22
+ | 18 | Figure components set to generate | Every component of a **non-boilerplate** figure has `generateElement: true` (else it gets no Visio box and no description text -- it is treated as background/boilerplate). Boilerplate figures leave it off. Include `figures` in `read {resource:"project"}` to inspect components. |
21
23
 
22
24
  ## General Issues
23
25