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
@@ -6,7 +6,7 @@ description: >-
6
6
 
7
7
  # Fenix Office Action
8
8
 
9
- **Skill version: 7** (authoritative version is in the top-level `VERSION` file; this line is for reference only).
9
+ **Skill version: 25** (authoritative version is in the top-level `VERSION` file; this line is for reference only).
10
10
 
11
11
  ## Triggers
12
12
 
@@ -16,11 +16,12 @@ description: >-
16
16
 
17
17
  ## Customization
18
18
 
19
- Before applying any workflow in this skill, read the `CUSTOMIZE.md` file in this skill directory. If it contains anything other than the placeholder text "place custom instructions here", treat its contents as user overrides that take precedence over the default instructions in this SKILL.md and its reference files.
19
+ User overrides for this skill live in a `CUSTOMIZE.md` file in this skill directory. This file is **not shipped with the skill** -- it belongs to the user. **If `CUSTOMIZE.md` does not already exist in this skill directory, create it now** containing exactly the single line `place custom instructions here`. **If it already exists, never overwrite it** -- it holds the user's own instructions.
20
+
21
+ Before applying any workflow in this skill, read `CUSTOMIZE.md`. If it contains anything other than the placeholder text "place custom instructions here", treat its contents as user overrides that take precedence over the default instructions in this SKILL.md and its reference files.
20
22
 
21
23
  Apply the custom overrides **only as long as the result still satisfies every structured-output contract** this skill depends on, including:
22
24
  - the JSON shapes passed to `save_project` (claims, figures, sections)
23
- - the `[EDITOR SUBMIT - <type>]` clipboard prefixes produced by the HTML editors
24
25
  - the figure ElementSchema (`type`, `label`, `number`, `text`) and component numbering rules
25
26
  - the spec section names and ordering required by the save/print tools
26
27
 
@@ -40,7 +41,7 @@ Trigger whenever the attorney wants to respond to an Office Action:
40
41
  ## How to use
41
42
 
42
43
  Read `references/oa-response.md` first -- it is the spine of the workflow. The phases are:
43
- 1. Identify the matter and find/create the OA-response project.
44
+ 1. Identify the matter, then CHECK for its Fenix project (`read {resource:"project", options:{identifier or query}}`). If none exists, do not proceed on air -- gather the intake (matter/application number, notification date, project type, due date, assignee initials) and create it with `write {resource:"project", action:"create"}` (the `fenix-project` skill covers the fields; `references/oa-response.md` has the detailed step) before importing anything.
44
45
  2. `populate_project_from_uspto` -- import the OA rejections, dispositions, references, and claims.
45
46
  3. `import_oa_references` -- download the cited references and capture their text (needed for §102/§103 arguments).
46
47
  4. Analyze the rejections (`references/oa-analysis.md`) -- classify, choose strategy, map elements. **Stop for attorney approval.**
@@ -54,5 +55,6 @@ Read `references/oa-response.md` first -- it is the spine of the workflow. The
54
55
  - **Pass assignee initials directly** -- the backend resolves initials to the user; do not call get_user_by_initials first.
55
56
  - **Generate the response document only at Phase 7**, after the amendments and arguments are approved -- do not assemble or print documents earlier or out of order.
56
57
  - **Batch your saves** -- use one `save_project` call with an `operations` array (oa_data + claims + sections) instead of many separate calls.
58
+ - **Delegate a BIG save** -- when the attorney has approved a large payload (a full `oa_data`, a whole amended claim set), write it to a file and hand the save to a background agent rather than spending the conversation on it twice. `references/oa-drafting.md` has the shape and the rules -- chiefly that the agent SAVES and does not draft, and that `oa_data` is NOT revision-checked, so the agent must do the read-merge-write itself and only ever ONE agent may touch it.
57
59
  - **Approve before saving** -- amendments and arguments are legal work product; the attorney approves each before you save it.
58
60
  - **Never fabricate prior-art content** -- only distinguish a reference whose disclosure text you actually have (see `import_oa_references`).
@@ -1 +1 @@
1
- 7
1
+ 25
@@ -1,6 +1,6 @@
1
1
  # Office Action Rejection Analysis
2
2
 
3
- **Version: 7**
3
+ **Version: 25**
4
4
 
5
5
  This file is how you turn the imported `oa_data` into a response strategy. The method is **classify → select → fill**:
6
6
 
@@ -15,7 +15,7 @@ Then present the per-rejection strategy to the attorney and **stop for approval
15
15
  Each entry in `oa_data.oa_rejections` has:
16
16
  - `status_type` / `status_type_extended` — the rejection basis (e.g. contains "101", "102", "103", "112").
17
17
  - `status_claims` — the claim numbers under this rejection.
