pi-career 0.1.0 → 0.3.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/README.md CHANGED
@@ -1,159 +1,508 @@
1
1
  # pi-career
2
2
 
3
- Self-contained [Pi package](https://github.com/earendil-works/pi) for deterministic Career Core workflows on explicitly supported native targets.
3
+ [![npm version](https://img.shields.io/npm/v/pi-career.svg)](https://www.npmjs.com/package/pi-career)
4
+ [![npm downloads](https://img.shields.io/npm/dm/pi-career.svg)](https://www.npmjs.com/package/pi-career)
5
+ [![CI](https://github.com/revazi/pi-career/actions/workflows/ci.yml/badge.svg)](https://github.com/revazi/pi-career/actions/workflows/ci.yml)
6
+ [![license: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license-and-provenance)
4
7
 
5
- This publicly readable Git repository owns the Pi adapter, package-owned runtime artifacts and resolver, Pi package metadata, Pi-facing Agent Skill, build/package tests, and integration guidance. Career Core remains authoritative for operations, algorithms, versioned JSON schemas, errors, evidence, warnings, uncertainty, ordering, and assisted/non-authoritative semantics.
8
+ `pi-career` is a [Pi package](https://github.com/earendil-works/pi) for deterministic resume analysis and conservative vacancy matching, with an optional model-assisted workflow for reviewed resume improvements.
6
9
 
7
- ## Surface and non-scope
10
+ The package's command handlers do not call a model/provider. `/career-workbench` prepares a visible private prompt in Pi's editor, while `/career-review` prepares only an ephemeral review handle and explicitly selected canonical IDs; only the user's later submission invokes the selected Pi model/provider. At runtime, pi-career never uses a Career Core source checkout or Cargo build. Its optional maintainer compatibility test may read an explicitly supplied, reviewed Core fixture checkout.
8
11
 
9
- The package preserves exactly three native tools:
12
+ It gives you:
10
13
 
11
- - `career_core_discover`
12
- - `career_core_resume`
13
- - `career_core_job`
14
-
15
- On supported targets it also provides deterministic slash commands:
16
-
17
- - `/career-setup`
18
- - `/career-library`
19
- - `/career-vacancy`
20
- - `/career-match`
21
- - `/career-analyze`
14
+ - local slash commands for setting up a resume library, analyzing originals, and matching them to a vacancy;
15
+ - one compact managed agent tool, `career_run`, for guided work after the deterministic baseline;
16
+ - a visible workbench handoff that never sends private resume text until you review and submit it yourself;
17
+ - bounded TUI inspection and explicit selection of Core-reviewed non-PDF changes without automatic materialization;
18
+ - a bounded resolver for a compatible external Career Core runtime;
19
+ - no bundled native binary, telemetry, vacancy URL fetching, automatic document overwrite, or hidden provider call.
22
20
 
23
- Commands call the same package-owned runtime directly through bounded argv/stdin execution; they never call an LLM-facing tool, provider, model, network, PATH, Cargo, sibling checkout, or downloaded runtime. The workflow scans only explicitly configured `.md`/`.txt` roots, excludes assisted variants and inputs over 50,000 Unicode scalar values from authoritative operations, and never overwrites source files. See [`docs/design.md`](docs/design.md), [`docs/product-flow.md`](docs/product-flow.md), and [`SECURITY.md`](SECURITY.md).
21
+ Career Core remains authoritative for scores, evidence, warnings, uncertainty, matching, and proposal review. `pi-career` owns the Pi workflow and presentation layer; it does not reimplement Career Core algorithms or schemas.
24
22
 
25
- ## Supported runtime targets
23
+ > **Version note:** this README describes the `pi-career@0.3.0` candidate. Published `pi-career@0.2.0` is the prior native-free release, and `pi-career@0.1.0` is the historical bundled-runtime release. Until `0.3.0` is explicitly released and visible on the npm registry, use a reviewed local checkout or pinned Git commit.
26
24
 
27
- | Package target | Native platform |
28
- |---|---|
29
- | `darwin-arm64` | macOS on Apple silicon |
30
- | `linux-x64-gnu` | Linux x64 with glibc |
31
-
32
- Windows, macOS x64, Linux arm64, Linux musl, and unknown libc/platform combinations are unsupported. The package may register on an unsupported target, but deterministic operations fail closed with a payload-free `unsupported_platform` error; they never guess, download a runtime, search `PATH`, or invoke Cargo.
33
-
34
- The unsigned package-owned runtime artifacts were produced and natively verified from Career Core commit `a3cdb4c6d7f966397e93ea4664071975bca7228c` by [artifact run 30953471793](https://github.com/revazi/career-core/actions/runs/30953471793). [`runtime/manifest.json`](runtime/manifest.json) pins target paths, sizes, SHA-256 values, provenance, and bounded contract digests. Before the first bundled spawn in each process, the selected regular executable is checked for exact size, mode, and SHA-256; only successful verification is cached in memory.
35
-
36
- `CAREER_CLI_PATH` remains an optional developer/recovery override. When set, it must be a bounded absolute path to a separately reviewed compatible executable and takes precedence over the bundled runtime. Normal users do not set it.
37
-
38
- ## End-user prerequisites
25
+ ## Requirements
39
26
 
27
+ - Node.js 22.19 or newer
40
28
  - Pi with 0.84.0-compatible package APIs
41
- - one of the two supported native targets above
42
- - a reviewed clean local checkout, public Git commit, or exact npm version of this package
29
+ - macOS or Linux on ARM64/x64; GNU Linux requires glibc 2.35+, and musl Linux is supported
30
+ - either a compatible local `career` executable or network access for first-use acquisition of exact `@revazi/career@0.2.0`
43
31
 
44
- No separate Career Core checkout, `career` installation, Cargo, Rust toolchain, install-time build, or runtime download is required.
32
+ Windows is unsupported. npm enforces the package `os` allowlist; for a local or Git registration, extension initialization fails with stable `unsupported_platform` guidance before registering any command or tool, inspecting `CAREER_CLI_PATH`, searching `PATH`, validating package routes, acquiring npm content, or opening private stdin.
45
33
 
46
- ## Reviewed local installation
34
+ ## Install
47
35
 
48
- Pi local-path packages are referenced in place rather than copied. Register a reviewed clean checkout at a stable absolute path:
36
+ After the registry confirms the release, install the exact version:
49
37
 
50
38
  ```bash
51
- cd /absolute/path/to/pi-career
52
- package_root="$(pwd -P)"
53
- pi install "$package_root"
39
+ pi install npm:pi-career@0.3.0
54
40
  pi list
55
41
  ```
56
42
 
57
- Restart Pi or run `/reload` after a reviewed update. A local registration follows files at that path and does not pin future changes, so update the checkout only to reviewed revisions.
58
-
59
- Remove the registration with the same resolved path:
43
+ For release-candidate testing, a clean checkout includes reproducible `dist/index.js` and `dist/pdf-worker.js` bundles, so local installation does not require a build or npm install:
60
44
 
61
45
  ```bash
62
46
  cd /absolute/path/to/pi-career
63
- package_root="$(pwd -P)"
64
- pi remove "$package_root"
47
+ pi install "$(pwd -P)"
65
48
  pi list
66
49
  ```
67
50
 
68
- ## Public npm installation pinned to a version
51
+ Local-path installation loads the checkout in place. After a reviewed update, restart Pi or run `/reload`.
69
52
 
70
- After reviewing the release metadata, install an exact published version:
53
+ To pin a reviewed Git commit instead:
71
54
 
72
55
  ```bash
73
- pi install npm:pi-career@0.1.0
74
- pi list
56
+ pi install git:github.com/revazi/pi-career@<reviewed-full-commit>
75
57
  ```
76
58
 
77
- A versioned npm package is pinned and skipped by package updates. Review and install a new exact version to update. Remove it by package identity:
59
+ Remove the exact source you installed:
78
60
 
79
61
  ```bash
80
62
  pi remove npm:pi-career
63
+
64
+ # Or, for a local-path registration:
65
+ cd /absolute/path/to/pi-career
66
+ pi remove "$(pwd -P)"
81
67
  ```
82
68
 
83
- ## Public Git installation pinned to a commit
69
+ Developers who modify `src/` must rebuild the tracked bundles with `npm run build`; see [Development](#development).
70
+
71
+ ## Recommended first run
72
+
73
+ The optimal path starts with deterministic analysis. The model-assisted path begins only if you review and submit the prompt prepared by `/career-workbench`.
74
+
75
+ ```mermaid
76
+ flowchart TD
77
+ A["Start Pi"] --> B{"Persist this Pi session?"}
78
+ B -->|No| C["Start with pi --no-session"]
79
+ B -->|Yes| D["Use a normal session<br/>approve local persistence if prompted"]
80
+
81
+ C --> E["/career-setup<br/>add an original-resume root"]
82
+ D --> E
83
+ E --> F["/career-library<br/>review indexed originals and notices"]
84
+ F --> G["/career-analyze<br/>establish the deterministic baseline"]
85
+
86
+ G --> H{"Matching a vacancy?"}
87
+ H -->|No| I{"Want model-assisted help?"}
88
+ H -->|Yes| J["/new<br/>one fresh session per company and role"]
89
+ J --> K["/career-application<br/>create company/role context"]
90
+ K --> L["/career-vacancy<br/>paste text; Career Core validates it"]
91
+ L --> M["/career-match<br/>rank eligible original resumes"]
92
+ M --> I
93
+
94
+ I -->|No| N["Inspect deterministic details and stop"]
95
+ I -->|Yes| O["/career-workbench<br/>private prompt is prepared in the editor<br/>nothing is sent"]
96
+ O --> P{"Review and submit the prompt?"}
97
+ P -->|No| Q["Edit or cancel"]
98
+ P -->|Yes| R["Selected Pi model/provider<br/>uses career_run handles"]
99
+ R --> S["career_run reruns the complete<br/>deterministic baseline"]
100
+ S --> T{"Requested workflow"}
101
+ T -->|Explain score| U["Explain the complete deterministic result"]
102
+ T -->|Plan / rewrite / replacements| V["Career Core reviews external<br/>suggestions or replacements once"]
103
+ V --> W["Present retained items, discards, and warnings<br/>no automatic application or save"]
104
+ T -->|Tailor to vacancy| X["Analyze and match the original<br/>Career Core reviews variant changes once"]
105
+ X --> Y{"Original format"}
106
+ Y -->|PDF| AA["Return targeted manual changes only"]
107
+ Y -->|Markdown/text| AB["career_run ends the review turn"]
108
+ AB --> AD["/career-review<br/>inspect notices and exact changes<br/>all IDs start excluded"]
109
+ AD --> AE{"Review and submit selected IDs?"}
110
+ AE -->|No| Z
111
+ AE -->|Yes| AC["Later turn: career_run materialize<br/>assisted text remains in memory"]
112
+ AC --> AF{"Save this local variant?"}
113
+ AF -->|No| Z
114
+ AF -->|Yes| AG["/career-save<br/>review exact files and destination<br/>then confirm separately"]
115
+
116
+ N --> Z["Original remains unchanged<br/>assisted output is non-authoritative<br/>and is never reranked as an original"]
117
+ Q --> Z
118
+ U --> Z
119
+ W --> Z
120
+ AA --> Z
121
+ AG --> Z
122
+ ```
84
123
 
85
- After reviewing a full commit SHA, install directly from this public repository; no configured Git credentials are required:
124
+ ### 1. Start with a transient Pi session
125
+
126
+ For a first test—or whenever you do not want Pi to write this conversation to a session JSONL—start:
86
127
 
87
128
  ```bash
88
- pi install git:github.com/revazi/pi-career@<full-reviewed-commit-sha>
89
- pi list
129
+ pi --no-session
90
130
  ```
91
131
 
92
- A pinned Git package is not moved by `pi update --extensions`. To update, review a new full SHA and install that explicit ref:
132
+ This prevents Pi session persistence for the new run. It is not secure erasure and does not remove shell history, previous sessions, backups, provider copies, or npm cache data.
93
133
 
94
- ```bash
95
- pi install git:github.com/revazi/pi-career@<new-full-reviewed-commit-sha>
134
+ If you use a normal persisted session, `pi-career` asks for explicit consent before it adds private vacancy/workflow state. A local-session decision is separate from permission to send content to a model provider.
135
+
136
+ ### 2. Configure an originals library
137
+
138
+ Put one or more original resumes in a dedicated directory. Supported inputs are:
139
+
140
+ - UTF-8 Markdown (`.md`)
141
+ - UTF-8 plain text (`.txt`)
142
+ - searchable, unencrypted PDF (`.pdf`), up to 10 MiB and 20 pages
143
+
144
+ Image-only/scanned PDFs need OCR or export to Markdown/text first. DOCX, Pages, vacancy URLs, and OCR are not supported.
145
+
146
+ In Pi, run:
147
+
148
+ ```text
149
+ /career-setup
150
+ ```
151
+
152
+ Choose **Add root** and enter the resume directory. Setup stores the canonical root in private local Pi configuration; it does not copy, move, or edit your resumes.
153
+
154
+ Setup also displays a preferred `variants/` destination. This is suggestion-only: it creates no directory or file and does not authorize a save.
155
+
156
+ ### 3. Confirm what was indexed
157
+
158
+ ```text
159
+ /career-library
160
+ ```
161
+
162
+ Review the indexed originals and any notices. Fix unreadable, oversized, invalid UTF-8, encrypted, or image-only documents before continuing.
163
+
164
+ ### 4. Analyze an original before tailoring it
165
+
166
+ ```text
167
+ /career-analyze
168
+ ```
169
+
170
+ Choose one original resume. The command runs deterministic readiness analysis, shows a compact card, and lets you inspect the complete result or focused sections in a transient viewer.
171
+
172
+ This is the best first baseline: understand the resume on its own before adding vacancy-specific concerns.
173
+
174
+ ### 5. Use one Pi session per company and role
175
+
176
+ Start a fresh Pi conversation before each application:
177
+
178
+ ```text
179
+ /new
180
+ /career-application
181
+ ```
182
+
183
+ Enter the company and role. The application context scopes its vacancy and result cards and names an otherwise unnamed Pi session. It does not create an application directory or write career documents.
184
+
185
+ Then set the vacancy:
186
+
187
+ ```text
188
+ /career-vacancy
189
+ ```
190
+
191
+ Paste the vacancy text directly. `pi-career` never fetches a vacancy URL. Career Core validates the text before it becomes the current vacancy.
192
+
193
+ ### 6. Match your originals
194
+
195
+ ```text
196
+ /career-match
197
+ ```
198
+
199
+ Choose all eligible originals or a subset. The command deterministically normalizes the vacancy, analyzes each selected original, matches each original to the vacancy, and then ranks the results conservatively. You can open detailed evidence for a selected row.
200
+
201
+ Scores and recommendations are bounded workflow guidance—not hiring predictions, ATS guarantees, or evidence that an employer will respond.
202
+
203
+ ### 7. Open the workbench only when you want model-assisted help
204
+
205
+ ```text
206
+ /career-workbench
207
+ ```
208
+
209
+ Choose an original and a guided mode. The command prepares a private prompt in Pi's normal editor; it does **not** invoke Career Core or a model and sends nothing automatically. Read the prompt and source payload before submitting it.
210
+
211
+ After you submit, the selected Pi agent uses `career_run` to rerun complete deterministic baselines and Core-review any proposed suggestions, replacements, or vacancy-specific changes. The original remains immutable.
212
+
213
+ For a non-PDF tailored variation, `career_run variant-review` ends the agent turn. Run `/career-review <review-handle>` to inspect every warning/discard and each exact before/after/evidence record; all retained changes start excluded. Explicitly include the IDs you want, review those selected changes together, and separately confirm the handle/ID-only editor handoff before submitting it as a later turn. The selector never materializes or submits automatically. After successful materialization, you may separately run `/career-save <variant-handle>` to inspect the complete local file plan and confirm it; the model cannot invoke saving. For PDFs, the workbench returns targeted manual changes only because extracted text cannot preserve typography, columns, spacing, or graphics; PDF review handles cannot enter selection, materialization, or saving.
214
+
215
+ ## Slash command reference
216
+
217
+ The workflow commands below require interactive TUI/RPC mode except `/career-vacancy clear`; `/career-review` is TUI-only, `/career-save` supports TUI/RPC, and `/career-tools` is a lightweight tool-surface switch. Slash-command handlers do not invoke a model/provider. `/career-workbench` and `/career-review` prepare editor prompts whose later user submission does. Core-backed commands may resolve or acquire the external runtime before processing private input.
218
+
219
+ ### `/career-setup [status]`
220
+
221
+ Configure and inspect package-level resume-library settings.
222
+
223
+ Without arguments, the setup menu can:
224
+
225
+ - add a readable resume root;
226
+ - rescan configured roots;
227
+ - show setup and scan status;
228
+ - set or clear a suggestion-only resume-variation directory.
229
+
230
+ It stores only canonical root paths, bounded labels, and the optional variation-directory suggestion. It does not install Career Core, create the suggested directory, copy resumes, or write result files.
231
+
232
+ Use `/career-setup status` to display the current summary and notices without opening the menu.
233
+
234
+ ### `/career-library [status]`
235
+
236
+ Browse and maintain the configured resume index.
237
+
238
+ The menu can:
239
+
240
+ - browse indexed PDF, Markdown, and text records;
241
+ - add or remove a root from configuration;
242
+ - rescan all configured roots;
243
+ - show counts and actionable scan notices.
244
+
245
+ Removing a root changes configuration only; it never deletes files. Assisted variants with valid sidecars remain visible but are excluded from authoritative analysis and matching. Oversized originals remain visible as unavailable where appropriate.
246
+
247
+ Use `/career-library status` for a summary without the menu.
248
+
249
+ ### `/career-application [status|clear]`
250
+
251
+ Create and manage one company/role context for the current Pi session.
252
+
253
+ A new application records bounded company and role labels, starts at `preparing`, and can later be marked `applied`, `interviewing`, or `closed`. Its immutable application ID scopes the current vacancy and result cards. If the Pi session has no name, the command names it from the company and role.
254
+
255
+ Use:
256
+
257
+ - `/career-application status` to show the active context;
258
+ - `/career-application clear` to clear the application and its current vacancy.
259
+
260
+ After clearing—or before working on another company/role—run `/new`. The same Pi session cannot be reused for a second application context because earlier private prompts would still be in that conversation.
261
+
262
+ This command manages session state only. It does not create workspace folders or application files.
263
+
264
+ ### `/career-vacancy [clear]`
265
+
266
+ Set, inspect, replace, or clear the current vacancy.
267
+
268
+ When no vacancy exists, the command opens an editor for pasted text. When one exists, it offers **Replace**, **View**, **Clear**, or **Cancel**. New or replacement text is normalized and validated by Career Core before being stored in workflow state.
269
+
270
+ The vacancy is bound to the active application when one exists. It must be supplied as text; URLs are never fetched.
271
+
272
+ Use `/career-vacancy clear` to clear it directly. This is the only career slash-command action allowed without interactive TUI/RPC mode.
273
+
274
+ ### `/career-analyze [filter]`
275
+
276
+ Run deterministic readiness analysis for one eligible original resume.
277
+
278
+ The optional filter is a case-insensitive substring matched against the resume label, relative path, and stable ID. For example:
279
+
280
+ ```text
281
+ /career-analyze backend
96
282
  ```
97
283
 
98
- Remove it by repository identity:
284
+ After selecting a resume, the command:
285
+
286
+ 1. requests persistence consent when needed;
287
+ 2. runs the authoritative original-resume analysis;
288
+ 3. stores only a bounded result card in session state;
289
+ 4. offers complete/focused transient detail;
290
+ 5. can prepare a single-resume match command when a vacancy exists;
291
+ 6. can open the guided workbench for the selected resume.
292
+
293
+ It never analyzes an assisted variant as an original. Oversized output fails without partial results or hidden file export.
294
+
295
+ ### `/career-match [filter]`
296
+
297
+ Deterministically rank eligible original resumes against the current vacancy.
298
+
299
+ Set a vacancy first with `/career-vacancy`. The optional filter uses the same label/relative-path/ID substring matching as `/career-analyze`.
300
+
301
+ The command lets you choose every matching original or select a subset. It then runs, sequentially:
302
+
303
+ 1. vacancy normalization;
304
+ 2. readiness analysis for every selected original;
305
+ 3. original-resume/vacancy matching for every selected original;
306
+ 4. stable conservative ranking and tie display.
307
+
308
+ The summary keeps unavailable oversized results visible instead of silently dropping them. Select a ranked row to inspect scores, strengths, gaps, confidence, warnings, evidence, and vacancy context.
309
+
310
+ Assisted variants are never accepted as authoritative match inputs.
311
+
312
+ ### `/career-workbench [filter]`
313
+
314
+ Prepare a visible, guided prompt for the selected Pi agent.
315
+
316
+ The optional resume filter behaves like `/career-analyze`. Available modes are:
317
+
318
+ - **Explain my score** — rerun and explain the complete deterministic analysis;
319
+ - **Create a reviewed improvement plan** — propose at most three advisory suggestions and Core-review them once;
320
+ - **Guided rewrite interview** — ask a small set of factual questions first, wait for your answers, then review bounded exact replacements in a later turn;
321
+ - **Draft reviewed replacements** — propose and Core-review bounded before/after replacements without claiming they were applied;
322
+ - **Create a tailored variation** — available when a current vacancy exists; analyze and match the original, then review vacancy-grounded changes;
323
+ - **Ask my own question** — prepare a custom resume-only request under the same safety rules.
324
+
325
+ The command itself calls neither Career Core nor a provider. It puts the complete selected resume—and the vacancy only for tailoring—into Pi's editor. Nothing is sent until you submit. Submitting may persist that message and send it to the provider selected in Pi.
326
+
327
+ The workbench and model never save automatically. Only a later successful non-PDF materialization can be passed by the user to `/career-save` for separate exact local preview and confirmation.
328
+
329
+ ### `/career-review <review-handle>`
330
+
331
+ Review and explicitly select retained changes from a current non-PDF `career_run variant-review` result. This command is available only in TUI mode and only while the ephemeral review handle remains in the current process/session branch.
332
+
333
+ The bounded selector:
334
+
335
+ - requires inspection/acknowledgment of all Core warnings and discarded-change reasons;
336
+ - shows every canonical change as excluded by default;
337
+ - opens a paged exact view of its before text, proposed after text, line bounds, resume evidence, and vacancy evidence;
338
+ - includes a change only after you toggle it from that exact view;
339
+ - requires at least one included canonical ID before continuing;
340
+ - pages all selected exact changes together in a compact labeled view, lets you reopen any selected record directly, and requires a separate final prepare choice with a back option for revisions.
341
+
342
+ Only that final prepare choice creates a short editor message containing the review handle and selected IDs. It does not invoke Career Core, materialize a result, contact a provider, append selection state to the Pi session, save a result, or write a file. Review and submit that editor message manually to start the later materialization turn. Escape cancels without preparing anything.
343
+
344
+ PDF review changes remain manual-application guidance and are rejected by `/career-review`, `career_run materialize`, and `/career-save`.
345
+
346
+ ### `/career-save <variant-handle>`
347
+
348
+ Save one current successful Markdown/text `career_run materialize` result as a new assisted local variant. This user-only command is not a model tool and is available in TUI/RPC mode on supported POSIX systems.
349
+
350
+ Before writing anything, it:
351
+
352
+ 1. revalidates the ephemeral variant and unchanged original;
353
+ 2. derives an eligible direct-child managed variants directory;
354
+ 3. opens a complete canonical preview containing exact destination paths, artifact/sidecar bytes, hashes, and any directory marker;
355
+ 4. requires the preview to be returned byte-identically;
356
+ 5. asks for a separate final confirmation.
357
+
358
+ It then publishes new `0600` files in a `0700` managed directory without replacing existing paths, writes a strict assisted/non-authoritative sidecar, and rescans before reporting success. Missing, malformed, edited, or hash-mismatched assisted metadata is quarantined and never falls back to original eligibility. Saving invokes no Career Core operation, provider, model, network request, or session entry. PDF handles fail closed; the save workflow is supported on pi-career's macOS/Linux platforms with its POSIX-private filesystem contract.
359
+
360
+ Saved files are not securely erased by session deletion, root removal, package removal, or `PI_OFFLINE=1`. Pi-career never automatically overwrites, updates, moves, or deletes them.
361
+
362
+ ### `/career-tools [managed|raw|status]`
363
+
364
+ Control which Career tools are active in model context.
365
+
366
+ - `/career-tools managed` keeps only the compact `career_run` workflow active. This is the default and recommended mode.
367
+ - `/career-tools raw` also activates `career_core_discover`, `career_core_resume`, and `career_core_job` for explicit schema/debugging work.
368
+ - `/career-tools status` reports the current tool mode.
369
+
370
+ This command changes only the active model-tool surface. It does not change slash-command behavior, runtime resolution, privacy boundaries, or compatibility validation.
371
+
372
+ ## Managed agent workflow
373
+
374
+ Normal users do not need to call raw JSON tools. The package's Agent Skill instructs Pi to use `career_run`:
375
+
376
+ 1. `context` obtains ephemeral handles for eligible originals and the current vacancy;
377
+ 2. `analyze` and `match` return compact projections backed by complete in-memory Core results;
378
+ 3. suggestion, replacement, and variant proposals must pass the corresponding Core review command;
379
+ 4. `detail` hydrates only the requested evidence, warning, check, change, document, or raw section;
380
+ 5. non-PDF `variant-review` ends its turn so `/career-review` can collect an explicit local selection and prepare a later user message;
381
+ 6. `materialize` requires that unchanged review handle and exactly the user-selected retained IDs;
382
+ 7. only the user may separately run `/career-save <variant-handle>` for unchanged preview and confirmation.
383
+
384
+ Handles and complete results remain bounded in process memory and disappear on session/branch replacement, reload, or shutdown. They are not result files and cannot be reconstructed safely from chat text.
385
+
386
+ The raw tools are retained for advanced compatibility work only:
387
+
388
+ - `career_core_discover`
389
+ - `career_core_resume`
390
+ - `career_core_job`
391
+
392
+ When raw mode is explicitly enabled, discovery-first use remains mandatory: capabilities → operations → schema list/export/bundle → exact JSON input.
393
+
394
+ ## External Career Core runtime
395
+
396
+ `pi-career` contains no native Career Core binary. A Core-backed command resolves a compatible runtime in this fixed order:
397
+
398
+ 1. absolute `CAREER_CLI_PATH`;
399
+ 2. `career` on `PATH`;
400
+ 3. package-local exact `@revazi/career@0.2.0`;
401
+ 4. bounded acquisition of exact `@revazi/career@0.2.0` from the canonical npm registry.
402
+
403
+ Runtime installation is separate from loading the local Pi package. `/career-setup`, `/career-library`, `/career-application`, `/career-workbench`, and `/career-review` itself do not resolve or invoke Core; `/career-review` requires a still-live review produced earlier by `career_run`. `/career-vacancy`, `/career-analyze`, `/career-match`, `career_run`, and the raw tools do need Core.
404
+
405
+ Extension initialization requires macOS or Linux and fails unsupported platforms with one payload-free `unsupported_platform` error before registering any command/tool or doing route work. Before private document stdin opens on a supported platform, the selected executable must pass the exact managed Career Core 0.2.0 operation and schema compatibility checks. An invalid explicit `CAREER_CLI_PATH` fails without fallback.
406
+
407
+ The pi-career runtime target matrix is:
408
+
409
+ | Operating system | Architecture | Runtime target | Requirement |
410
+ | --- | --- | --- | --- |
411
+ | macOS | ARM64 | `darwin-arm64` | native Apple silicon |
412
+ | macOS | x64 | `darwin-x64` | native Intel |
413
+ | GNU/Linux | x64 | `linux-x64-gnu` | glibc 2.35+ |
414
+ | GNU/Linux | ARM64 | `linux-arm64-gnu` | glibc 2.35+ |
415
+ | musl Linux | x64 | `linux-x64-musl` | detected musl runtime |
416
+ | musl Linux | ARM64 | `linux-arm64-musl` | detected musl runtime |
417
+
418
+ The platform-specific optional packages are internal launcher details; install or acquire only exact `@revazi/career@0.2.0`. Pi-career validates the launcher's exact ordered six-package v2 manifest and lockstep versions before direct execution, while the launcher remains authoritative for native selection and integrity. Windows remains unsupported.
419
+
420
+ To prohibit acquisition:
99
421
 
100
422
  ```bash
101
- pi remove git:github.com/revazi/pi-career
423
+ PI_OFFLINE=1 pi --no-session
102
424
  ```
103
425
 
104
- Version `0.1.0` is published as the public npm package `pi-career` with no lifecycle scripts, package-owned runtime npm dependencies, or bundled Pi peer contents. The npm tarball carries the same two unsigned, hash-verified, not-notarized native executables as reviewed local and Git installations; it does not build them with Cargo on the user's machine.
426
+ Offline Core-backed use then requires a compatible `CAREER_CLI_PATH`, `career` on `PATH`, or package-local launcher. Acquisition receives no resume or vacancy input, but it may leave ordinary npm cache or `_npx` data; this is not secure erasure.
427
+
428
+ ## Privacy and persistence
429
+
430
+ Use `pi --no-session` when you do not want a new Pi session JSONL. In a persisted session, review the package's consent prompt before continuing with private content.
431
+
432
+ Possible persistence surfaces are distinct:
433
+
434
+ - **Package config:** canonical resume-root paths, bounded labels, and an optional variation-directory suggestion; never resume text, vacancy text, or full Core output.
435
+ - **Pi session:** consent, application/vacancy workflow entries, bounded result cards, and potentially tool arguments/results or submitted workbench messages.
436
+ - **Model provider:** only content you submit through ordinary Pi model interaction; `/career-workbench` makes the private payload visible before submission, while `/career-review` prepares only an ephemeral handle and selected canonical IDs.
437
+ - **Approved local variant files:** exact assisted Markdown/text bytes plus bounded marker/sidecar metadata only after `/career-save` preview and confirmation; never full Core JSON.
438
+ - **npm cache:** ordinary package-acquisition data, never private Career Core stdin.
105
439
 
106
- The `v0.1.0` release consists of the exact npm version, an unsigned annotated Git tag, and a GitHub Release; the reviewed full commit SHA and exact npm version are the installation coordinates. There is no crate publication, custom release asset, signing, or notarization. Both the package-owned production audit and complete development/host-Pi audit are clean at the explicit low threshold. Native-license evidence received documented sole-maintainer review, not independent legal review; see [`docs/releasing.md`](docs/releasing.md).
440
+ `pi-career` does not create payload/result temporary files, export full Core JSON, overwrite originals, or automatically save assisted resumes. Explicit `/career-save` files are local, private-mode, assisted/non-authoritative, and excluded from analysis/matching. Searchable PDF extraction is local, bounded, and network-disabled.
107
441
 
108
- ## Contributor build and verification
442
+ See [`SECURITY.md`](SECURITY.md), [`docs/design.md`](docs/design.md), and [`docs/product-flow.md`](docs/product-flow.md) for the complete boundary and threat model.
109
443
 
110
- Node.js 22.19 or newer is required for development checks; release verification uses npm 10.9.3 from the Node 22.19 CI toolchain. TypeScript under `src/` is authoritative. `dist/index.js` is its reproducible generated bundle and is intentionally tracked with the reviewed native runtimes so clean local, public-Git, and npm packages load without development dependencies. Node build/test tooling stays as directly executed `.mjs` under `scripts/` and `tests/` and is excluded from the package artifact. Pi-provided packages remain external peers.
444
+ ## Current limitations
445
+
446
+ - Supported original formats: searchable PDF, Markdown, and UTF-8 text.
447
+ - No OCR, DOCX/Pages editing, vacancy URL fetching, or PDF layout reconstruction.
448
+ - No automatic resume or application-workspace saving; explicit materialized-variant saving is private Markdown/text only on supported macOS/Linux filesystems.
449
+ - PDF workbench output is targeted manual guidance only.
450
+ - Assisted variants remain non-authoritative and cannot be reranked as originals.
451
+ - Matching is conservative workflow guidance, not a hiring prediction or proprietary ATS simulation.
452
+ - Supported runtime targets are `darwin-arm64`, `darwin-x64`, `linux-x64-gnu`, `linux-arm64-gnu`, `linux-x64-musl`, and `linux-arm64-musl`; Windows is unsupported.
453
+
454
+ The future application-workspace contract is documented in [`docs/application-workspaces.md`](docs/application-workspaces.md); those filesystem-writing phases are not implemented.
455
+
456
+ ## Development
457
+
458
+ TypeScript under `src/` is authoritative. `dist/index.js` and `dist/pdf-worker.js` are reproducible tracked bundles for clean local and Git loading.
111
459
 
112
460
  ```bash
113
461
  npm ci
114
462
  npm run build
115
- git diff --exit-code -- dist/index.js
463
+ git diff --exit-code -- dist/index.js dist/pdf-worker.js
464
+ npm run bench:tokens
465
+ npm run bench:tokens:compare
116
466
  npm run check
117
- npm run test:bundled-runtime
467
+ npm run test:runtime-resolution
468
+ npm run test:career-package
118
469
  npm run audit:production
119
470
  npm run audit:full
120
471
  npm run check:publish
121
472
  PI_OFFLINE=1 npm run test:pi-smoke
122
473
  PI_OFFLINE=1 npm run test:install
474
+ npm run test:compat
123
475
  git diff --check
124
476
  ```
125
477
 
126
- `npm run build` rebuilds only `dist/index.js`; it never builds or downloads native runtimes. `npm run check:runtime-artifacts` enforces the runtime manifest, provenance, five-file source artifact contract, target magic, exact hashes/sizes/modes, and package bounds. `npm run audit:production` requires zero package-owned production vulnerabilities and `npm run audit:full` requires zero vulnerabilities across the complete development/host-Pi tree, both from an explicit low-severity threshold. Production/full audit and package commands invoke `process.execPath` with the absolute npm CLI derived from that real Node installation, verify any inherited `npm_execpath`, and remove omit/include/audit-level/`NODE_ENV` overrides; npm and tar are never selected from `PATH`. `npm run check:publish` is a direct Node authoritative readiness orchestrator but does not publish anything: it runs both strict audits and the package checks. Strict bounded parsing rejects duplicate decoded keys in audit and pack JSON. The package check uses verified absolute `/usr/bin/tar`, proves the tarball has no `node_modules` or Pi package contents, keeps exactly `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`, `@earendil-works/pi-tui`, and `typebox` as wildcard external peers, extracts the artifact, loads it, executes the bundled runtime, and performs an isolated install/list/remove smoke. Any future audit finding blocks publication and requires remediation rather than a checked-in acceptance baseline.
478
+ `npm run bench:tokens` collects the current synthetic model-visible surfaces, including Pi's stable always-visible Skill name/description metadata and the complete on-demand `career-core` Skill for matching career tasks. Linked Skill references and machine-specific discovery paths stay outside that boundary. `npm run bench:tokens:compare` verifies the surface digest, immutable `c7d7634…` before and `7ed36c4…` after source/Skill trees and frozen bytes from Git history, exact frozen before/after deltas, managed serialization parity, semantic/privacy invariants, budgets, and no current workflow regression relative to the frozen after evidence. Later source may differ and improve without rewriting that historical snapshot. The finalized frozen evidence records 25,652 → 21,552 aggregate workflow tokens (15.98% reduction) with no workflow regression.
127
479
 
128
- Optional local compatibility uses an explicitly supplied reviewed Career Core fixture root while still executing the bundled runtime:
480
+ `npm run test:career-package` is the network-capable exact-package integration test. `npm run test:compat` skips unless an explicitly reviewed fixture checkout is provided:
129
481
 
130
482
  ```bash
131
483
  CAREER_CORE_FIXTURE_ROOT=/absolute/path/to/reviewed/career-core \
132
484
  npm run test:compat
133
485
  ```
134
486
 
135
- Hosted CI needs no separate Core checkout or provider credentials. Its native matrix executes every claimed target: Ubuntu x64 GNU and macOS arm64.
136
-
137
- ## Privacy before document operations
487
+ `npm run build` rebuilds JavaScript bundles only; it never builds or downloads native runtimes. `npm run check:publish` verifies readiness and package contents but does not publish anything.
138
488
 
139
- Pi may persist native-tool arguments/results and workflow custom entries in session JSONL. The slash commands require the displayed session-persistence decision before the first private vacancy or compact result card is appended to a persisted session. Global config stores only canonical resume-root paths and bounded labels—never resume text, vacancy text, or Core output. Full Core JSON is not stored by the workflow, and custom workflow entries are excluded from LLM context.
489
+ ## Security and release provenance
140
490
 
141
- For direct native-tool use, make the same explicit persistence decision before placing private resume or job content in `input_json`. Prefer a new transient run when session saving is not wanted:
142
-
143
- ```bash
144
- pi --no-session
145
- ```
491
+ The exact reviewed external runtime coordinate is [`@revazi/career@0.2.0`](https://www.npmjs.com/package/@revazi/career/v/0.2.0), published from Career Core commit [`536690632884c17336cc3c108f1bba0f254b862b`](https://github.com/revazi/career-core/tree/536690632884c17336cc3c108f1bba0f254b862b). Its launcher owns native target/libc selection and package metadata, provenance, file invariants, size, format, and SHA-256 verification. Registry integrity and SLSA v1 provenance were reviewed for the user-facing launcher and all six lockstep native packages. Pi-career validates that exact six-package v2 manifest and supports only its macOS/Linux targets.
146
492
 
147
- This is not a secure-erasure guarantee and does not remove previous sessions, shell history, backups, provider copies, or saved output. Local Pi-context approval also does not authorize sending content to an external model/provider.
493
+ Historical published `pi-career` v0.1.0 coordinates are retained for verification:
148
494
 
149
- Start with `career_core_discover`, invoke only capabilities reported as available, and export the exact input schema before document calls. If the adapter reports `result_too_large` or `result_too_many_lines`, do not request or use partial output. Full-result export is not yet available through pi-career.
495
+ - npm: [`pi-career@0.1.0`](https://www.npmjs.com/package/pi-career/v/0.1.0)
496
+ - Git commit: [`967da62503bc8a97c070946f6506ea3471baeb34`](https://github.com/revazi/pi-career/tree/967da62503bc8a97c070946f6506ea3471baeb34)
497
+ - npm integrity: `sha512-mmbDdWDyWz77f2uLzZECJT9E6w1ZRCJjYFrUnZd3ldoS6ehEa5DrCENIfavHR5xMOFi0of6AVQ35ZTxwpeDeAQ==`
498
+ - GitHub Release: [`v0.1.0`](https://github.com/revazi/pi-career/releases/tag/v0.1.0)
150
499
 
151
- ## Maintainer and support
500
+ That historical release bundled native artifacts; `pi-career@0.2.0` and later do not. Historical evidence remains in [`docs/native-dependency-inventory.md`](docs/native-dependency-inventory.md), [`docs/releasing.md`](docs/releasing.md), and [`docs/licenses/`](docs/licenses/).
152
501
 
153
- Maintained by [Revaz Zakalashvili](https://github.com/revazi). Use this repository's Issues for sanitized bugs and scoped feature requests, follow [`CONTRIBUTING.md`](CONTRIBUTING.md) for changes, and follow [`SECURITY.md`](SECURITY.md) for vulnerabilities. Never place private career content or vulnerability details in an ordinary issue.
502
+ Use [Issues](https://github.com/revazi/pi-career/issues) only for sanitized bugs and scoped feature requests. Follow [`SECURITY.md`](SECURITY.md) for private vulnerability reports. Never attach real resumes, vacancies, credentials, provider responses, or Pi session files to a public issue.
154
503
 
155
504
  ## License and provenance
156
505
 
157
- Licensed under either Apache-2.0 or MIT, at your option. See [`LICENSE-APACHE`](LICENSE-APACHE), [`LICENSE-MIT`](LICENSE-MIT), [`NOTICE`](NOTICE), and the package-bounded runtime license/notices files under [`runtime/`](runtime/).
506
+ Licensed under either Apache-2.0 or MIT, at your option. See [`LICENSE-APACHE`](LICENSE-APACHE), [`LICENSE-MIT`](LICENSE-MIT), and [`NOTICE`](NOTICE).
158
507
 
159
- The locked normal/build dependency evidence for both native CLI targets is in [`docs/native-dependency-inventory.md`](docs/native-dependency-inventory.md). The package preserves the exact selected MIT/copyright texts for every reachable crate group, Rust 1.97.1 Standard Library evidence, and the required [`Unicode License V3`](docs/licenses/Unicode-3.0.txt) text under [`docs/licenses/`](docs/licenses/). `npm run check:native-licenses` enforces that payload. The inventory is evidence, not legal advice or automated release approval; [`docs/releasing.md`](docs/releasing.md) requires documented human sign-off and transparently records sole-maintainer review when independent review is unavailable.
508
+ The external `@revazi/career` distribution carries its own native licenses and notices.