pi-career 0.2.0 → 0.4.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.
@@ -1,8 +1,67 @@
1
1
  # Product flow roadmap
2
2
 
3
- The cross-repository migration plan and measured findings are recorded in [`career-run-roadmap.md`](career-run-roadmap.md). Career Core Phase 8 and the first managed `career_run` implementation are complete; package-owned saving and PDF extraction expansion remain later phases.
3
+ The cross-repository migration plan and measured findings are recorded in [`career-run-roadmap.md`](career-run-roadmap.md). Career Core Phase 8, the first managed `career_run` implementation, the threat-reviewed package-owned Markdown/text save workflow in [`variant-save-workflow.md`](variant-save-workflow.md), and application-workspace Gate 1 in [`application-workspaces.md`](application-workspaces.md) are implemented. Synthetic PDF compatibility covers reviewed Chromium-generated tagged/untagged and ReportLab-generated two-page documents, embedded-font and multi-column layouts, and fail-closed text-unavailable cases. The Git-history/tree/hash-bound token-optimization study is complete: its frozen before/after evidence includes Pi Skill discovery and matching-task full-Skill context and records a 15.98% aggregate workflow reduction with no workflow regression. Application-workspace assisted resume artifacts, deletion, repair/adoption/archive/sync, broader workspace files, and further PDF extraction expansion remain later separately approved phases.
4
4
 
5
- ## Current phase: managed agent tool and deterministic slash commands
5
+ ## Approved target: `/career` as a local Pi application
6
+
7
+ ### Application catalog filter (P3-49)
8
+
9
+ The shared Applications view supports bounded transient text and lifecycle filters in both TUI (`/` for text, `l` for All/Preparing/Applied/Interviewing/Closed, then clear with `k`) and RPC. Text matching is a deterministic, case-sensitive substring over the already-safe displayed company/role labels, lifecycle status, readiness text, and aggregate classification. Filters perform no Unicode normalization and never inspect paths, document bodies, hashes, raw errors, or invalid-child details; UUID row identity remains distinct when labels match. Filter state exists only in the current overlay instance, is clearable, and creates no config, workspace, session, or model/provider entry. Browsing, opening, filtering, and clearing do not attach, activate, call Career Core, submit messages, or expose Career Skill/tool metadata.
10
+
11
+ The application-centric roadmap treats `/career` as a user-invoked modal application inside Pi. It is not a chat prompt, model command, or full-screen replacement for Pi. Its execution model has three separate planes:
12
+
13
+ | Plane | User trigger | Execution boundary | Model/session effect |
14
+ |---|---|---|---|
15
+ | Overlay navigation | Open `/career`; browse, search, filter, open local detail, or review readiness | Local extension UI and bounded filesystem reads | No provider/model call, message submission, Career-specific model context, attachment, or session append |
16
+ | Deterministic work | Explicit Analyze or Match action | Career Core through the reviewed resolver, with existing compatibility, stdin, cancellation, and output bounds | No provider/model call or model-context activation; only separately approved persistence may append or write |
17
+ | Model assistance | Explicit Ask Pi/Regenerate/Suggest/Explain action followed by review and ordinary user submission | One application-scoped Pi assistance session using the bundled Skill and primary `career_run` tool | Career context and tokens begin only for this action; no package-initiated submission |
18
+
19
+ “Token-free overlay” means the first two planes cause no model turn and add no Career document, result, Skill content, or tool contract to a model request. The target also removes Career-specific Skill discovery metadata and tool schemas from ordinary Pi sessions that have not been explicitly activated for Career assistance. A local Core operation can consume CPU and may perform the already bounded exact-package acquisition before private stdin; it still consumes no model tokens. `PI_OFFLINE=1` disables that acquisition for offline testing/use but is not required for normal overlay operation.
20
+
21
+ ### Read, cache, and refresh contract
22
+
23
+ One overlay open or explicit refresh takes one bounded catalog snapshot. List views use only that projection and never read every document body. Exact document bytes and larger local details are loaded lazily only after the user opens the corresponding detail or starts an eligible action. Derived readiness is calculated locally from validated current metadata; it is never persisted or model-derived.
24
+
25
+ Library originals (Markdown, text, or extracted searchable PDF text) and attached application job descriptions, selected originals, and effective Resumes offer a separate **Preview document (local only)** action from their metadata detail. TUI uses `v`; RPC selects the named action after opening a row. Opening a row or a one-item list never reveals the body. Preview rescans or reloads the validated attached authority and checks the selected identity and text digest before display; unavailable, drifted, unsafe-control, or >12,000-byte text is rejected with a fixed payload-free message rather than truncated. The effective Resume is labeled original or tailored assisted, never presented as an original when assisted. Preview is read-only and transient: Back/Escape drops its text, no editor approval, Core call, provider send, attachment, session entry, or file write is performed. TUI displays six soft-wrapped lines per explicitly labeled page with ↑/↓ navigation instead of silently clipping long previews; RPC shows the full bounded exact text. No path or binary/PDF bytes are displayed. This is local UI authorization, not consent to model submission. Catalog, detail, and rendered-view caches are process-memory-only, bounded, and scoped to the current overlay instance. Closing the overlay drops UI/search/filter/cursor state. There is no persisted index, background watcher, polling loop, URL fetch, or speculative Core/model work. Returning from a dialog or completed mutation refreshes the affected bounded projection. Explicit Resume-library Rescan shows a local cancellable progress state and replaces the snapshot only after a complete scan; cancellation discards the candidate projection, so partial reads never masquerade as fresh complete state.
26
+
27
+ The Resume-library list and detail explicitly label every indexed record as `Original` or `Assisted variant`, show format, availability, current-session analysis state, and payload-free scan notices, and keep quarantined/unreadable entries non-authoritative. An available highlighted Original may run deterministic Analyze directly: its exact in-memory document/root/format/text-digest identity is revalidated after confirmation and again at Core submission, with no fallback chooser or alternate Resume. Drift, stale/capped scans, oversized input, assisted variants, and quarantined metadata fail closed. Root add/remove and rescan remain explicit local actions; removal changes config only after confirmation and never changes files beneath the root.
28
+
29
+ Before any mutation, Core invocation, attachment, or model handoff, the adapter revalidates the selected identity, root, referenced bytes, and action prerequisites under the owning workflow’s race rules. Drift invalidates the action and requires a fresh view; cached display data never becomes write, Core, or prompt authority.
30
+
31
+ ### Session and model-context boundary
32
+
33
+ Browsing never attaches an application. The approved #64 attachment stores only the exact bounded, path-free application/root identity pointer in a Pi custom entry after the separate session-persistence decision; it stores no document, result, prompt, or provider content and does not itself activate a Career Skill/tool or authorize provider submission. Workspace files remain the application authority.
34
+
35
+ An explicit assistance action revalidates the application and uses one company/role per assistance session so prior-company conversation content cannot leak into another application. The action may prepare a visible editor message and may establish a fresh application-scoped Pi session, but it must never call `sendMessage()`, `sendUserMessage()`, or an equivalent automatic submission path. Only the user’s later ordinary submission activates the provider boundary. Within that explicitly activated assistance session, the Career Skill and compact `career_run` contract remain stable rather than being toggled every turn, preserving prompt-cache reuse. The exact raw compatibility tools remain inactive unless the user explicitly requests raw/debug mode.
36
+
37
+ Restart, `/new`, branch, detach, unavailable-root, and identity-drift behavior must revalidate the bounded pointer and fail closed; no session is reconstructed from workspace files alone. Overlay route state and cached private bytes are never written to the Pi session. Session persistence, application attachment, assistance activation, provider submission, artifact mutation, and deletion are distinct approvals.
38
+
39
+ ### Ordered delivery and acceptance invariants
40
+
41
+ Application state uses one schema; former state `.v1`/`.v2` identifiers are unsupported, and append-only revision numbers remain only integrity/history controls. The Resume-library and persistent-Applications slices are implemented on #64's exact attachment, command-authority, and context-on-demand lifecycle. A valid attached application is the default `/career` detail; otherwise the deterministic persistent catalog opens. Detail shows lifecycle, all three readiness components, effective-Resume authority, current-session match state, and last-update metadata. Applied remains independent from readiness and requires an extra visible warning when the package is incomplete. Remaining user-visible work advances through job/effective-Resume, cover-letter, and integrated preparation slices before #59 validates the complete product.
42
+
43
+ Every overlay slice must prove with synthetic scenarios that:
44
+
45
+ 1. opening, closing, resizing, browsing, filtering, searching, and local detail navigation make no provider/model call, submit no message, append no session entry, and activate no Career-specific model context;
46
+ 2. list rendering uses one bounded metadata snapshot and does not read document bodies;
47
+ 3. local Analyze and Match remain explicit, cancellable Career Core operations with zero model calls/tokens;
48
+ 4. cached state is revalidated before mutation, Core use, attachment, or handoff, and observed drift fails closed;
49
+ 5. only an explicit assistance action may prepare Career model context, and preparation remains visibly reviewable without automatic submission;
50
+ 6. application attachment neither implies assistance activation nor provider or mutation consent;
51
+ 7. `career_run` remains the primary managed tool once assistance is active, while `career_core_discover`, `career_core_resume`, and `career_core_job` retain their exact compatibility names and stay inactive by default;
52
+ 8. branch/session replacement clears process-local handles and uses only the fresh Pi context;
53
+ 9. no persisted index, watcher, prompt/result cache, document duplication, telemetry, or background work is introduced; and
54
+ 10. benchmarks report ordinary model turns outside activated Career assistance sessions as zero Career-specific context tokens, separately from activated workflows, and preserve stable activated-session surfaces for prompt caching.
55
+
56
+ TUI overlay and RPC select/confirm dialogs render one Career view model. **Applications** and **Resumes** are its only peer top-level destinations. Setup belongs under Resumes; job description, Analyze, Match, Workspace, and Ask Pi are application or Resume context. The existing `/career-setup`, `/career-library`, `/career-application`, `/career-vacancy`, `/career-match`, `/career-analyze`, `/career-workbench`, and `/career-workspace` commands remain direct compatibility routes into that same hierarchy rather than tabs. A contextual route shows its full breadcrumb and Escape/Back returns to its owning destination; TUI Left/Right or Tab switches only the two destinations. RPC **Switch view** remains available but likewise lists only Applications and Resumes.
57
+
58
+ Opening, browsing, filtering, switching destinations, viewing help, and highlighting do not attach, activate assistance, bind a Resume, call Core or a provider, or submit a message. Attach, add/remove/rescan library roots, create application, selected-original binding, analyze/match, vacancy edit/clear, status update, detach, Ask Pi, and Gate 1 workspace management are explicit contextual actions on that same model. Attached selected-original binding uses the existing exact workspace preview and separate confirmation, while Analyze and Match require that authoritative binding instead of falling back to another library Resume. Application detail and prerequisite/empty states show current state, a derived recommended next action, and safe alternatives without executing that recommendation. Footer hints show only current navigation and eligible actions; TUI help describes the hierarchy without performing work.
59
+
60
+ The centered TUI modal has explicit host margin, one complete rounded theme-colored Unicode frame, connected separators, and equal interior horizontal padding. All header, breadcrumb, destination, body, preview, and footer rows are wrapped or bounded against the inner content width so the complete ANSI-styled outer line stays within Pi's supplied width. Its terminal-derived row budget always retains header, destinations, footer, and bottom border while scrolling only the content region; long catalogs keep selection visible, and detail/help expose Up/Down scrolling. Widths or heights too small for the minimum complete padded frame show only bounded resize guidance and no private preview bytes. TUI list labels wrap instead of being clipped so warning/state wording remains available at narrow supported widths; selection also has a visible text marker independent of theme color. Rendering is recomputed at the supplied viewport, so resizing does not retain stale layout or theme-colored output.
61
+
62
+ The integrated application journey is presented as persisted package review rather than a second workflow engine. Applications detail classifies job description, selected Resume, cover letter, effective Resume authority, readiness, match evidence, and application classification; it exposes a derived contextual next action, while existing alternatives remain available in the view navigation and action list. The recommendation is informational only: create/attach, job-description editing, Original selection, Analyze/Match, workspace materialization/cover-letter authoring, and Applied status each retain their existing explicit confirmation and cancellation boundaries. Closing/reopening reconstructs the recommendation from the current validated workspace/catalog and explicit session attachment/activation; no overlay progress is authority.
63
+
64
+ ## Implemented current phase: managed agent tool and deterministic slash commands
6
65
 