18
- - `reject_refs` / `status_refs` — the references applied (resolve to citations; their disclosure text is on the citation's `plainText` after `import_oa_references`).
18
+ - `reject_refs` / `status_refs` — the references applied (resolve to citations; their disclosure text is on the citation's `plainText` after `write {resource:"oa", action:"import-references"}`).
19
19
  - `match`, `page` — the verbatim rejection text and page in the OA.
20
20
 
21
21
  `oa_data.claim_dispositions` tells you the big picture: `allowed_claims`, `rejected_claims`, `objected_claims`, `withdrawn_claims`, `restriction_or_election`.
@@ -34,10 +34,20 @@ Before working rejection-by-rejection, orient the attorney with two things:
34
34
  |---|---|---|
35
35
  | _e.g. "a processor configured to…"_ | _e.g. Smith ¶[0042], Fig. 3_ | _e.g. Questionable — Smith discloses X but not the claimed Y_ |
36
36
 
37
- Fill the middle column from the rejection's `match`/`page` and the cited reference's disclosure text — call `get_reference_text({ citationId, query })` for the references the examiner applied, passing the claim limitation (or the concept the examiner cited) as `query` to pull just the most relevant passages with paragraph numbers (`maxPassages` caps how many). The `citationId` comes from the `import_oa_references` list. Fill the right column with your element-by-element read: is the examiner's mapping correct, a stretch, or wrong, and why. This table is the backbone of the §102/§103 analysis — the strongest distinctions surface here.
37
+ Fill the middle column from the rejection's `match`/`page` and the cited reference's disclosure text — call `read {resource:"reference-text", options:{citationId, query}}` for the references the examiner applied, passing the claim limitation (or the concept the examiner cited) as `query` to pull just the most relevant passages with paragraph numbers (`maxPassages` caps how many). The `citationId` comes from the `write {resource:"oa", action:"import-references"}` list. Fill the right column with your element-by-element read: is the examiner's mapping correct, a stretch, or wrong, and why. This table is the backbone of the §102/§103 analysis — the strongest distinctions surface here.
38
38
 
39
39
  Present the overview + table to the attorney, then proceed to the per-rejection analysis below.
40
40
 
41
+ ## Analyzing the cited references — fan out when there are several
42
+
43
+ The element-by-element mapping below depends on each cited reference's disclosure text (via `read {resource:"reference-text"}`). **If more than two references are cited** across the office action, analyze them **in parallel** rather than one at a time:
44
+
45
+ - Launch the reference-analysis agents in a single message (one Agent call per reference) so they run concurrently.
46
+ - Each agent's prompt must include the `projectId`, the `citationId`, and the claim language to map (the limitations of the rejected claim(s) the reference is applied against).
47
+ - Agents must **not** call `write {resource:"project", action:"save"}` — collect their findings and save once from the main conversation.
48
+
49
+ Each agent returns its reference's element-by-element mapping and the disclosure gaps it found; you assemble those into the per-rejection analysis. With two or fewer references, just analyze them inline — the fan-out overhead isn't worth it.
50
+
41
51
  ## §101 — Subject-matter eligibility (MPEP 2106)
42
52
 
43
53
  **Classify** the rejection into the Alice/Mayo step it turns on, and the abstract-idea grouping it asserts:
@@ -61,7 +71,7 @@ Present the overview + table to the attorney, then proceed to the per-rejection
61
71
  2. For each, find where (if anywhere) the reference discloses it; quote the passage.
62
72
  3. Identify at least one element that is **absent** from the reference (or not arranged as claimed). That gap is the anticipation argument.
63
73
 
64
- To get a reference's text, call `get_reference_text({ citationId, query, maxPassages })` (the `citationId` comes from the `import_oa_references` list). Pass the claim limitation or the examiner's cited concept as `query` to retrieve just the most relevant passages (with ¶ numbers) instead of the whole disclosure — better for element mapping and far smaller. It returns clean EPO text or targeted passages, a presigned PDF download URL (`pdf_url`) to read, a Google Patents link, or captured OCR text, and only asks the attorney as a last resort. Never guess a reference's contents.
74
+ To get a reference's text, call `read {resource:"reference-text", options:{citationId, query, maxPassages}}` (the `citationId` comes from the `write {resource:"oa", action:"import-references"}` list). Pass the claim limitation or the examiner's cited concept as `query` to retrieve just the most relevant passages (with ¶ numbers) instead of the whole disclosure — better for element mapping and far smaller. It returns clean EPO text or targeted passages, a presigned PDF download URL (`pdf_url`) to read, a Google Patents link, or captured OCR text, and only asks the attorney as a last resort. Never guess a reference's contents.
65
75
 
66
76
  ## §103 — Obviousness (MPEP 2141–2145)
67
77
 
@@ -1,6 +1,6 @@
1
1
  # Office Action Response Drafting & Save Contracts
2
2
 
3
- **Version: 7**
3
+ **Version: 25**
4
4
 
5
5
  This file defines how drafted amendments and arguments are written back to Fenix. Everything here happens **after** the attorney approves the strategy (Phase 4) and the draft (Phases 5–6).
6
6
 
@@ -12,27 +12,44 @@ You save **clean data**; Fenix renders the document. Save the **amended claim te
12
12
 
13
13
  | Artifact | Saved to | How |
14
14
  |---|---|---|
15
- | One amended/new claim | `Project.claims` (by claimNumber) | `save_project({ type: "claim", claim })` — **preferred** |
16
- | Several claims at once | `Project.claims` | `save_project({ type: "claims", claims: [...] })` |
17
- | Which claims were amended / cancelled / added | `oa_data.amendmentsStatus` | `save_project({ fields: { oa_data } })` (read-merge-write) |
18
- | Per-rejection drafted argument | `oa_data.oa_rejections[i].argument` / `.response_strategy` | `save_project({ fields: { oa_data } })` (read-merge-write) |
19
- | Final remarks prose | `Project.sections` | `save_project({ type: "sections" })` |
15
+ | One amended/new claim | `Project.claims` (by claimNumber) | `write {resource:"project", action:"save", options:{type: "claim", claim}}` — **preferred** |
16
+ | Several claims at once | `Project.claims` | `write {resource:"project", action:"save", options:{type: "claims", claims: [...]}}` |
17
+ | Which claims were amended / cancelled / added | `oa_data.amendmentsStatus` | `write {resource:"project", action:"save", options:{fields: { oa_data }}}` (read-merge-write) |
18
+ | Per-rejection drafted argument | `oa_data.oa_rejections[i].argument` / `.response_strategy` | `write {resource:"project", action:"save", options:{fields: { oa_data }}}` (read-merge-write) |
19
+ | Final remarks prose | `Project.sections` | `write {resource:"project", action:"save", options:{type: "sections"}}` |
20
20
 
21
21
  ## Amendment markup is automatic — save clean text
22
22
 
23
23
  When you amend a claim, save the **final amended claim text only** (the clean "after" version) with `claimStatus: "Currently Amended"`. Fenix keeps an immutable snapshot of the as-pending claims (`oa_data.original_claims`) and, when it generates the OAR document, diffs your amended claim against that snapshot to produce the underline/strikethrough markup and the `(Currently Amended)` heading. **Do not** embed underline/strikethrough, brackets, or any markup in `claimText` — just the clean amended language.
24
24
 
25
+ ### Use the LEAST markup possible — minimal, surgical edits
26
+
27
+ The markup is a **word-level diff** against the as-pending claim, so every word you change becomes strikethrough (deletion) or underline (addition). Make the amendment as small as the change requires:
28
+
29
+ - **Start from the exact as-pending claim text** and edit only the words the amendment actually needs. Keep all surrounding language **verbatim** — same words, same order.
30
+ - **Do not reword, rephrase, "clean up," reorder, or re-punctuate** any part you are not deliberately amending. Rewording untouched text produces large, noisy markup that overstates the scope of the amendment (and can create unintended prosecution-history estoppel).
31
+ - If your edit to a limitation changes more than the words you intend, you have reworded too much — revert to the original wording and make a tighter change.
32
+
33
+ ### Preserve the claim's existing formatting
34
+
35
+ Keep the as-pending claim's structure so the diff lines up cleanly limitation-by-limitation:
36
+
37
+ - Keep the **same line breaks between limitations** — one `claimText` array entry per limitation/line, exactly as in the as-pending claim. Edit *within* the existing lines; do not merge limitations onto one line or re-split them.
38
+ - Keep the same punctuation, indentation, and ordering of limitations.
39
+
40
+ If the `claimText` array structure changes, the diff can no longer align limitations and instead strikes an entire limitation and re-inserts it — turning a one-word change into a whole-paragraph rewrite in the markup. Matching the original structure keeps the markup minimal and readable.
41
+
25
42
  ## Prefer single-claim saves
26
43
 
27
- Amendments usually touch a few claims out of many. Save each amended (or new) claim on its own with `save_project({ type: "claim", claim: { ... } })` — it upserts that one claim by `claimNumber` and re-derives the claim tree, instead of re-sending the whole set. Use the bulk `type: "claims"` only when you are replacing most/all of the claims.
44
+ Amendments usually touch a few claims out of many. Save each amended (or new) claim on its own with `write {resource:"project", action:"save", options:{type: "claim", claim: { ... }}}` — it upserts that one claim by `claimNumber` and re-derives the claim tree, instead of re-sending the whole set. Use the bulk `type: "claims"` only when you are replacing most/all of the claims.
28
45
 
29
46
  ## CRITICAL: read-merge-write for `oa_data`
30
47
 
31
- `save_project({ fields: { oa_data } })` **replaces the entire `oa_data` object** (it is a `$set`). To avoid wiping the imported rejections, dispositions, references, and the `original_claims` snapshot, you must:
48
+ `write {resource:"project", action:"save", options:{fields: { oa_data }}}` **replaces the entire `oa_data` object** (it is a `$set`). To avoid wiping the imported rejections, dispositions, references, and the `original_claims` snapshot, you must:
32
49
 
33
- 1. Load the current full object: `get_project({ projectId, include: ["oa_data"] })`.
50
+ 1. Load the current full object: `read {resource:"project", options:{projectId, include: ["oa_data"]}}`.
34
51
  2. Modify the in-memory object (set `amendmentsStatus`, `oa_rejections[i].argument`, etc.) **without dropping any existing keys**.
35
- 3. Save the complete merged object back: `save_project({ projectId, fields: { oa_data: <full merged object> } })`.
52
+ 3. Save the complete merged object back: `write {resource:"project", action:"save", options:{projectId, fields: { oa_data: <full merged object> }}}`.
36
53
 
37
54
  Never send a partial `oa_data`. (Single-claim and `type:"claims"` saves write `Project.claims`, not `oa_data`, so they never touch `original_claims`.)
38
55
 
@@ -49,10 +66,10 @@ Use these exact `claimStatus` values:
49
66
  ## Saving a claim
50
67
 
51
68
  ```
52
- save_project({ type: "claim", claim: {
69
+ write {resource:"project", action:"save", options:{type: "claim", claim: {
53
70
  claimNumber: "7", claimStatus: "Currently Amended", claimType: "dependent",
54
71
  claimText: ["...clean amended limitation...", "..."], parent: "1", independentParent: "1"
55
- }})
72
+ }}}
56
73
  ```
57
74
 
58
75
  - Independent claims set `claimType: "independent"` and empty `parent`/`independentParent`.
@@ -61,20 +78,78 @@ save_project({ type: "claim", claim: {
61
78
 
62
79
  ## Save efficiently — batch in ONE call
63
80
 
64
- Save several things in a single `save_project` call with the `operations` array (runs in order; returns a `steps` array — check each `ok`):
81
+ Save several things in a single `write {resource:"project", action:"save"}` call with the `operations` array (runs in order; returns a `steps` array — check each `ok`):
65
82
 
66
83
  ```
67
- save_project({
68
- projectId,
84
+ write {resource:"project", action:"save", options:{projectId,
69
85
  operations: [
70
86
  { fields: { oa_data: <full merged oa_data> } }, // amendmentsStatus + oa_rejections[].argument (read-merge-write)
71
87
  { type: "claim", claim: { claimNumber: "1", claimStatus: "Currently Amended", ... } },
72
88
  { type: "claim", claim: { claimNumber: "7", claimStatus: "Currently Amended", ... } },
73
89
  { type: "section", sectionName: "Conclusion", paragraphs: [ "..." ] } // ONE remarks section (repeat the op for more)
74
- ]
75
- })
90
+ ]}}
76
91
  ```
77
92
 
93
+ ## Hand a big save to a background agent
94
+
95
+ A full `oa_data` — every rejection with its drafted argument, the amendment
96
+ bookkeeping, and the `original_claims` snapshot you must carry through — is a
97
+ large payload, and in the main conversation it costs you **twice**: once in the
98
+ call you write out, and again in the result echoed back. When the content is
99
+ **settled** (the attorney has approved it), delegate the save and keep working.
100
+
101
+ The two payload shapes here are not equally safe to delegate, and the difference
102
+ matters:
103
+
104
+ **Claims** (`type: "claim"` / `type: "claims"`) are revision-checked. Write the
105
+ approved claim objects to a file, and have the agent make one call passing
106
+ `baseRev` (the `claimsRev` you loaded). A stale save is then rejected with a 409
107
+ instead of overwriting whoever moved first.
108
+
109
+ **`oa_data` is NOT revision-checked.** It is saved through `fields`, which is a
110
+ whole-object `$set` — there is no `baseRev` for it and no 409 to catch a race.
111
+ Two writers silently produce one survivor. So for `oa_data`:
112
+
113
+ - **Give the agent the PATCH, not the merged object.** Put only what you drafted
114
+ (the per-rejection `argument` / `response_strategy`, `amendmentsStatus`) in the
115
+ file, and have the agent do the whole read-merge-write itself: load the current
116
+ `oa_data`, apply your patch over it without dropping any existing keys, save the
117
+ complete object. That keeps the READ fresh. A merged object computed in the main
118
+ conversation and saved minutes later silently reverts anything that changed in
119
+ between — the exact failure `original_claims` cannot survive.
120
+ - **Never run two agents against `oa_data`,** and do not run one while the
121
+ attorney is editing rejections in the OA editor. With no rev check, the loser's
122
+ work is simply gone.
123
+
124
+ A prompt of the right shape:
125
+
126
+ > Read `<path>/oa-patch.json`. Then: (1) load the current `oa_data` with
127
+ > `read {resource:"project", options:{projectId:"<id>", include:["oa_data"]}}`;
128
+ > (2) apply the patch over it — set only the keys the patch names, drop nothing,
129
+ > and leave `original_claims` and every existing rejection key untouched;
130
+ > (3) save the COMPLETE merged object with
131
+ > `write {resource:"project", action:"save", options:{projectId:"<id>", fields:{oa_data:<merged>}}}`.
132
+ > Do not edit, re-word, re-order or add to any argument text — it is
133
+ > attorney-approved work product. Reply with the rejection count and which keys
134
+ > you set, or the full error if it failed.
135
+
136
+ **Rules**
137
+
138
+ - The agent **saves; it does not draft.** Amendments and arguments are legal work
139
+ product approved by the attorney in the main conversation. An agent asked to
140
+ "finish" or "improve" anything will write text nobody approved.
141
+ - **Only for saves that are large and settled.** One argument, or a two-claim
142
+ amendment, costs more to delegate than to call.
143
+ - **One save per agent.** Writing the file is the step that actually saves
144
+ anything — the agent reads it, so the JSON never passes through the conversation
145
+ a second time. Pasting the payload into the agent's prompt saves nothing.
146
+ - **Check its result before you rely on the save**, and before you generate the
147
+ response document. A save you never confirmed is not a save, and Phase 7 prints
148
+ from whatever is actually stored.
149
+ - **If your host cannot run a background agent,** or the agent cannot reach the
150
+ Fenix tools, just make the call yourself — that is always the fallback, and a
151
+ delegated save that never happened is worse than a slow one.
152
+
78
153
  ## Saving the amendment bookkeeping
79
154
 
80
155
  Populate `oa_data.amendmentsStatus` (read-merge-write the full `oa_data`):
@@ -101,14 +176,14 @@ These are **rendered automatically** into the OAR document — each argument is
101
176
 
102
177
  For a review/revision pass after the one-by-one drafting, offer a live editor (ask first — never open unprompted):
103
178
 
104
- - **Arguments** — `get_live_artifacts({ name: "oa-arguments-editor" })`: substitute `__PROJECT_ID__` and `__SERVER_PREFIX__`, write the returned `html` to its `fileName`, and open it. It loads the rejections, lets the attorney edit each `argument` + `response_strategy`, **read-merge-writes the full `oa_data` itself**, and returns a `[OA ARGUMENTS SAVED]` diff. When the attorney pastes that diff, **do not re-save** — it already persisted; just apply the delta to your working copy.
179
+ - **Rejections & arguments** — bind the matter with `write {resource:"context", options:{ids: { projectId }, label: "<matter number>"}}`, then have the attorney open the **installed Fenix OA editor** from their artifacts sidebar. **Never write, edit, or substitute anything into the artifact**; see `references/editors.md` in fenix-application. It loads the rejections (and reference labels) and lets the attorney edit each rejection's **type, claims, applied references, response strategy, and argument** (and add/remove rejections), **read-merge-writes the full `oa_data` itself**, and returns a `[OA REJECTIONS SAVED]` diff. When the attorney pastes that diff, **do not re-save** — it already persisted; just apply the delta to your working copy.
105
180
  - **Amendments (claims)** — use the `claims-editor` artifact to edit the amended claim text. Save the **clean** amended text with status `Currently Amended`; the document derives the underline/strikethrough markup on print.
106
181
 
107
182
  ## Remarks
108
183
 
109
184
  Save any standalone remarks (claim-status summary, conclusion) as `sections`. **Two shapes — pick the right one (a wrong shape costs a failed save + retry):**
110
- - **One section** (the usual case): `save_project({ type: "section", sectionName: "Conclusion", paragraphs: ["<html paragraph>", "..."] })`.
111
- - **All sections at once:** `save_project({ type: "sections", sections: { "Conclusion": {...}, "Status of the Claims": {...} } })` — here `sections` is a **map of name → content**, never a single section.
185
+ - **One section** (the usual case): `write {resource:"project", action:"save", options:{type: "section", sectionName: "Conclusion", paragraphs: ["<html paragraph>", "..."]}}`.
186
+ - **All sections at once:** `write {resource:"project", action:"save", options:{type: "sections", sections: { "Conclusion": {...}, "Status of the Claims": {...} }}}` — here `sections` is a **map of name → content**, never a single section.
112
187
 
113
188
  In a batch `operations` array, save each remarks section with its own `type: "section"` op (`sectionName` + `paragraphs`); do **not** put a single section under `type: "sections"`. The per-rejection arguments live on `oa_data` (above) and are auto-inserted — do not duplicate them in `sections`.
114
189
 
@@ -116,6 +191,8 @@ In a batch `operations` array, save each remarks section with its own `type: "se
116
191
 
117
192
  Because the amended-claim markup and the per-rejection arguments are rendered from the saved data, the generated OAR document already contains them — there is no manual hand-filling for those:
118
193
 
119
- 1. `get_oa_shell_doc({ projectId })` → returns a direct `downloadUrl` to the formatted OAR document (now populated with the marked-up claims and the arguments).
194
+ 1. `write {resource:"oa", action:"generate-shell", options:{projectId}}` → returns a direct `downloadUrl` to the formatted OAR document (now populated with the marked-up claims and the arguments).
120
195
  2. Download it and review. Use your docx skill only for any residual blanks the template leaves that are **not** driven by saved data (e.g. signature/date).
121
196
  3. Present the document to the attorney. (If you can't download a URL, pass `delivery: "base64"`.)
197
+
198
+ **Avoiding "the file got truncated."** The OAR document from `write {resource:"oa", action:"generate-shell"}` is generated **whole** — treat it as the finished file, not a draft to rebuild. Do **not** read its full text back and regenerate the `.docx` from that: a long document gets truncated on read, so the rebuilt file silently loses whatever fell past the cutoff. For the residual blanks only (signature/date), make **targeted, in-place edits** to the downloaded file (find-and-replace the specific text/field with your docx skill) and leave the rest byte-for-byte untouched — never re-emit the whole document. After editing, reopen it and confirm the last section (signature block / conclusion) is present before presenting it.
@@ -1,32 +1,32 @@
1
1
  # Office Action Response Workflow
2
2
 
3
- **Version: 7**
3
+ **Version: 25**
4
4
 
5
5
  This is the end-to-end workflow for responding to a USPTO Office Action. Work through the phases in order. **Each drafting phase ends with attorney approval before anything is saved** — you draft, the attorney approves, then you save. This is legal work product; never save amendments or arguments the attorney has not approved.
6
6
 
7
7
  ## Invariants (always)
8
8
 
9
- - **Never pass `clientDb`.** It is inferred from the connector's API key. Passing it is an error.
10
- - **Never auto-generate a document.** Only call `print_patent({ type: "oa_shell" })` when the attorney explicitly asks for the Word document.
9
+ - **Never pass `clientDb`.** The tools no longer accept it — the firm is fixed by the connector you signed in to (each firm authenticates to its own MCP endpoint), so there is nothing to override.
10
+ - **Never auto-generate a document.** Only call `read {resource:"patent-document", options:{type: "oa_shell"}}` when the attorney explicitly asks for the Word document.
11
11
  - **Approval gate before every save.** Show the draft, ask for changes, save only after the attorney confirms.
12
12
  - **Never fabricate prior-art content.** Only distinguish a reference whose disclosure text you actually have (see Phase 3).
13
13
 
14
14
  ## Phase 1 — Identify the matter and the OA project
15
15
 
16
- 1. Identify the matter: `get_project({ identifier })` (exact app/matter number) or `get_project({ query })` (keyword). Confirm the matter with the attorney.
16
+ 1. Identify the matter: `read {resource:"project", options:{identifier}}` (exact app/matter number) or `read {resource:"project", options:{query}}` (keyword). Confirm the matter with the attorney.
17
17
  2. The response includes a `projects` array. Look for an existing Office-Action-response project. If one exists, use its `projectId`.
18
18
  3. If none exists, create one: `list_project_types` → `create_project` (matter/app number, notification date, due date, type, and the assignee's **initials** — pass the initials directly; the backend resolves them to the user, so you do **not** need to look the user up first) → `assign_project` only if WA1/WA2 need changing. (The `fenix-project` skill covers the intake flow.)
19
19
 
20
20
  ## Phase 2 — Pull the Office Action facts from USPTO
21
21
 
22
- 1. `populate_project_from_uspto({ projectId })`. If `matter.applicationNum` is missing it will tell you — ask the attorney for the application number and pass it as `applicationNum`.
23
- 2. Load the full state: `get_project({ projectId, include: ["matter", "claims", "oa_data"] })`.
22
+ 1. `write {resource:"project", action:"populate-from-uspto", options:{projectId}}`. If `matter.applicationNum` is missing it will tell you — ask the attorney for the application number and pass it as `applicationNum`.
23
+ 2. Load the full state: `read {resource:"project", options:{projectId, include: ["matter", "claims", "oa_data"]}}`.
24
24
  3. **Report to the attorney and stop:** OA date and type (Non-Final / Final / Restriction), examiner, the rejections grouped by statute, which claims are rejected/objected/allowed, the cited references, and whether claims/spec/figures amendments are flagged. Let the attorney confirm the picture before you analyze.
25
25
 
26
26
  ## Phase 3 — Pull the cited-reference text
27
27
 
28
- 1. `import_oa_references({ projectId })` — downloads the cited references and returns a **compact list** (`references[]` with `citationId`, `label`, `number`, `pubType`, `fileUrl`, `ocrTextChars`). It does **not** return the full text (that would flood the context). The response also includes the project `dashboardUrl` (→ Citations tab) you can share.
29
- 2. For each reference you actually need to read — usually the ones the examiner applied against the claims you are arguing — call `get_reference_text({ citationId })`. It walks a fallback chain and returns whichever source worked (`source` tells you which):
28
+ 1. `write {resource:"oa", action:"import-references", options:{projectId}}` — downloads the cited references and returns a **compact list** (`references[]` with `citationId`, `label`, `number`, `pubType`, `fileUrl`, `ocrTextChars`). It does **not** return the full text (that would flood the context). The response also includes the project `dashboardUrl` (→ Citations tab) you can share.
29
+ 2. For each reference you actually need to read — usually the ones the examiner applied against the claims you are arguing — call `read {resource:"reference-text", options:{citationId}}`. It walks a fallback chain and returns whichever source worked (`source` tells you which):
30
30
  - **`epo`** — clean structured claims + description in `text`; use it directly.
31
31
  - **`google_patents_url`** — read the `url` with your web tools.
32
32
  - **`pdf_url`** — download the `downloadUrl` to a local `.pdf` and read it with your pdf/Read tools (don't WebFetch it). (`source: "pdf_base64"` returns the bytes inline only if you can't download a URL.)
@@ -40,7 +40,7 @@ Read `references/oa-analysis.md`. For each rejection, classify it into a sub-typ
40
40
 
41
41
  ## Phase 5 — Draft and save the amendments
42
42
 
43
- Read `references/oa-drafting.md`. Draft amended claim text with the correct claim status. Confirm with the attorney, then save: amended claims via `save_project({ type: "claims" })` (and you **must** check `parseVerification.ok`), and the amendment bookkeeping into `oa_data.amendmentsStatus`.
43
+ Read `references/oa-drafting.md`. Draft amended claim text with the correct claim status. Confirm with the attorney, then save: amended claims via `write {resource:"project", action:"save", options:{type: "claims"}}` (and you **must** check `parseVerification.ok`), and the amendment bookkeeping into `oa_data.amendmentsStatus`.
44
44
 
45
45
  ## Phase 6 — Draft the arguments, one rejection at a time
46
46
 
@@ -57,15 +57,15 @@ After all arguments are approved, save them in **one** read-merge-write: set eac
57
57
 
58
58
  Once the arguments are saved, you **must offer the arguments editor before generating any document.** This is a required step; do not skip it and do not jump straight to printing. Say it explicitly, e.g.:
59
59
 
60
- > "The arguments are saved. Want me to open the **OA arguments editor** so you can review and revise them all together before I generate the response? (Or I can generate it now.)"
60
+ > "The arguments are saved. Want me to open the **OA rejections & arguments editor** so you can review and revise them all together before I generate the response? (Or I can generate it now.)"
61
61
 
62
- If yes, open the `oa-arguments-editor` live artifact (see `references/oa-drafting.md`) — it loads the rejections, lets the attorney edit each argument + strategy, saves itself, and returns a `[OA ARGUMENTS SAVED]` diff to paste back (apply the diff; do not re-save). Only move to Phase 7 after the attorney has used the editor or explicitly declined it. (Amendments are reviewed in the `claims-editor`; markup is derived on print.)
62
+ If yes, open the `oa-arguments-editor` live artifact (see `references/oa-drafting.md`) — it lets the attorney adjust each rejection's type, claims, applied references, response strategy, and argument (and add/remove rejections), saves itself, and returns a `[OA REJECTIONS SAVED]` diff to paste back (apply the diff; do not re-save). Only move to Phase 7 after the attorney has used the editor or explicitly declined it. (Amendments are reviewed in the `claims-editor`; markup is derived on print.)
63
63
 
64
64
  ## Phase 7 — Generate and review the response document
65
65
 
66
66
  Only after you have offered the arguments editor (Phase 6) and the attorney has used or declined it, generate the response document. Fenix renders the **amended-claim markup** (underline/strikethrough, derived from the saved clean claims) and the **per-rejection arguments** (inserted after each boilerplate) directly from the saved data — so the document already contains them. There is no manual hand-filling for those.
67
67
 
68
- 1. `get_oa_shell_doc({ projectId })` → returns a direct `downloadUrl` (presigned, ~1 hour) to the formatted OAR document, populated with the marked-up claims and the arguments.
69
- 2. **Download** `downloadUrl` to a folder you can write to — it is a direct, public file URL, so save it to disk; do **not** WebFetch it. If your environment cannot download a URL, call `get_oa_shell_doc({ projectId, delivery: "base64" })` and write the `base64` to a local `.docx`.
68
+ 1. `write {resource:"oa", action:"generate-shell", options:{projectId}}` → returns a direct `downloadUrl` (presigned, ~1 hour) to the formatted OAR document, populated with the marked-up claims and the arguments.
69
+ 2. **Download** `downloadUrl` to a folder you can write to — it is a direct, public file URL, so save it to disk; do **not** WebFetch it. If your environment cannot download a URL, call `write {resource:"oa", action:"generate-shell", options:{projectId, delivery: "base64"}}` and write the `base64` to a local `.docx`.
70
70
  3. **Scan the document for anything left to fill.** Read the downloaded `.docx` and find any remaining blanks, highlighted fields, bracketed placeholders, or template variables (e.g. `[ … ]`, `{{ … }}`, highlighted runs, and signature / date / customer-number / attorney-docket blanks). List exactly what you found and **ask the attorney whether to fill each one in, and with what** — then apply the answers with your **docx skill**. Do not silently leave them or guess values.
71
71
  4. Present the document to the attorney for review. Share the `dashboardUrl` so they can open the case in Fenix.
@@ -6,7 +6,7 @@ description: >-
6
6
 
7
7
  # Fenix Project
8
8
 
9
- **Skill version: 2** (authoritative version is in the top-level `VERSION` file; this line is for reference only).
9
+ **Skill version: 4** (authoritative version is in the top-level `VERSION` file; this line is for reference only).
10
10
 
11
11
  ## Triggers
12
12
 
@@ -16,11 +16,12 @@ description: >-
16
16
 
17
17
  ## Customization
18
18
 
19
- Before applying any workflow in this skill, read the `CUSTOMIZE.md` file in this skill directory. If it contains anything other than the placeholder text "place custom instructions here", treat its contents as user overrides that take precedence over the default instructions in this SKILL.md and its reference files.
19
+ User overrides for this skill live in a `CUSTOMIZE.md` file in this skill directory. This file is **not shipped with the skill** -- it belongs to the user. **If `CUSTOMIZE.md` does not already exist in this skill directory, create it now** containing exactly the single line `place custom instructions here`. **If it already exists, never overwrite it** -- it holds the user's own instructions.
20
+
21
+ Before applying any workflow in this skill, read `CUSTOMIZE.md`. If it contains anything other than the placeholder text "place custom instructions here", treat its contents as user overrides that take precedence over the default instructions in this SKILL.md and its reference files.
20
22
 
21
23
  Apply the custom overrides **only as long as the result still satisfies every structured-output contract** this skill depends on, including:
22
24
  - the JSON shapes passed to `save_project` (claims, figures, sections)
23
- - the `[EDITOR SUBMIT - <type>]` clipboard prefixes produced by the HTML editors
24
25
  - the figure ElementSchema (`type`, `label`, `number`, `text`) and component numbering rules
25
26
  - the spec section names and ordering required by the save/print tools
26
27
 
@@ -1 +1 @@
1
- 2
1
+ 4
@@ -1,9 +1,19 @@
1
1
  # Create Project
2
2
 
3
- **Version: 2**
3
+ **Version: 4**
4
4
 
5
5
  1. **Collect** -- matter/app number, notification date, project type ('list_project_types'), due date, assignee initials
6
6
  2. **Confirm** -- show all values. Ask 'Ready to create -- any changes?' **END TURN**
7
7
  3. **Create** -- 'create_project' once confirmed. Pass the assignee **initials** directly -- the backend resolves initials to the user automatically (no need to call 'get_user_by_initials'). If the initials are not recognised, create_project returns an error so you can ask for the correct initials.
8
8
 
9
+ ## The notification date is the date the USER gives you -- never today
10
+
11
+ `notificationDate` is a REQUIRED field and it is **whatever date the user states** for this filing or action -- the date on the office action, the date the notice was received, the filing/receipt date for a new application. If the user gives you a date at any point during intake, that date is the notificationDate; do **not** quietly substitute today's date, and do not put the user's date in `dueDate` instead.
12
+
13
+ **Why it matters: it is the one field that tells two projects on the same matter apart.** A matter can carry several projects -- two office actions, an application and its continuation, refilings -- and they share a matter number and an invention title, so in every list and in the editor's matter switcher they look identical. The notification date is the disambiguator. Getting it wrong (or defaulting it to today) leaves the user with two rows they cannot tell apart and cannot reliably pick between.
14
+
15
+ If the user has not given a date, **ask for it** rather than inventing one. For a brand-new application with no notice, ask which date they want recorded (filing date, receipt date); it still has to be a real, deliberate value, because it is what will distinguish this project later.
16
+
17
+ `dueDate` is a DIFFERENT field -- the response/action deadline. Keep the two separate; if the user gives only one date, confirm which it is before creating.
18
+
9
19
  If any field is missing: render a React form with all fields. On submit show confirmation block, then 'create_project'.