fenix-claude-plugin 0.1.2 → 0.1.3

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.
@@ -1,6 +1,6 @@
1
1
  # Patent Drafting Workflow
2
2
 
3
- **Version: 13**
3
+ **Version: 21**
4
4
 
5
5
  ## Phase overview
6
6
  - **Phase 1 -- Claims**: Read `references/claims.md` -> draft one-by-one (confirm each) -> save the whole set **once** at the end with `save_project(type=claims)`. Do not save after each claim.
@@ -11,9 +11,10 @@
11
11
 
12
12
  ## Intake
13
13
  1. Matter -- `get_project({ identifier })` (exact) or `get_project({ query })` (keyword search)
14
- 2. Template/source -- `get_project({ projectId, templateId, include: ["figures","sections","template"] })` or `get_project({ projectId, sourceProjectId, include: ["figures","sections","template"] })`
14
+ 2. Template/source -- optionally call `list_patent_templates` first to show the user the available starting templates (name, figure/claim counts) so they can pick one; then import the chosen template (or copy from another project) via `get_project({ projectId, templateId, include: ["figures","sections","template"] })` or `get_project({ projectId, sourceProjectId, include: ["figures","sections","template"] })`
15
15
  3. Disclosure -- user describes or run `references/disclosure.md` interview
16
- 4. Phase -- ask which to start
16
+ 4. Inventors -- if the user provides an inventor information sheet, declaration, or ADS (or just names), call `add_inventors({ projectId, inventors: [...] })`. Interpret the document into the Fenix person schema -- `{ name, firstName, middleName, lastName, prefix, suffix, address1, city, stateName, country, postalCode, residenceCity, residenceState, residenceCountry, email, registrationNumber }` (only `name` is required) -- or pass just names. Any number of inventors; they are upserted by name (no duplicates) and added to the matter. Never pass `clientDb`.
17
+ 5. Phase -- ask which to start
17
18
 
18
19
  **Use the imported data as-is -- do NOT drop or stub any of it.** When a template/source is imported, the response carries real figure data (brief descriptions, components, stencils/placeholders, steps, numbering) and sections. Carry every field through to `save_project` exactly as imported; only fill in genuinely missing pieces. Never replace an imported brief description, component list, stencil/placeholder, or section with a placeholder, an old stub, or invented content. If a field looks empty, confirm with the user rather than substituting a stub.
19
20
 
@@ -1,6 +1,6 @@
1
1
  # Spec Section Guidance
2
2
 
3
- **Version: 13**
3
+ **Version: 21**
4
4
 
5
5
  ## Background
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Spec Drafting Workflow
2
2
 
3
- **Version: 13**
3
+ **Version: 21**
4
4
 
5
5
  ## Start
6
6
  `get_project({ projectId, include: ["claims","figures","sections"] })` -- loads claims, figure list, and any previously saved sections.
@@ -41,7 +41,7 @@ Read `references/figure-description.md` for the full protocol. Key rules:
41
41
  Read `references/spec-guidance.md` for the drafting prompt for each section.
42
42
 
43
43
  ## Editor (accordion)