7
66
  The normal active model surface is one compact `career_run` tool. The exact raw compatibility tools remain registered but inactive until `/career-tools raw` explicitly enables them:
8
67
 
@@ -12,16 +71,15 @@ The normal active model surface is one compact `career_run` tool. The exact raw
12
71
 
13
72
  It also registers:
14
73
 
15
- - `/career-setup` for library/privacy onboarding and a suggestion-only preferred variation directory—not external CLI installation
16
- - `/career-library` for explicitly configured searchable PDF, Markdown, and text resume roots, with actionable extraction notices
17
- - `/career-application` for session-scoped company/role identity and vacancy/result isolation
18
- - `/career-vacancy` for bounded vacancy input after session-persistence consent
19
- - `/career-match` for deterministic multi-resume matching and conservative ranking
20
- - `/career-analyze` for deterministic single-resume readiness detail
21
- - `/career-workbench` for a bounded, guided, visibly reviewable rebuild handoff to the user's normal Pi editor
74
+ - `/career` and `/career-setup`, `/career-library`, `/career-application`, `/career-vacancy`, `/career-match`, `/career-analyze`, `/career-workbench`, and `/career-workspace` to open one Career view model at different starting views; TUI overlay and RPC select/confirm dialogs are only renderers of that model
75
+ - `/career-setup status` and `/career-library status` for local configuration/library notices
76
+ - `/career-application status|clear` for attached detach or session-scoped application context
77
+ - `/career-vacancy clear` for the existing fail-closed vacancy clear, including print/JSON when unattached
78
+ - `/career-review` for TUI-only, bounded inspection and explicit selection of current non-PDF retained variant changes
79
+ - `/career-save` for user-only TUI/RPC exact preview, confirmation, and no-clobber local saving of one current Markdown/text materialization
22
80
  - `/career-tools` to switch between the managed-only and advanced raw model-tool surfaces
23
81
 
24
- `career_run`, the raw compatibility tools, `/career-vacancy`, `/career-match`, and `/career-analyze` invoke the compatible Career Core route selected by the external resolver. Managed compatibility is validated before private input, and the reviewed exact package may be acquired only after local routes fail unless `PI_OFFLINE=1`. `career_run` validates Phase 8 operation/schema contracts internally, resolves current originals/vacancy through ephemeral handles, keeps complete results in bounded process memory, and exposes compact detail hydration without nested `input_json`. Setup/library scanning remains local. `/career-application` manages consented session state only. `/career-workbench` does not invoke Core or a provider/model itself: it prepares an ordinary editor message containing one original resume and, only for tailoring, the current vacancy. Guided modes cover complete score explanation, reviewed improvement suggestions, a question-led factual interview before reviewed replacements, direct reviewed exact replacements, and vacancy-specific variant review. The user must review and submit that message separately through Pi.
82
+ `career_run` and the raw compatibility tools invoke the compatible Career Core route selected by the external resolver on supported macOS/Linux systems. The `/career*` view commands do not invoke Core while browsing. Package metadata rejects other systems, and direct local/Git extension initialization registers no command/tool and fails with `unsupported_platform` before route work or private stdin. Managed compatibility is validated before private input, and the reviewed exact package may be acquired only after local routes fail unless `PI_OFFLINE=1`. `career_run` validates Phase 8 operation/schema contracts internally, resolves current originals/vacancy through ephemeral handles (workspace sources when a persistent application is attached and activated), keeps complete results in bounded process memory, and exposes compact detail hydration without nested `input_json`. Setup/library scanning remains local. Opening or browsing a Career view never attaches, activates assistance, calls Core or a provider, or submits a message. Attach remains confirmation-gated, path-free, and assistance-inactive. `/career-review` also invokes neither Core nor a provider: it reads one current in-memory non-PDF variant review, requires warnings/discards acknowledgment and exact per-change inspection before inclusion, then prepares a later editor message containing only the unchanged review handle and selected canonical IDs.
25
83
 
