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.
- package/.claude-plugin/plugin.json +13 -13
- package/.mcp.json +11 -11
- package/README.md +33 -40
- package/artifacts/collections.html +149 -0
- package/artifacts/fenix-workspace.html +1285 -0
- package/artifacts/oa-editor.html +210 -0
- package/artifacts/patent-editor.html +325 -0
- package/artifacts/review-workspace.html +1135 -0
- package/commands/fenix-install.md +19 -11
- package/commands/fenix-setup.md +18 -13
- package/package.json +16 -16
- package/skills/fenix-application/SKILL.md +35 -12
- package/skills/fenix-application/VERSION +1 -1
- package/skills/fenix-application/references/claim1-method-drafting.md +1 -1
- package/skills/fenix-application/references/claims.md +4 -5
- package/skills/fenix-application/references/disclosure.md +116 -10
- package/skills/fenix-application/references/editors.md +222 -51
- package/skills/fenix-application/references/figure-description.md +1 -1
- package/skills/fenix-application/references/figure-strategy.md +166 -0
- package/skills/fenix-application/references/figures-guidance.md +1 -1
- package/skills/fenix-application/references/figures.md +51 -14
- package/skills/fenix-application/references/patent-review-checklist.md +3 -1
- package/skills/fenix-application/references/patent-review.md +6 -2
- package/skills/fenix-application/references/patent-safe.md +1 -1
- package/skills/fenix-application/references/patent.md +9 -9
- package/skills/fenix-application/references/spec-guidance.md +1 -1
- package/skills/fenix-application/references/spec.md +17 -7
- package/skills/fenix-application/scripts/figure_strategy_server.py +136 -0
- package/skills/fenix-diagram/SKILL.md +54 -0
- package/skills/fenix-diagram/VERSION +1 -0
- package/skills/fenix-diagram/references/diagram-svg-guide.md +271 -0
- package/skills/fenix-office-action/SKILL.md +6 -4
- package/skills/fenix-office-action/VERSION +1 -1
- package/skills/fenix-office-action/references/oa-analysis.md +14 -4
- package/skills/fenix-office-action/references/oa-drafting.md +98 -21
- package/skills/fenix-office-action/references/oa-response.md +13 -13
- package/skills/fenix-project/SKILL.md +4 -3
- package/skills/fenix-project/VERSION +1 -1
- package/skills/fenix-project/references/create-project.md +11 -1
- package/artifacts/claims-editor.html +0 -205
- package/artifacts/figures-editor.html +0 -237
- package/artifacts/oa-arguments-editor.html +0 -216
- package/artifacts/practice-dashboard.html +0 -469
- package/artifacts/project-overview.html +0 -481
- package/artifacts/sections-editor.html +0 -205
- package/artifacts/user-dashboard.html +0 -368
- package/skills/fenix-application/CUSTOMIZE.md +0 -1
- package/skills/fenix-application/assets/claims_editor.html +0 -86
- package/skills/fenix-application/assets/figures_editor.html +0 -86
- package/skills/fenix-application/assets/spec_editor.html +0 -86
- package/skills/fenix-office-action/CUSTOMIZE.md +0 -1
- package/skills/fenix-project/CUSTOMIZE.md +0 -1
|
@@ -1,71 +1,242 @@
|
|
|
1
1
|
# Editors — how to drive them
|
|
2
2
|
|
|
3
|
-
**Version:
|
|
3
|
+
**Version: 48**
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13
|
+
## The one rule
|
|
10
14
|
|
|
11
|
-
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
29
|
+
The single exception is the **courier** (below), whose entire purpose is to be rewritten.
|
|
24
30
|
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
48
|
-
|
|
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_context | `read {resource:"context"}` |
|
|
58
|
+
| set_context | `write {resource:"context", options:{ids:{projectId}, label}}` |
|
|
59
|
+
| get_project | `read {resource:"project", options:{projectId, include}}` |
|
|
60
|
+
| save_project | `write {resource:"project", action:"save", options:{…}}` |
|
|
61
|
+
| get_claim_limitations | `read {resource:"claim-limitations", options:{projectId}}` |
|
|
62
|
+
| update_claim_limitation | `write {resource:"claim-limitation", options:{…}}` |
|
|
63
|
+
| list_active_projects | `read {resource:"projects"}` |
|
|
64
|
+
| get_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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
-
|
|
71
|
-
|
|
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.
|
|
@@ -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,44 +1,81 @@
|
|
|
1
1
|
# Figures Workflow
|
|
2
2
|
|
|
3
|
-
**Version:
|
|
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
|
|
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?"
|
|
16
|
-
- **From a template:** `
|
|
17
|
-
- **
|
|
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. `
|
|
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. `
|
|
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 `
|
|
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
|
-
|
|
33
|
-
-
|
|
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.
|
|
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 `
|
|
44
|
-
**When you do run `
|
|
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 (
|
|
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
|
|