44
- **Always ask the user whether they want to open the spec editor to review/edit all sections at once** -- e.g. "Want me to open the spec editor so you can review every section together?" Only open it if they say yes. To open it, open `assets/spec_editor.html` with `INITIAL_CONTENT` set to the full sections object (each key a section name, including each "Figure N" as its own section). Each section is a collapsible accordion item with a text box (blank line = new paragraph). The user opens any section to edit, can add/remove sections, then clicks Copy for Save. On `[EDITOR SUBMIT - sections]`, strip the prefix and call `save_project({ type: "sections", sections: {...} })` with the returned object.
44
+ **Always ask the user whether they want to open the spec editor to review/edit all sections at once** -- e.g. "Want me to open the spec editor so you can review every section together?" Only open it if they say yes. **In Cowork, prefer the live spec sections editor:** `get_live_artifacts({ name: "sections-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 sections and **saves them itself**; when the user pastes a `[SECTIONS SAVED - sectionsRev N]` block, apply that delta and do **not** call `save_project` again (see `references/editors.md`). **Otherwise (non-Cowork), open `assets/spec_editor.html`** with `INITIAL_CONTENT` set to the full sections object (each key a section name, including each "Figure N" as its own section). Each section is a collapsible accordion item with a text box (blank line = new paragraph). The user opens any section to edit, can add/remove sections, then clicks Copy for Save. On `[EDITOR SUBMIT - sections]`, strip the prefix and call `save_project({ type: "sections", sections: {...} })` with the returned object.
45
45
 
46
46
  ## Notes
47
47
  - Claims are already saved -- do not include them as a section here.
@@ -6,7 +6,7 @@ description: >-
6
6
 
7
7
  # Fenix Office Action
8
8
 
9
- **Skill version: 4** (authoritative version is in the top-level `VERSION` file; this line is for reference only).
9
+ **Skill version: 7** (authoritative version is in the top-level `VERSION` file; this line is for reference only).
10
10
 
11
11
  ## Triggers
12
12
 
@@ -44,9 +44,9 @@ Read `references/oa-response.md` first -- it is the spine of the workflow. The
44
44
  2. `populate_project_from_uspto` -- import the OA rejections, dispositions, references, and claims.
45
45
  3. `import_oa_references` -- download the cited references and capture their text (needed for §102/§103 arguments).
46
46
  4. Analyze the rejections (`references/oa-analysis.md`) -- classify, choose strategy, map elements. **Stop for attorney approval.**
47
- 5. Draft + save amendments (`references/oa-drafting.md`). **Attorney approval before saving.**
48
- 6. Draft + save remarks (`references/oa-drafting.md`). **Attorney approval before saving.**
49
- 7. Assemble the response document: `get_oa_shell_doc` returns the formatted shell as base64; fill it with your docx skill (see `references/oa-drafting.md`). `print_patent({ type: "oa_shell" })` still returns just the blank shell link if that is all that is wanted.
47
+ 5. Draft + save amendments -- save CLEAN amended claim text with status Currently Amended (markup is derived on print). **Attorney approval before saving.**
48
+ 6. Draft the arguments **one rejection at a time** (present -> approve -> next), save them, then **offer the `oa-arguments-editor`** to review/revise -- REQUIRED before printing; do not skip it.
49
+ 7. Generate the document with `get_oa_shell_doc` (already populated with the marked-up claims + arguments), then **scan it for any remaining blanks/highlights/variables and ask the attorney** before finalizing.
50
50
 
51
51
  ## Invariants
52
52
 
@@ -1 +1 @@
1
- 4
1
+ 7
@@ -1,6 +1,6 @@
1
1
  # Office Action Rejection Analysis
2
2
 
3
- **Version: 4**
3
+ **Version: 7**
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
 
@@ -34,7 +34,7 @@ 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 })` for the references the examiner applied (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 `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.
38
38
 
39
39
  Present the overview + table to the attorney, then proceed to the per-rejection analysis below.
40
40
 
@@ -61,7 +61,7 @@ Present the overview + table to the attorney, then proceed to the per-rejection
61
61
  2. For each, find where (if anywhere) the reference discloses it; quote the passage.
62
62
  3. Identify at least one element that is **absent** from the reference (or not arranged as claimed). That gap is the anticipation argument.
63
63
 
64
- To get a reference's text, call `get_reference_text({ citationId })` (the `citationId` comes from the `import_oa_references` list). It returns clean EPO text, or the PDF as base64 to read, or a Google Patents link, or captured OCR text, and only asks the attorney as a last resort. Never guess a reference's contents.
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.
65
65
 
66
66
  ## §103 — Obviousness (MPEP 2141–2145)
67
67
 
@@ -1,68 +1,79 @@
1
1
  # Office Action Response Drafting & Save Contracts
2
2
 
3
- **Version: 4**
3
+ **Version: 7**
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
 
7
+ ## The model in one paragraph
8
+
9
+ You save **clean data**; Fenix renders the document. Save the **amended claim text** (clean — no markup) with status `Currently Amended`, the **per-rejection argument** prose, and the **amendment bookkeeping**. The OAR document generator then derives amendment markup (underline additions / strikethrough deletions) by diffing your amended claims against the as-pending snapshot, and inserts each argument after its boilerplate — automatically. You do **not** produce markup or hand-fill the document.
10
+
7
11
  ## Where each artifact is saved
8
12
 
9
13
  | Artifact | Saved to | How |
10
14
  |---|---|---|
11
- | Amended claim text | `Project.claims` | `save_project({ type: "claims" })` |
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: [...] })` |
12
17
  | Which claims were amended / cancelled / added | `oa_data.amendmentsStatus` | `save_project({ fields: { oa_data } })` (read-merge-write) |
13
18
  | Per-rejection drafted argument | `oa_data.oa_rejections[i].argument` / `.response_strategy` | `save_project({ fields: { oa_data } })` (read-merge-write) |
14
19
  | Final remarks prose | `Project.sections` | `save_project({ type: "sections" })` |
15
20
 
16
- ## Save efficientlybatch in ONE call
21
+ ## Amendment markup is automatic save clean text
17
22
 
18
- At the end of drafting you typically save several things: the updated `oa_data` (amendmentsStatus + per-rejection arguments), the amended `claims`, and the remarks `sections`. **Do them in a single `save_project` call using the `operations` array** do not make a separate call for each:
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.
19
24
 
20
- ```
21
- save_project({
22
- projectId,
23
- operations: [
24
- { fields: { oa_data: <full merged oa_data> } }, // amendmentsStatus + oa_rejections[].argument (read-merge-write)
25
- { type: "claims", claims: [ ... ] }, // amended claims
26
- { type: "sections", sections: { ... } } // remarks
27
- ]
28
- })
29
- ```
25
+ ## Prefer single-claim saves
30
26
 
31
- The operations run in order; the response returns a `steps` array check each `ok`, and the claims step's `parseVerification.ok`. The single-operation params still work for one-off saves.
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.
32
28
 
33
29
  ## CRITICAL: read-merge-write for `oa_data`
34
30
 
35
- `save_project({ fields: { oa_data } })` **replaces the entire `oa_data` object** (it is a `$set`). To avoid wiping the imported rejections, dispositions, and references, you must:
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:
36
32
 
37
33
  1. Load the current full object: `get_project({ projectId, include: ["oa_data"] })`.
38
- 2. Modify the in-memory object (add `amendmentsStatus`, set `oa_rejections[i].argument`, etc.) **without dropping any existing keys**.
34
+ 2. Modify the in-memory object (set `amendmentsStatus`, `oa_rejections[i].argument`, etc.) **without dropping any existing keys**.
39
35
  3. Save the complete merged object back: `save_project({ projectId, fields: { oa_data: <full merged object> } })`.
40
36
 
41
- Never send a partial `oa_data`.
37
+ Never send a partial `oa_data`. (Single-claim and `type:"claims"` saves write `Project.claims`, not `oa_data`, so they never touch `original_claims`.)
42
38
 
43
39
  ## Amendment status conventions (37 CFR 1.121)
44
40
 
45
- Every claim presented in an amendment carries a status identifier. Use these exact `claimStatus` values:
46
- - **(Original)** — unchanged since filing.
47
- - **(Currently Amended)** — being changed in this response (show changes with underline/strikethrough in the remarks/document, not in the stored `claimText`).
48
- - **(Previously Presented)** — added/amended in an earlier response, unchanged now.
49
- - **(Canceled)** — removed; no claim text.
50
- - **(New)** — newly added in this response.
51
- - **(Withdrawn)** — non-elected; not under examination.
52
-
53
- ## Saving amended claims
41
+ Use these exact `claimStatus` values:
42
+ - **Original** — unchanged since filing.
43
+ - **Currently Amended** — changed in this response. Save the clean amended text; markup + heading are derived.
44
+ - **Previously Presented** — amended in an earlier response, unchanged now.
45
+ - **Canceled** — removed; no claim text.
46
+ - **New** — newly added in this response.
47
+ - **Withdrawn** — non-elected; not under examination.
54
48
 
55
- `save_project({ type: "claims", claims: [ ... ] })` where each claim is:
49
+ ## Saving a claim
56
50
 
57
51
  ```
58
- { claimNumber: "1", claimStatus: "Currently Amended", claimType: "independent",
59
- claimText: ["...limitation...", "...limitation..."], parent: "", independentParent: "" }
52
+ save_project({ type: "claim", claim: {
53
+ claimNumber: "7", claimStatus: "Currently Amended", claimType: "dependent",
54
+ claimText: ["...clean amended limitation...", "..."], parent: "1", independentParent: "1"
55
+ }})
60
56
  ```
61
57
 
62
- - Dependent claims set `claimType: "dependent"`, `parent` to the claim they depend from, and `independentParent` to the root independent claim.
63
- - You may instead pass `rawClaims` (text); the server parses it and returns `parseVerification`.
58
+ - Independent claims set `claimType: "independent"` and empty `parent`/`independentParent`.
59
+ - For a bulk `type:"claims"` save with `rawClaims` text, the response includes `parseVerification`. **You MUST evaluate `parseVerification.ok`** — if `false`, parse the claims yourself into the structured array and re-save; do not just resend raw text.
60
+ - Optional optimistic concurrency: pass `baseRev` (the `claimsRev` you loaded) to have a stale save rejected (409) instead of overwriting.
64
61
 
65
- **You MUST evaluate `parseVerification.ok` in the response.** If it is `false` (gaps in numbering, suspected merged claims, or count mismatch vs. `sourceClaimMarkers`), the auto-parse failed: parse the claims yourself into the structured array above and re-call `save_project({ type: "claims", claims: [...] })` with your corrected JSON. Do not just resend raw text.
62
+ ## Save efficiently batch in ONE call
63
+
64
+ Save several things in a single `save_project` call with the `operations` array (runs in order; returns a `steps` array — check each `ok`):
65
+
66
+ ```
67
+ save_project({
68
+ projectId,
69
+ operations: [
70
+ { fields: { oa_data: <full merged oa_data> } }, // amendmentsStatus + oa_rejections[].argument (read-merge-write)
71
+ { type: "claim", claim: { claimNumber: "1", claimStatus: "Currently Amended", ... } },
72
+ { type: "claim", claim: { claimNumber: "7", claimStatus: "Currently Amended", ... } },
73
+ { type: "section", sectionName: "Conclusion", paragraphs: [ "..." ] } // ONE remarks section (repeat the op for more)
74
+ ]
75
+ })
76
+ ```
66
77
 
67
78
  ## Saving the amendment bookkeeping
68
79
 
@@ -80,25 +91,31 @@ amendmentsStatus: {
80
91
 
81
92
  ## Saving the per-rejection arguments
82
93
 
83
- For each rejection you responded to, set two keys on that entry in `oa_data.oa_rejections` (read-merge-write):
94
+ For each rejection you responded to, set on that entry in `oa_data.oa_rejections` (read-merge-write):
84
95
  - `response_strategy`: `"amend"` | `"argue"` | `"both"`.
85
- - `argument`: the drafted argument prose for that rejection.
96
+ - `argument`: the drafted argument prose.
97
+
98
+ These are **rendered automatically** into the OAR document — each argument is inserted right after that rejection's static boilerplate. Keep the argument as clean prose (blank lines separate paragraphs). Do not remove or reorder the existing rejection keys (`status_type`, `status_claims`, `status_refs`, etc.).
86
99
 
87
- This keeps each argument co-located with the rejection it answers. Do not remove or reorder the existing keys (`status_type`, `status_claims`, `status_refs`, etc.).
100
+ ## Editors (Cowork live artifacts)
88
101
 
89
- ## Saving the remarks
102
+ For a review/revision pass after the one-by-one drafting, offer a live editor (ask first — never open unprompted):
90
103
 
91
- Write the Remarks as project `sections`: a claim-status summary section, then one section per rejection (in OA order) containing the approved argument. Save with `save_project({ type: "sections", sections: { ... } })` (bulk) or `save_project({ type: "section", sectionName, paragraphs: [<HTML strings>] })` per section. Keep the section names stable — the OA shell print consumes them.
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.
105
+ - **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.
92
106
 
93
- ## Remarks structure (recommended)
107
+ ## Remarks
94
108
 
95
- 1. **Status of the claims** — what is pending, amended, canceled, new; which are allowed/objected.
96
- 2. **Claim amendments** the marked-up claims (handled by the claims save + the document).
97
- 3. **Arguments**, one heading per rejection, in OA order for each: restate the rejection briefly, then the approved argument (the element gap for §102/§103, the eligibility/practical-application argument for §101, the spec citations for §112, etc.).
98
- 4. **Conclusion** — request allowance / reconsideration; offer an interview if appropriate.
109
+ 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.
99
112
 
100
- Always confirm the full remarks with the attorney before saving.
113
+ 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`.
101
114
 
102
115
  ## Assembling the response document
103
116
 
104
- After the amendments and arguments are saved, assemble the Word response document per **Phase 7** of `oa-response.md`: `get_oa_shell_doc({ projectId })` returns a direct `downloadUrl` to the formatted Fenix shell; download it to an authorized folder (or use `delivery: "base64"` if you can't download a URL), use your docx skill to insert the saved arguments and amended-claim text into the blanks, and present the filled document to the attorney. The attorney does not need to download or upload anything.
117
+ 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
+
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).
120
+ 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
+ 3. Present the document to the attorney. (If you can't download a URL, pass `delivery: "base64"`.)
@@ -1,6 +1,6 @@
1
1
  # Office Action Response Workflow
2
2
 
3
- **Version: 4**
3
+ **Version: 7**
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
 
@@ -42,17 +42,30 @@ Read `references/oa-analysis.md`. For each rejection, classify it into a sub-typ
42
42
 
43
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`.
44
44
 
45
- ## Phase 6 — Draft and save the remarks
45
+ ## Phase 6 — Draft the arguments, one rejection at a time
46
46
 
47
- Read `references/oa-drafting.md`. Write the Remarks: a claim-status summary followed by one argument section per rejection, using the analysis from Phase 4. Confirm with the attorney, then save the per-rejection argument text into `oa_data.oa_rejections[i]` and the final prose as project `sections`.
47
+ Read `references/oa-drafting.md`. Draft the arguments **one rejection at a time** (like the figure-description flow), not all in a single dump:
48
48
 
49
- ## Phase 7 Assemble the response document
49
+ For each rejection, in OA order:
50
+ 1. Draft the argument from the Phase-4 analysis (the §102/§103 element gap, the §101 eligibility/practical-application argument, the §112 spec citations, etc.) and the firm's scaffolds.
51
+ 2. **Present that one argument to the attorney and END TURN.** Wait for confirmation or edits.
52
+ 3. Once approved, move to the next rejection — hold the approved arguments, don't save yet.
50
53
 
51
- Once the amendments and arguments are drafted, saved, and approved, assemble the actual response document. The Fenix shell is the firm's formatted template, but it leaves the arguments and amended-claim text **blank** you fill those in (the attorney does not need to download or upload anything):
54
+ After all arguments are approved, save them in **one** read-merge-write: set each `oa_data.oa_rejections[i].argument` (and `response_strategy`) on the full `oa_data` and save once. Also save any standalone remarks as `sections` (use the exact save shape in `references/oa-drafting.md` getting it wrong wastes a retry).
52
55
 
53
- 1. `get_oa_shell_doc({ projectId })` returns a direct `downloadUrl` (presigned, ~1 hour) to the shell.
54
- 2. **Download** `downloadUrl` into a folder you are authorized to write to — it is a direct, public file URL, so save it to disk; do **not** WebFetch it (WebFetch returns text and cannot handle a binary `.docx`). If your environment cannot download a URL to a file, call `get_oa_shell_doc({ projectId, delivery: "base64" })` and write the returned `base64` to a local `.docx` instead.
55
- 3. Use your **docx skill** to insert the drafted arguments and amended claims into the blanks. You already have this content from Phases 4–6 and from the saved project data (`oa_data.oa_rejections[].argument`, `oa_data.amendmentsStatus`, `claims`, `sections`).
56
- 4. Present the filled `.docx` to the attorney for review. Share the `dashboardUrl` so they can open the case in Fenix.
56
+ ### Required before printing offer the arguments editor
57
57
 
58
- (If the attorney only wants the blank shell, `print_patent({ type: "oa_shell" })` still returns just the download link.)
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
+
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.)"
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.)
63
+
64
+ ## Phase 7 — Generate and review the response document
65
+
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
+
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`.
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
+ 4. Present the document to the attorney for review. Share the `dashboardUrl` so they can open the case in Fenix.