26
84
  Binding boundaries:
27
85
 
@@ -39,19 +97,23 @@ Binding boundaries:
39
97
  - workbench prompts keep originals immutable, omit absolute source paths, treat document text as untrusted data, rerun complete deterministic baselines after submission, and require Career Core review of external suggestions, replacements, and variant changes
40
98
  - workbench prompts may include a privacy-reduced preferred variation-directory display path from setup; the selected agent recommends it first only after a separate user request and receives no automatic write authority
41
99
  - review proposals use verbatim source targets and in-range evidence, prefer single-line targets, make one review attempt, and surface discard codes instead of model-led repair/retry loops
100
+ - `career_run variant-review` terminates its turn; the TUI selector defaults every retained change to excluded, pages exact before/after/evidence locally, then pages selected changes together as compact labeled exact records, permits direct final-stage reopening of each record, and requires a separate prepare-or-back decision
101
+ - review selection is process-memory-only: only the final prepare choice puts the ephemeral review handle and selected canonical IDs in the editor; pi-career appends no selection entry and performs no Core call
102
+ - PDF review changes remain manual guidance; `/career-review` and `career_run materialize` reject PDF review handles because extracted text cannot preserve the styled document
42
103
  - raw tool JSON remains authoritative; managed projections refer to complete authoritative in-memory results by handle, while prose hydrates only requested evidence and retained items
43
104
  - PDF workbench output is suggestion-only because extracted text cannot expose or preserve visual layout; Markdown/text prompts require existing structure and unchanged wording to remain intact
44
- - no full-result file export unless a separate bounded local-file workflow is designed and tested
105
+ - no full-result file export; `/career-save` persists only exact approved assisted document bytes and bounded marker/sidecar metadata
106
+ - `/career-workspace` is absent from model tools, calls no Core/runtime/provider/model/network/child process, appends no session entry, and persists only separately previewed Gate 1 config/marker/manifest/state/vacancy metadata under one strict disjoint private root
45
107
 
46
- The approved workflow specification fixes command behavior, persistence format, non-TUI behavior, bounded UI, and cancellation ownership. Print/JSON modes fail closed except for the pure `/career-vacancy clear` state action. Company/role isolation and future opt-in artifact persistence follow the separate [`application-workspaces.md`](application-workspaces.md) contract.
108
+ The approved workflow specification fixes command behavior, persistence format, non-TUI behavior, bounded UI, and cancellation ownership. Print/JSON modes fail closed except for the pure `/career-vacancy clear` state action. Company/role isolation and implemented Gate 1 application state persistence follow the separate [`application-workspaces.md`](application-workspaces.md) contract. Workspace-assisted artifacts and deletion remain unimplemented Gates 2 and 3.
47
109
 
48
110
  ## Assisted handoff and later materialization
49
111
 
50
112
  The current workbench prepares private context in Pi's editor only. It does not call a model, hide the source payload, or write a document. Submitting is the user's separate provider action. The prompt directs the selected Pi agent to start with `career_run context`, use internal exact Phase 8 contract discovery, rerun and preserve complete deterministic baselines behind ephemeral handles, and pass external suggestions, replacements, or variant changes through the corresponding Career Core review before presenting them. The question-led rewrite mode reviews first, asks one bounded batch of user-verifiable factual questions, and waits for a later turn before drafting or reviewing exact replacements.
51
113
 
52
- For a non-PDF vacancy-specific variant, the first assisted turn must stop after review and ask the user to explicitly select Core-assigned canonical change IDs. Only a later turn may invoke deterministic materialization with exactly those selected IDs. The result remains assisted/non-authoritative and cannot enter authoritative analysis or matching. PDF workbenches stop after reviewed targeted changes for manual application and never materialize extracted text as a styled resume.
114
+ For a non-PDF vacancy-specific variant, the first assisted turn stops mechanically after review. In TUI, the user can run `/career-review <review-handle>` to page all warnings/discards and exact retained changes. Every change starts excluded and can be included only from its exact detail view. Continuing pages all selected exact records together with compact labels and permits direct read-only reopening of each one; a separate final choice either returns to review or prepares—but never submits—the later user message with exactly the selected Core IDs and unchanged handle. Only after the user reviews and submits that message may deterministic materialization run. The result remains assisted/non-authoritative and cannot enter authoritative analysis or matching. PDF workbenches stop after reviewed targeted changes for manual application; PDF handles are rejected by selection and materialization and never turn extracted text into a styled resume.
53
115
 
54
- Automatic variant saving remains deferred. Setup now records or derives only a preferred destination suggestion: an explicit override wins, otherwise `variants/` under the selected original's configured root is recommended. It creates no directory or file. A future phase may save a newly materialized immutable assisted file only after separate local-file approval. It must not add provider fallback, automatic repair/retry, overwrite originals, auto-apply changes, or feed assisted output back into authoritative analysis/matching.
116
+ Automatic variant saving remains prohibited. Setup records or derives only a preferred destination suggestion and creates no directory or file. After a successful non-PDF materialization, the user may separately run `/career-save <variant-handle>`: it derives an eligible direct-child managed destination, shows the complete exact plan, requires unchanged preview plus separate confirmation, performs no-clobber private writes, and succeeds only after fail-closed rescanning excludes the artifact from originals. It does not add provider fallback, automatic repair/retry, original overwrite, auto-application, or authoritative reranking.
55
117
 
56
118
  ## Non-goals in this phase
57
119
 
@@ -60,4 +122,4 @@ Automatic variant saving remains deferred. Setup now records or derives only a p
60
122
  - source-document or full-Core-result persistence outside the approved config/custom-entry workflow
61
123
  - source document mutation
62
124
  - career-document publication/export, release-asset downloads, signing, or notarization
63
- - package-owned native binaries or platform claims beyond the exact reviewed `@revazi/career@0.1.1` catalog
125
+ - package-owned native binaries or platform claims beyond pi-career's six reviewed macOS/Linux targets; the launcher's additional upstream manifest entries are contract metadata, not support
@@ -0,0 +1,69 @@
1
+ # pi-career 0.4.0 release candidate
2
+
3
+ **Status: release-candidate metadata finalized; not a release-execution authorization.** Package and lockfile metadata, Skill metadata, the dated changelog, package assertions, release helpers, and README installation coordinate identify `0.4.0`. The complete local candidate ladder passed on 2026-10-04, including fixture parity against the exact reviewed Career Core `v0.2.0` checkout. The immutable candidate SHA is established only by the reviewed commit and is recorded externally rather than embedded self-referentially in tracked files. Tag creation, publication, and GitHub Release creation require clean same-SHA hosted evidence and separate explicit authorization.
4
+
5
+ ## Version rationale and scope
6
+
7
+ The selected **0.4.0** version reflects the substantial additive, user-visible application-centric workflow: one shared Career overlay across TUI/RPC, persistent application catalog and attachment, workspace-backed current vacancy and selected-original authority, explicit lifecycle/revision handling, readiness presentation, and the separately approved user-authored cover-letter transaction. This is not a breaking change to the canonical application-state contract. It does not justify 1.0: boundaries and later workspace gates remain deliberately narrow.
8
+
9
+ The candidate scope is only the implemented application-centric experience recorded in the dated `CHANGELOG.md` 0.4.0 entry: one shared overlay and views; application create/catalog/attach; library-root add/rescan/remove; confirmation-gated analyze/match, vacancy edit, status update, and workspace management; workspace-backed vacancy/selected-original authority and lifecycle; derived readiness/next action; and user-authored cover-letter handling. Legacy identity-only migration remains exact-label, canonical-byte-previewed, separately confirmed, and no-clobber. Preserve the exact `career_run` primary managed tool, raw compatibility names, Core contract, local-first runtime boundary, consent/privacy/cancellation guarantees, and native-free package. Release claims must be checked against the final source rather than copied from this proposal.
10
+
11
+ ### State and migration distinctions
12
+
13
+ Application-state revisions use the single canonical schema identifier `pi.career.application_state`. They have **no schema-version migration or compatibility reader**: former `.v1`/`.v2` and other unsupported identifiers fail closed, are not adopted/repaired/rewritten, and do not expose a trusted prefix. This is distinct from the separately versioned user configuration contract. Ordinary setup/mutations preserve canonical config v1; only the explicit application-root configuration flow can migrate config v1 to v2, after exact preview and separate user confirmation. Never imply that application-state changes migrate config, or that config migration converts application-state files. See [single application-state contract](single-application-state.md) and [workspace design](application-workspaces.md).
14
+
15
+ ### Deferred / not part of 0.4.0
16
+
17
+ No inferred future scope: workspace resume artifacts and deletion, arbitrary files/browsing, adoption, repair, rebind, archive, synchronization, encryption/secure deletion, broad artifact formats, provider-response/result persistence, automated submission, model/provider behavior, telemetry, MCP, Windows, new native targets, runtime/Core upgrades, or application-state migration. Any later workspace gate requires its own review/authorization. The separate `/career-save` workflow remains distinct.
18
+
19
+ ## Support claims (exact, no extrapolation)
20
+
21
+ - Node.js: `>=22.19.0` per package engine; do not advertise an upper tested range or a different minimum.
22
+ - Pi APIs: the README's exact claim is “1.0.0-compatible package APIs.” Development dependency pins are exact 1.0.2; they do not prove a broader tested compatibility range. Do not claim “Pi 1.0+” or infer newer/older versions.
23
+ - Career runtime: exact `@revazi/career@0.2.0`, managed Core 0.2.0 contract; not a range.
24
+ - Native targets, delegated to that reviewed launcher: `darwin-arm64`, `darwin-x64`, `linux-x64-gnu`, `linux-arm64-gnu`, `linux-x64-musl`, `linux-arm64-musl`. GNU Linux requires glibc 2.35+. No Windows or other target claim.
25
+
26
+ ## Privacy, retention, and screenshots
27
+
28
+ All examples, UI captures, and render checks use synthetic labels/documents, synthetic paths, and disposable sessions/workspaces only. Never use real user records, credentials, provider responses, or session content. A screenshot/render review may cover compact/wide TUI layout, overlay navigation/empty state, and representative RPC dialogs; check wrapping, clipping, visible consent/confirmation, and absence of unintended private detail. Do not inspect or modify protected PNGs. Any new image must be generated from synthetic fixtures, separately reviewed for metadata/content, and added to the exact package allowlist only if intentionally packaged; no screenshot is required for the release.
29
+
30
+ Local documents and Pi sessions, RPC clients, editor history, backups/snapshots/sync, provider systems, and npm cache are distinct retention surfaces. Exact runtime acquisition receives no private document stdin, but ordinary npm cache or `_npx` residue may remain; this is not secure erasure. Do not promise cache cleansing or secure deletion. Existing privacy and persistence descriptions remain authoritative.
31
+
32
+ ## Evidence matrix — prepared local candidate
33
+
34
+ The 2026-10-04 results below cover the prepared candidate content before its SHA is frozen. They are local release-candidate evidence, not production-wire acceptance and not a substitute for externally recorded same-SHA hosted evidence on the final reviewed commit.
35
+
36
+ | Gate / evidence | Current classification | Remaining release requirement |
37
+ | --- | --- | --- |
38
+ | Candidate identity | Package, root lockfile entries, Skill metadata, package assertions, release helpers, README coordinate, and dated changelog all identify 0.4.0. | Freeze the reviewed bytes once and record the resulting full SHA externally without adding a self-referential placeholder to tracked files. |
39
+ | Build / dist reproducibility | Passed immediately after `npm run build` against a temporary-index snapshot of the prepared candidate's tracked bundles. | On the clean committed SHA, run the standard immediate `git diff --exit-code -- dist/index.js dist/pdf-worker.js` proof. |
40
+ | Token and complete adapter checks | `bench:tokens`, `bench:tokens:compare`, and `check` passed locally. | Require the protected same-SHA `Adapter checks` result after commit/push. |
41
+ | Exact Career package runtime integration | Passed locally with exact `@revazi/career@0.2.0`, including synthetic managed discovery and representative resume/job operations. | Require the same-SHA six-target hosted matrix; this local result is not production-wire evidence. |
42
+ | Production and full audits | Both passed with zero vulnerabilities at the explicit low threshold under exact Pi 1.0.2 development pins. | No baseline, exception, dependency downgrade, or lockfile workaround is permitted. |
43
+ | Package/publication readiness | `check:publish` passed; the candidate remains native-free with four wildcard Pi peers and no production/optional/bundled dependency tree or lifecycle/publication script. | Rerun on the clean committed candidate and in the authorized release workflow. |
44
+ | Fixture-backed compatibility | Passed, not skipped, against reviewed Career Core commit `536690632884c17336cc3c108f1bba0f254b862b` / `v0.2.0`. | Keep the fixture checkout read-only and local; do not add its machine path to runtime code or hosted CI. |
45
+ | Offline Pi load and isolated install/remove | Both passed locally with `PI_OFFLINE=1`. | Preserve the offline no-acquisition boundary. |
46
+ | Registry state | Canonical registry query confirmed `pi-career@0.4.0` absent. | Reconfirm authoritative absence immediately before any first, separately authorized publication attempt. |
47
+ | Hosted candidate evidence | Intentionally external to the tracked candidate so evidence cannot change its SHA. | Require same-SHA `Adapter checks`, then dispatch `external-career.yml` on that exact ref and require all six jobs before release authorization. |
48
+
49
+ The complete local ladder passed: `npm ci`; `npm run build` plus immediate candidate-relative dist comparison; `npm run bench:tokens`; `npm run bench:tokens:compare`; `npm run check`; `npm run test:runtime-resolution`; `npm run test:career-package`; `npm run audit:production`; `npm run audit:full`; `npm run check:publish`; `PI_OFFLINE=1 npm run test:pi-smoke`; `PI_OFFLINE=1 npm run test:install`; fixture-backed `npm run test:compat`; `npm ls --omit=dev --depth=0`; `git diff --check`. The exact Pi development pins remain 1.0.2, and the resolved vulnerable `brace-expansion@5.0.9` selection is absent. Any content change after this evidence requires the affected gates again; after the candidate is committed, the standard clean-SHA local and hosted gates remain mandatory.
50
+
51
+ ## Exact publication-path checklist (future authorized execution only)
52
+
53
+ The sole publication path remains existing [.github/workflows/release.yml](../.github/workflows/release.yml), triggered only by reviewed annotated unsigned `v*.*.*` tags. Before any separately authorized tag action, verify against the exact workflow and maintainer-controlled configuration:
54
+
55
+ - GitHub Actions trusted publisher is exactly `revazi/pi-career`, workflow `release.yml`, environment `npm`; protected `npm` environment is enabled.
56
+ - Workflow grants `id-token: write` only to the publication job and uses that `npm` environment; no long-lived npm token, `NPM_TOKEN`, `NODE_AUTH_TOKEN`, OTP, manual token publishing, or alternate workflow/path exists.
57
+ - Pinned checkout/setup-node actions, Node 22.19.0 release host, exact npm 11.6.2 tooling, lifecycle-disabled dependency installation/publication, and provenance settings match the reviewed workflow.
58
+ - Tag/version/changelog/lockfile/full SHA/annotated unsigned tag checks, same-SHA hosted gates, complete audits/package gates, and clean-tree checks all pass before publish. The workflow alone may publish and create the GitHub Release, only after registry verification.
59
+ - Trusted publisher/environment configuration is verified before release authorization; do not alter repository/npm settings as part of candidate preparation.
60
+
61
+ ### Registry-first and ambiguous-outcome rule
62
+
63
+ Immediately before any first publish, query the authoritative registry explicitly: `npm view pi-career@0.4.0 version --json` against `https://registry.npmjs.org/`. It must report absence before a first publish. For any failed, timed-out, or ambiguous publish response, do **not** blindly rerun the workflow, republish, move/replace the tag, or attempt overwrite. First query authoritative registry state and inspect exact version metadata, dist-tag, tarball integrity/shasum, provenance/publisher identity, and `gitHead`; preserve evidence and stop if indeterminate. If the exact package is already present, recovery is verification/bookkeeping only through the approved workflow after explicit maintainer incident authorization; never republish immutable version. If absent, investigate and obtain explicit authorization before a controlled retry, following the existing release procedure. No alternate publish channel.
64
+
65
+ ## Rollback, recovery, and post-release verification
66
+
67
+ Before publication, rollback is simply stop: leave the tag and registry untouched, fix the candidate in a reviewed commit, and rerun all gates on the new SHA. A bad published package cannot be overwritten or “rolled back” by republishing; stop installation promotion, document the incident, and use npm's immutable-version policy plus maintainer-directed deprecation/communication only after verifying authoritative state. Do not move a tag or fabricate a replacement artifact. A post-publication failure is an incident, not permission to retry.
68
+
69
+ After successful workflow completion, independently verify the exact npm version's registry metadata and tarball integrity/shasum, provenance and trusted publisher, `gitHead` against full candidate SHA, `latest` dist-tag, annotated tag target, asset-free GitHub Release target/notes, and main CI. In an isolated Pi agent directory install exact `npm:pi-career@0.4.0`, list/load, exercise synthetic runtime operation/acquisition and `PI_OFFLINE=1` failure, then remove the exact installed package. Confirm no native assets/custom Release assets and no unexpected package contents. Triage failures as release blockers/incidents in #73; record the observed Pi 1.0.2 remediation for #149, keep fixture-parity blockers visible, and open focused issues for any newly discovered defect without broadening support claims.
package/docs/releasing.md CHANGED
@@ -1,20 +1,20 @@
1
1
  # Release process
2
2
 
3
- This document defines the bounded trusted-publishing release process for `pi-career@0.2.0` and records the historical `v0.1.0` outcome.
3
+ This document defines the bounded trusted-publishing process for `pi-career@0.4.0` and records the historical `v0.1.0`, `v0.2.0`, and `v0.3.0` outcomes. Candidate metadata and the dated changelog must be finalized before the release SHA is frozen; tracked files do not embed that self-referential SHA. Publication and tag creation always require the separate explicit authorization described below. In the instructions below, `<version>` is the exact package version without `v`, `<tag>` is `v<version>`, and `<sha>` is the full frozen candidate commit.
4
4
 
5
5
  ## Release boundary
6
6
 
7
- The coordinated `v0.2.0` release may create exactly:
7
+ One coordinated release may create exactly:
8
8
 
9
- 1. one public `pi-career@0.2.0` npm package on `https://registry.npmjs.org/`;
10
- 2. one annotated, unsigned `v0.2.0` Git tag pointing to the exact published commit; and
9
+ 1. one public `pi-career@<version>` npm package on `https://registry.npmjs.org/`;
10
+ 2. one annotated, unsigned `<tag>` Git tag pointing to the exact published commit; and
11
11
  3. one GitHub Release for that tag with notes derived from the finalized [`CHANGELOG.md`](../CHANGELOG.md) entry.
12
12
 
13
13
  The npm package must be the native-free allowlisted artifact verified by `npm run check:package`. It contains the Pi extension, generated PDF worker, Agent Skill, and documentation. It must contain no `runtime/`, native executable, `node_modules`, Pi peer package contents, production dependency tree, lifecycle download/build hook, or publication script.
14
14
 
15
- Career Core distribution remains external. The candidate pins exact [`@revazi/career@0.1.1`](https://www.npmjs.com/package/@revazi/career/v/0.1.1); its reviewed launcher owns native target/libc, package metadata, provenance, Unix mode or Windows file invariant, size, format, architecture, and SHA-256 verification. Pi-career must not copy those algorithms or artifacts.
15
+ Career Core distribution remains external. The candidate pins exact [`@revazi/career@0.2.0`](https://www.npmjs.com/package/@revazi/career/v/0.2.0); its reviewed launcher owns native target/libc, package metadata, provenance, file invariants, size, format, architecture, and SHA-256 verification. Pi-career supports only its six macOS/Linux targets and must not copy those algorithms or artifacts. Pi-career validates the exact ordered six-package v2 launcher manifest, declared file allowlist, and `career` bin before direct execution.
16
16
 
17
- The reviewed external release is bound to Career Core commit/tag `0318b3b0993ee23093c8f023757fa7e4d8b3b8e0`/`v0.1.1` and successful protected publication run [`31346152236`](https://github.com/revazi/career-core/actions/runs/31346152236). The launcher registry integrity is `sha512-K2WojK0wbuMt4WWT87jrLUiRWLwlDeYR0BcSTqlaTGc0SNw4z7VWkSe7utFwH2MFhHaIE1iHWfpsj+nNlHklvQ==`; registry metadata reports SLSA v1 provenance for the launcher and all eight lockstep native packages.
17
+ The reviewed external release is bound to Career Core commit/tag `536690632884c17336cc3c108f1bba0f254b862b`/`v0.2.0` and successful protected publication run [`31761238274`](https://github.com/revazi/career-core/actions/runs/31761238274). The launcher registry integrity is `sha512-5aksKh9S2fqPKBwlUY94XgCHjggr2Gep45zEWOMBNEfRtXvC/pYnlkI9CYrVHBFR8/gfGQog4pwV854FMzDxww==`; registry metadata reports SLSA v1 provenance for the user-facing launcher and all six lockstep launcher-owned native packages.
18
18
 
19
19
  The sole permitted automated publication path is the tag-triggered `.github/workflows/release.yml` workflow using npm Trusted Publishing through GitHub OIDC and the protected `npm` environment. It must use no `NPM_TOKEN`, `NODE_AUTH_TOKEN`, OTP, or other long-lived publication credential. Preparation, CI success, a version bump, workflow availability, or this document does **not** authorize tag creation/push, npm publication, or a GitHub Release; release execution remains a separate explicit maintainer action. Do not publish to crates.io, attach an npm tarball/native binary as a custom GitHub Release asset, add signing/notarization claims, or add lifecycle/publication scripts.
20
20
 
@@ -31,9 +31,49 @@ Release execution completed on 2026-08-06:
31
31
  - npm shasum: `4212cea50c08c98771df267361cee28070a15765`
32
32
  - custom GitHub Release assets: none
33
33
 
34
- That release bundled native Career Core artifacts. Its dependency/license/provenance evidence remains historical in [`native-dependency-inventory.md`](native-dependency-inventory.md) and [`licenses/`](licenses/). None of those native files may re-enter the `v0.2.0` package.
34
+ That release bundled native Career Core artifacts. Its dependency/license/provenance evidence remains historical in [`native-dependency-inventory.md`](native-dependency-inventory.md) and [`licenses/`](licenses/). None of those native files may re-enter a future package.
35
35
 
36
- ## `v0.2.0` release gates
36
+ ## Historical `v0.2.0` outcome
37
+
38
+ Release execution completed on 2026-08-10:
39
+
40
+ - npm: [`pi-career@0.2.0`](https://www.npmjs.com/package/pi-career/v/0.2.0)
41
+ - published commit: `6db58644a6140202de2f2d661a740acd298c79b5`
42
+ - annotated unsigned tag and GitHub Release: [`v0.2.0`](https://github.com/revazi/pi-career/releases/tag/v0.2.0)
43
+ - npm integrity: `sha512-2V0z42oxsDHdE9a/UTskCzLY3inU0/DX30h2QhXse/Y3rAJpsaaNweqVhvZwZlMUovtyBu7pnGSpSo8CLhVOBg==`
44
+ - npm shasum: `c182b09945eee8cd85d817b7ce4965784731fd49`
45
+ - same-SHA six-target compatibility run: [`31352965430`](https://github.com/revazi/pi-career/actions/runs/31352965430)
46
+ - OIDC publication run: [`31353182855`](https://github.com/revazi/pi-career/actions/runs/31353182855)
47
+ - npm publisher identity: GitHub Actions trusted publisher for `revazi/pi-career`, workflow `release.yml`, environment `npm`
48
+ - SLSA provenance subject and resolved Git dependency: exact `pi-career@0.2.0` tarball and commit above
49
+ - custom GitHub Release assets: none
50
+
51
+ The first tag-triggered attempt, run [`31352716654`](https://github.com/revazi/pi-career/actions/runs/31352716654), failed before dependency installation or publication because `shell: node {0}` resolved a relative ESM import from GitHub's temporary script directory. Registry absence was reconfirmed; no publish retry occurred. PR [#23](https://github.com/revazi/pi-career/pull/23) moved the hosted-gate query into a checked-in script. After explicit incident authorization, the unpublished tag was replaced once on the corrected candidate.
52
+
53
+ In run `31353182855`, every gate and the OIDC `npm publish` step succeeded. The run then failed closed before GitHub Release creation because npm's attestation endpoint propagated after the original one-minute bound and the resulting SLSA bundle used the current Sigstore v0.3 media type while npm's publish attestation remained v0.2. The version already existed authoritatively, so it was never rerun or republished. PR [#24](https://github.com/revazi/pi-career/pull/24) extended bounded propagation polling and validates both exact bundle formats. The corrected verifier subsequently proved registry metadata, tarball bytes, trusted-publisher identity, provenance workflow/tag/SHA, and latest dist-tag; exact published Pi install/load/runtime/offline/remove acceptance passed before the GitHub Release and deployment status were finalized.
54
+
55
+ **Never rerun or republish after an ambiguous publish response.** Query authoritative registry state first. A post-publication recovery may finish verification and release-channel bookkeeping only; it must not create an alternate publication path, overwrite an immutable npm version, or move the published tag.
56
+
57
+ ## Historical `v0.3.0` outcome
58
+
59
+ Release execution completed on 2026-08-14:
60
+
61
+ - npm: [`pi-career@0.3.0`](https://www.npmjs.com/package/pi-career/v/0.3.0)
62
+ - published commit: `2c0da9ff623b50cc02a7b5bccd3cb047596d947e`
63
+ - annotated unsigned tag and asset-free GitHub Release: [`v0.3.0`](https://github.com/revazi/pi-career/releases/tag/v0.3.0)
64
+ - npm integrity: `sha512-u/odRK/KMYXhIt/lvGm93RFmQIwBQZV0qbAf1vs/GsNH8Fx/X2f+p+F1iyUYtMi5RH9++SkdhEN8CR2XBScyBw==`
65
+ - npm shasum: `3ad37db78cb76330838fbb3efe722c1cff4d8d00`
66
+ - same-SHA main Adapter checks: [`31790996492`](https://github.com/revazi/pi-career/actions/runs/31790996492)
67
+ - same-SHA six-target compatibility run: [`31791011739`](https://github.com/revazi/pi-career/actions/runs/31791011739)
68
+ - OIDC publication, authoritative registry verification, and GitHub Release run: [`31791158472`](https://github.com/revazi/pi-career/actions/runs/31791158472)
69
+ - npm publisher identity: GitHub Actions trusted publisher for `revazi/pi-career`, workflow `release.yml`, environment `npm`
70
+ - SLSA provenance subject and resolved Git dependency: exact `pi-career@0.3.0` tarball and commit above
71
+ - exact public Pi install/list/runtime acquisition with synthetic operations/offline failure/remove acceptance: passed
72
+ - custom GitHub Release assets: none
73
+
74
+ The published package is native-free, supports the six reviewed macOS/Linux targets through exact external `@revazi/career@0.2.0`, and validates its exact ordered six-package v2 launcher manifest. Production and complete development/host-Pi audits were both clean at the explicit low threshold before publication.
75
+
76
+ ## Release gates
37
77
 
38
78
  A skipped, unknown, stale, or merely planned result is not a pass.
39
79
 
@@ -41,21 +81,22 @@ A skipped, unknown, stale, or merely planned result is not a pass.
41
81
 
42
82
  - Start from synchronized public `main` and identify one full candidate SHA.
43
83
  - Require a clean Git tree and no divergence from `origin/main`.
44
- - Confirm `package.json`, the root package-lock entries, the Skill metadata, package assertions, changelog, README, and release documentation all identify pi-career `0.2.0` where appropriate.
45
- - Keep Career Core and `@revazi/career` compatibility coordinates at exact `0.1.1`; do not confuse the adapter release version with the external runtime version.
46
- - Confirm `package.json` is explicitly public only at `https://registry.npmjs.org/`, has exactly four wildcard Pi peers, declares no production/optional/bundled dependency tree, and has no lifecycle/publication script.
84
+ - Confirm `package.json`, the root package-lock entries, the Skill metadata, package assertions, changelog, README, and release documentation all identify the candidate version where appropriate.
85
+ - Keep Career Core and `@revazi/career` compatibility coordinates at exact `0.2.0` unless a separate compatibility/provenance review explicitly updates them; do not confuse the adapter release version with the external runtime version.
86
+ - Confirm `package.json` is explicitly public only at `https://registry.npmjs.org/`, has `os` exactly `['darwin', 'linux']`, has exactly four wildcard Pi peers, declares no production/optional/bundled dependency tree, and has no lifecycle/publication script.
47
87
  - Ensure the candidate contains no real resume, vacancy, credentials, Pi session, provider output, generated local path, npm token, or unreviewed executable.
48
- - Review the complete diff from `v0.1.0`, including authoritative `src/`, generated `dist/index.js`/`dist/pdf-worker.js`, `career_run`, all three exact raw tools, slash commands, external resolver, Skill, and package documentation.
88
+ - Review the complete diff from the prior release tag, including authoritative `src/`, generated `dist/index.js`/`dist/pdf-worker.js`, `career_run`, all three exact raw tools, slash commands, external resolver, Skill, release automation, and package documentation.
49
89
  - Do not move the candidate after local/hosted evidence is recorded. Any content change creates a new candidate and requires the gates again.
50
90
 
51
91
  ### 2. Review the external runtime boundary
52
92
 
53
- - Confirm the only acquisition coordinate remains exact `@revazi/career@0.1.1` from the canonical npm registry.
93
+ - Confirm unsupported local/Git extension initialization registers no command/tool and fails with stable payload-free `unsupported_platform` before explicit/PATH lookup, package validation, acquisition, compatibility probing, or private stdin; retain invocation/resolver guards as defense in depth.
94
+ - Confirm the only acquisition coordinate remains exact `@revazi/career@0.2.0` from the canonical npm registry.
54
95
  - Confirm runtime order remains: absolute `CAREER_CLI_PATH`, PATH `career`, package-local exact launcher, then bounded exact-package acquisition unless `PI_OFFLINE=1`.
55
- - Confirm every caller-controlled route must pass the exact managed Core 0.1.1 operation catalog and required self-contained schema bundles before private stdin opens.
56
- - Confirm package-local/acquired routes delegate native target/libc/provenance/mode or Windows file invariant/size/format/architecture/SHA-256 verification to the reviewed launcher.
57
- - Confirm all nine exact npm packages remain version-lockstep, have canonical registry integrity and SLSA v1 provenance, and match the ordered v2 launcher catalog from reviewed Core commit `0318b3b0993ee23093c8f023757fa7e4d8b3b8e0`.
58
- - Run the exact-package integration test on the six hosted macOS/GNU Linux/musl Linux release targets. Updating the external package coordinate, native target list, launcher schema, or managed Core contract requires separate compatibility, provenance, audit, and package review before this gate can pass.
96
+ - Confirm every caller-controlled route must pass the exact managed Core 0.2.0 operation catalog and required self-contained schema bundles before private stdin opens.
97
+ - Confirm package-local/acquired routes validate the exact ordered six-package v2 launcher manifest and delegate native target/libc/provenance/mode/size/format/architecture/SHA-256 verification to the reviewed launcher on the six supported targets.
98
+ - Confirm the external release's launcher plus six native packages remain version-lockstep, have canonical registry integrity and SLSA v1 provenance, and are bound to reviewed Core commit `536690632884c17336cc3c108f1bba0f254b862b`.
99
+ - Run the exact-package integration test on the six hosted macOS/GNU Linux/musl Linux release targets. Updating the external package coordinate, supported native target list, launcher schema, or managed Core contract requires separate compatibility, provenance, audit, and package review before this gate can pass.
59
100
 
60
101
  ### 3. Require clean audits and strict package proof
61
102
 
@@ -67,7 +108,7 @@ A skipped, unknown, stale, or merely planned result is not a pass.
67
108
  - trusted npm is derived from the real Node installation and conflicting `npm_execpath` is rejected;
68
109
  - npm environment overrides and duplicate decoded JSON keys cannot weaken checks;
69
110
  - package listing/extraction uses verified absolute `/usr/bin/tar`;
70
- - the tarball matches the exact allowlist and size bounds;
111
+ - the tarball matches the exact allowlist and size bounds and declares `os: ['darwin', 'linux']`;
71
112
  - no native runtime, `node_modules`, Pi peer contents, production dependency tree, or lifecycle/publication script is present;
72
113
  - extracted package loading, stable offline failure, and isolated Pi install/list/remove behavior pass.
73
114
 
@@ -82,6 +123,7 @@ npm ci
82
123
  npm run build
83
124
  git diff --exit-code -- dist/index.js dist/pdf-worker.js
84
125
  npm run bench:tokens
126
+ npm run bench:tokens:compare
85
127
  npm run check
86
128
  npm run test:runtime-resolution
87
129
  npm run test:career-package
@@ -98,11 +140,11 @@ git diff --check
98
140
  Requirements:
99
141
 
100
142
  - The immediate dist diff after `npm run build` must pass; a later reproducibility test alone does not prove the candidate committed the generated output.
101
- - Token measurements must exactly reproduce the committed baseline and remain within budgets.
143
+ - Token measurements must satisfy the active before/optimizing/after manifest: immutable Git-history snapshot/manifest bytes and source/Skill tree anchors, exact frozen before/after comparability and deltas, unchanged current shape/invariants/budgets, and no current workflow regression relative to the frozen after snapshot. Later current source need not equal the historical after tree.
102
144
  - Exact-package acquisition must execute managed discovery plus representative synthetic resume/job operations.
103
145
  - Compatibility must run against an explicitly reviewed fixture checkout. A skip is not release evidence.
104
146
  - The production npm tree must remain empty apart from unmet external peers expected in the Pi host.
105
- - No command may create a repository tarball, native runtime, payload/result file, acceptance baseline, or publication side effect.
147
+ - No command may create a repository tarball, native runtime, payload/result file, audit-acceptance baseline, or publication side effect. Reviewed synthetic token snapshots are benchmark evidence, not vulnerability acceptance.
106
148
 
107
149
  ### 5. Require hosted checks on the same SHA
108
150
 
@@ -127,13 +169,13 @@ Record the dispatched run's `headSha` and reject it unless it equals the frozen
127
169
 
128
170
  Before release authorization:
129
171
 
130
- - convert `CHANGELOG.md` candidate notes to the dated `0.2.0` entry;
131
- - ensure README installation uses exact `npm:pi-career@0.2.0` and clearly distinguishes historical v0.1.0;
132
- - state that pi-career packages no native runtime and identify exact external `@revazi/career@0.1.1` plus all eight supported targets;
172
+ - convert `CHANGELOG.md` candidate notes to a dated candidate-version entry;
173
+ - ensure README installation uses the exact candidate `npm:pi-career@<version>` coordinate and clearly distinguishes historical releases;
174
+ - state that pi-career packages no native runtime, supports only the six reviewed macOS/Linux targets, uses exact external `@revazi/career@0.2.0`, and validates its exact ordered six-package v2 manifest;
133
175
  - state that both production and complete development/host-Pi audits are clean at the explicit low threshold;
134
176
  - keep all full commit SHA and npm integrity placeholders out of tracked files until those values exist; record them in the GitHub Release after publication.
135
177
 
136
- The finalization commit cannot contain its own SHA. Only the separately authorized final clean commit may be published and receive `v0.2.0`.
178
+ The finalization commit cannot contain its own SHA. Only the separately authorized final clean commit may be published and receive `<tag>`.
137
179
 
138
180
  ## Manual pre-publication checks
139
181
 
@@ -141,7 +183,7 @@ Run these only on the frozen clean candidate:
141
183
 
142
184
  1. Confirm npm package `pi-career` has exactly the GitHub Actions trusted publisher `revazi/pi-career`, workflow `release.yml`, environment `npm`.
143
185
  2. Confirm the GitHub `npm` environment exists and applies the reviewed deployment protections. No npm token or OTP may be stored in GitHub, npm configuration, repository files, Pi messages, logs, or release notes.
144
- 3. Confirm `npm view pi-career@0.2.0 version --json` reports no existing version. npm versions are immutable.
186
+ 3. Confirm `npm view pi-career@<version> version --json` reports no existing version. npm versions are immutable.
145
187
  4. Run trusted `npm pack --dry-run --json --ignore-scripts` or rely on the stricter recorded `check:publish` artifact proof.
146
188
  5. Record the candidate full SHA, package filename/size, clean audit results, hosted run URLs, and reviewed fixture SHA outside private content.
147
189
  6. Obtain explicit release authorization. Do not infer authorization from readiness work.
@@ -150,20 +192,20 @@ Run these only on the frozen clean candidate:
150
192
 
151
193
  Only after every gate passes and the maintainer explicitly authorizes release execution:
152
194
 
153
- 1. Reconfirm the clean SHA, branch protection checks, trusted-publisher/environment configuration, canonical registry, and absence of `pi-career@0.2.0`.
154
- 2. Create one annotated unsigned `v0.2.0` tag on the exact candidate and push only that tag. The tag is the immutable input that triggers `.github/workflows/release.yml`; the workflow must never create or move it.
195
+ 1. Reconfirm the clean SHA, branch protection checks, trusted-publisher/environment configuration, canonical registry, and absence of `pi-career@<version>`.
196
+ 2. Create one annotated unsigned `<tag>` on the exact candidate and push only that tag. The tag is the immutable input that triggers `.github/workflows/release.yml`; the workflow must never create or move it.
155
197
  3. The workflow must verify the tag/version/changelog/SHA, install exact trusted-publishing-compatible npm tooling, run the complete package publication gate, and publish with lifecycle scripts disabled, public/latest coordinates, and npm provenance through OIDC.
156
198
  4. If publication returns an ambiguous response, query the registry before any rerun. Never move the tag, attempt to overwrite the version, or blindly republish.
157
199
  5. Before creating the GitHub Release, the workflow must verify registry metadata: version, repository, four wildcard peers, no dependency tree/lifecycle scripts, tarball integrity, shasum, provenance, and `gitHead` equal to the tagged candidate SHA.
158
- 6. The workflow must create the GitHub Release from the existing `v0.2.0` tag with:
200
+ 6. The workflow must create the GitHub Release from the existing `<tag>` with:
159
201
  - full commit SHA;
160
202
  - npm integrity and shasum;
161
- - exact external `@revazi/career@0.1.1` coordinate;
162
- - all eight reviewed macOS, GNU Linux, musl Linux, and MSVC Windows targets;
203
+ - exact external `@revazi/career@0.2.0` coordinate;
204
+ - all six supported macOS, GNU Linux, and musl Linux targets, plus a clear note that only the launcher is a pi-career installation surface;
163
205
  - native-free pi-career package statement;
164
206
  - clean production/full audit statement;
165
207
  - no crate publication, signing/notarization claim, or custom release asset.
166
- 7. In an isolated Pi agent directory, install exact `npm:pi-career@0.2.0`, list/load it, exercise exact-package runtime acquisition with synthetic operations on a supported target, test offline failure, and remove it.
208
+ 7. In an isolated Pi agent directory, install exact `npm:pi-career@<version>`, list/load it, exercise exact-package runtime acquisition with synthetic operations on a supported target, test offline failure, and remove it.
167
209
  8. Recheck the npm dist-tag, Git tag target, GitHub Release target, provenance, and main CI after all channels settle.
168
210
 
169
- Do not sign, attach assets, change repository visibility, add an alternate publication workflow or token-based path, publish another registry tag/version, or retry an ambiguous operation without first querying authoritative state. A failed post-publication check is an incident, not permission to replace `0.2.0`.
211
+ Do not sign, attach assets, change repository visibility, add an alternate publication workflow or token-based path, publish another registry tag/version, or retry an ambiguous operation without first querying authoritative state. A failed post-publication check is an incident, not permission to replace the immutable published version.
@@ -0,0 +1,110 @@
1
+ # Single application-state contract — issue #140
2
+
3
+ ## Status and scope
4
+
5
+ This contract replaces application-state schema versioning with one exact pi-career-owned schema:
6
+
7
+ ```text
8
+ pi.career.application_state
9
+ ```
10
+
11
+ Issue #140 approved this contract. Issue #141 implements production, fixture, generated-bundle, and documentation convergence.
12
+
13
+ There is no application-state schema migration or compatibility path. Files whose `schema_version` is `pi.career.application_state.v1`, `pi.career.application_state.v2`, or any other value are unsupported and fail closed. They are never rewritten, adopted, interpreted as a compatible prefix, or exposed as current state.
14
+
15
+ Append-only numbered revisions are retained. Revision numbers and parent hashes protect immutable history, concurrency, crash settlement, and no-clobber publication; they are not schema versions.
16
+
17
+ ## Canonical schema
18
+
19
+ Every state revision is canonical two-space JSON plus one LF with these exact ordered keys:
20
+
21
+ ```json
22
+ {
23
+ "schema_version": "pi.career.application_state",
24
+ "kind": "application_state_revision",
25
+ "application_id": "00000000-0000-4000-8000-000000000001",
26
+ "sequence": 1,
27
+ "parent_sha256": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
28
+ "status": "preparing",
29
+ "vacancy": null,
30
+ "selected_original": null,
31
+ "resume_artifact": null,
32
+ "cover_letter_artifact": null,
33
+ "updated_at": "2026-08-12T00:00:01.000Z"
34
+ }
35
+ ```
36
+
37
+ The field meanings and bounds remain:
38
+
39
+ - `application_id`: canonical lowercase application UUID bound to the immutable manifest.
40
+ - `sequence`: integer 1 through 64 matching the six-digit state filename.
41
+ - `parent_sha256`: SHA-256 of the exact manifest bytes for sequence 1, otherwise of the immediately preceding exact state bytes.
42
+ - `status`: `preparing`, `applied`, `interviewing`, or `closed`.
43
+ - `vacancy`: `null` or the existing exact ordered vacancy reference.
44
+ - `selected_original`: `null` or the existing exact ordered original Resume binding.
45
+ - `resume_artifact`: `null` or the existing exact ordered assisted artifact and sidecar reference.
46
+ - `cover_letter_artifact`: `null` or the exact ordered reference below.
47
+ - `updated_at`: canonical UTC timestamp with milliseconds, strictly increasing across revisions.
48
+
49
+ A non-null cover-letter reference has exactly these ordered keys:
50
+
51
+ ```json
52
+ {
53
+ "relative_path": "cover-letter.md",
54
+ "artifact_sha256": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
55
+ "utf8_bytes": 42,
56
+ "format": "markdown",
57
+ "authority": "user_authored",
58
+ "job_description_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
59
+ "effective_resume_sha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
60
+ }
61
+ ```
62
+
63
+ Issue #57 separately authorizes a narrowly scoped user-authored writer using this exact reference shape. It does not authorize rebind, artifact deletion/adoption, or model-assisted content. The transaction, byte bound, authority, preview, confirmation, and immutable-history rules are specified in [`cover-letter-contract.md`](cover-letter-contract.md).
64
+
65
+ ## Complete-chain rules
66
+
67
+ A trusted chain contains only `pi.career.application_state` revisions and must satisfy all existing safety rules:
68
+
69
+ 1. State files begin at `.pi-career-state-000001.json`, are contiguous, match embedded sequence values, and never exceed 64 revisions.
70
+ 2. Sequence 1 hashes the immutable manifest; each later revision hashes the exact previous revision.
71
+ 3. Every revision binds the same application UUID and has a strictly later canonical timestamp.
72
+ 4. Every referenced package-owned file retains exact containment, ownership, mode, link-count, size, and hash validation.
73
+ 5. Gaps, forks, duplicate state-shaped names, malformed bytes, unsupported schema identifiers, historical managed-reference drift, races, and exceeded bounds reject the complete chain. No last-known-good prefix becomes current.
74
+ 6. Reads never mutate, migrate, repair, compact, adopt, or delete state.
75
+
76
+ New applications and every approved state mutation write only the one canonical schema. There is no transition revision, upgrade, downgrade, dual reader, or mixed-schema chain.
77
+
78
+ ## Readiness and authority
79
+
80
+ The existing pure readiness and effective-Resume rules operate on a fully validated single-schema head. Readiness remains derived rather than persisted or manually toggled. Lifecycle status and match results do not override component validity.
81
+
82
+ This simplification changes no authority or consent boundary:
83
+
84
+ - original Resumes remain immutable and external to application workspaces;
85
+ - workspace files remain authoritative for attached application state;
86
+ - Career Core remains authoritative for supported career-domain operations and contracts;
87
+ - no read, migration rejection, or readiness derivation invokes Core, a provider/model, network, telemetry, or session append;
88
+ - every mutation still requires exact preview, unchanged return, separate confirmation, fresh under-lock validation, no-clobber publication, state commit last, and payload-free errors;
89
+ - no private body, path, UUID, hash, environment value, raw error, Core result, prompt, or provider content is logged or exposed at the adapter boundary.
90
+
91
+ ## Acceptance scenarios for #141
92
+
93
+ | ID | Given | When | Then |
94
+ |---|---|---|---|
95
+ | S1-01 | Canonical single-schema sequence 1 | Read application | Accept exact state without mutation |
96
+ | S1-02 | Multiple contiguous single-schema revisions | Read application | Select the exact highest complete head |
97
+ | S1-03 | A former `.v1` or `.v2` identifier anywhere in the chain | Discover or read | Classify unsupported; trust no prefix and mutate nothing |
98
+ | S1-04 | Any other unsupported canonical schema identifier | Discover or read | Classify unsupported with a payload-free result |
99
+ | S1-05 | Gap, fork, duplicate name, bad parent, or malformed state | Discover or read | Fail closed under the existing drift classification |
100
+ | S1-06 | New application | Commit approved creation | Write sequence 1 using only `pi.career.application_state` |
101
+ | S1-07 | Approved status, vacancy, or selected-original mutation | Commit | Append one canonical single-schema revision |
102
+ | S1-08 | Nullable or valid non-null cover-letter reference | Parse and derive | Preserve the exact shape and existing readiness rules without authorizing a writer |
103
+ | S1-09 | Concurrent same-next-revision plans | Commit | One no-clobber winner; no fork, retry name, or overwrite |
104
+ | S1-10 | Capacity, byte, metadata, or post-preview race boundary | Plan or commit | Preserve existing before-preview and under-lock rejection |
105
+ | S1-11 | Unsupported former-schema application | Open overlay or restore attachment | Do not expose as valid/current, attach, migrate, or append |
106
+ | S1-12 | Any read or rejected mutation above | Observe side effects | No Core/provider/network/session/logging or unauthorized file effect |
107
+
108
+ ## Explicit exclusions
109
+
110
+ This contract does not authorize cover-letter persistence, deletion, archive, synchronization, repair, unknown-file adoption, provider behavior, a package-version change, publication, or release. It does not change config, marker, identity, attachment, activation, variant-sidecar, Career Core, or managed-tool schema identifiers.