@mriekki/project-forge 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@mriekki/project-forge",
4
- "version": "4.1.0",
4
+ "version": "4.2.0",
5
5
  "defaultProfile": "greenfield-project",
6
6
  "profiles": {
7
7
  "greenfield-project": {
@@ -14,7 +14,7 @@
14
14
  "components": {
15
15
  "core": {
16
16
  "repository": "mriekki/project-forge-core",
17
- "commit": "738dca3e03d110da0837d35d45101d2315f13a6f",
17
+ "commit": "d84829629d151c85bbe4680bc2297abfdf3a3022",
18
18
  "version": "4.0.0",
19
19
  "distribution": "greenfield-workspace",
20
20
  "descriptor": "assets/core/distribution.json",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "deployment": {
25
25
  "repository": "mriekki/project-forge-deployment-kit",
26
- "commit": "149812159cafdfeeca04645e129392021b8b9e09",
26
+ "commit": "e974c227d9d0768e64605550709db89ccaf93434",
27
27
  "distribution": "greenfield-project",
28
28
  "descriptor": "assets/deployment/distribution.json",
29
29
  "sourceRoot": "assets/generated/deployment",
@@ -31,6 +31,7 @@
31
31
  {"source": "src/project_forge_deployment/profile_migration.py", "destination": "tools/project-forge-deployment/project_forge_deployment/profile_migration.py"},
32
32
  {"source": "src/project_forge_deployment/profile_repository.py", "destination": "tools/project-forge-deployment/project_forge_deployment/profile_repository.py"},
33
33
  {"source": "src/project_forge_deployment/profiles.py", "destination": "tools/project-forge-deployment/project_forge_deployment/profiles.py"},
34
+ {"source": "src/project_forge_deployment/proof_receipt.py", "destination": "tools/project-forge-deployment/project_forge_deployment/proof_receipt.py"},
34
35
  {"source": "src/project_forge_deployment/registry_access.py", "destination": "tools/project-forge-deployment/project_forge_deployment/registry_access.py"},
35
36
  {"source": "src/project_forge_deployment/registry_cli.py", "destination": "tools/project-forge-deployment/project_forge_deployment/registry_cli.py"},
36
37
  {"source": "src/project_forge_deployment/route_registry.py", "destination": "tools/project-forge-deployment/project_forge_deployment/route_registry.py"},
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@mriekki/project-forge",
4
- "version": "4.1.0",
4
+ "version": "4.2.0",
5
5
  "components": {
6
6
  "core": {
7
7
  "repository": "mriekki/project-forge-core",
8
- "commit": "738dca3e03d110da0837d35d45101d2315f13a6f",
8
+ "commit": "d84829629d151c85bbe4680bc2297abfdf3a3022",
9
9
  "version": "4.0.0",
10
10
  "distribution": "greenfield-workspace",
11
11
  "files": [
@@ -22,7 +22,7 @@
22
22
  {
23
23
  "source": "core/instructions/project-forge-workflow.instructions.md",
24
24
  "destination": ".github/instructions/project-forge-workflow.instructions.md",
25
- "sha256": "a6b28d916b67c9eec3831e414b56be3636512f7f7740523d22aaaf6efa00d335"
25
+ "sha256": "85568ba56681831e34c63aa14f91702522a451e8b2fa883da631d609440d7a7c"
26
26
  },
27
27
  {
28
28
  "source": "core/instructions/project-forge-docs.instructions.md",
@@ -52,7 +52,7 @@
52
52
  {
53
53
  "source": "core/skills/setup/SKILL.md",
54
54
  "destination": ".github/skills/setup/SKILL.md",
55
- "sha256": "2f1b88b31b2c7233a00ab9293cd98a5fade00e114e1a442a793affbc7fe4ad83"
55
+ "sha256": "deb64d0e7ce3a7788e5674182c9788219f2422468ed3e0cc767d49ce569acaea"
56
56
  },
57
57
  {
58
58
  "source": "core/skills/build/SKILL.md",
@@ -107,7 +107,7 @@
107
107
  {
108
108
  "source": "core/skills/upstream-fix/SKILL.md",
109
109
  "destination": ".github/skills/upstream-fix/SKILL.md",
110
- "sha256": "72466740638688f99b0a1dd6c56ef7bc90ac218b27642d0af8b3237074b97fec"
110
+ "sha256": "cec11a112840b37a5ff61e28281d26eb9490e9d7b05df99ae5fa152231316798"
111
111
  },
112
112
  {
113
113
  "source": "core/skills/wait-what/SKILL.md",
@@ -328,7 +328,7 @@
328
328
  },
329
329
  "deployment": {
330
330
  "repository": "mriekki/project-forge-deployment-kit",
331
- "commit": "149812159cafdfeeca04645e129392021b8b9e09",
331
+ "commit": "e974c227d9d0768e64605550709db89ccaf93434",
332
332
  "distribution": "greenfield-project",
333
333
  "files": [
334
334
  {
@@ -404,12 +404,12 @@
404
404
  {
405
405
  "source": "src/project_forge_deployment/environment_probe.py",
406
406
  "destination": "tools/project-forge-deployment/project_forge_deployment/environment_probe.py",
407
- "sha256": "5f4bba4a9e01b97eccdf67919d49894c9d264fae0edd63f742baaa18e42f69d0"
407
+ "sha256": "4e9a49a7cf0427dcdef1e28f955297569ec8cd0ee9d071404ef876e3ce036313"
408
408
  },
409
409
  {
410
410
  "source": "src/project_forge_deployment/environment_setup.py",
411
411
  "destination": "tools/project-forge-deployment/project_forge_deployment/environment_setup.py",
412
- "sha256": "1554c2954a024f8419f44eb2ab3fdc129334de41df6038628bade9cb7a803950"
412
+ "sha256": "a79919da8655a6c42fded3224373f6381d15c8c68869b70c31d6edb7702fd348"
413
413
  },
414
414
  {
415
415
  "source": "src/project_forge_deployment/errors.py",
@@ -419,7 +419,7 @@
419
419
  {
420
420
  "source": "src/project_forge_deployment/home_lab.py",
421
421
  "destination": "tools/project-forge-deployment/project_forge_deployment/home_lab.py",
422
- "sha256": "071391b687aac7e4bade0a27bf7d47257935a21c8f9151138fe74185f6c54cfb"
422
+ "sha256": "481b22ee7983dbe39b9e727ad874356a5dc4d55a4d7380545f2577e4a9ea45e7"
423
423
  },
424
424
  {
425
425
  "source": "src/project_forge_deployment/image_transfer.py",
@@ -471,6 +471,11 @@
471
471
  "destination": "tools/project-forge-deployment/project_forge_deployment/profiles.py",
472
472
  "sha256": "c8fb1c378af9d39d28f46b300064bec967e2a6f7a13e22d089fc00413c42fd9d"
473
473
  },
474
+ {
475
+ "source": "src/project_forge_deployment/proof_receipt.py",
476
+ "destination": "tools/project-forge-deployment/project_forge_deployment/proof_receipt.py",
477
+ "sha256": "9b4bbb559747fc4ee3ba984a050fc6425e532527ae82f9897c73e04d8d0291b6"
478
+ },
474
479
  {
475
480
  "source": "src/project_forge_deployment/registry_access.py",
476
481
  "destination": "tools/project-forge-deployment/project_forge_deployment/registry_access.py",
@@ -519,7 +524,7 @@
519
524
  {
520
525
  "source": "src/project_forge_deployment/ssh.py",
521
526
  "destination": "tools/project-forge-deployment/project_forge_deployment/ssh.py",
522
- "sha256": "916a272ed5978df642e6084a3030c32f2c9dcb4b3b686a194428f9810ec55e9d"
527
+ "sha256": "88d59b62f63dc6b7206b6074dd109af4ea7c8f022f506e67f7204f1f06240d26"
523
528
  },
524
529
  {
525
530
  "source": "src/project_forge_deployment/teardown.py",
@@ -554,7 +559,7 @@
554
559
  {
555
560
  "source": "docs/ENVIRONMENT_PROOF.md",
556
561
  "destination": "docs/project-forge/ENVIRONMENT_PROOF.md",
557
- "sha256": "f635a87ada6a22deb09a3ac0f1c99f8e32119bb8bff3613d77db2ed876dc2552"
562
+ "sha256": "2ce7225ad6166a4ee30f51ea67ec077de0c29ce3a5c39b4ff57bf11cbe25e927"
558
563
  },
559
564
  {
560
565
  "source": "docs/images/developer-environment-journey.svg",
@@ -34,7 +34,9 @@ For deployment readiness, inspect existing non-secret configuration before askin
34
34
 
35
35
  Shared managed code keeps its canonical owner. When a consumer contains `CORE_BASELINE.json` or `DEPLOYMENT_BASELINE.json`, treat those baselines as ownership evidence. A temporary edit to a shared-managed consumer file may be used to diagnose or prove a reusable defect, but it is not the canonical deliverable.
36
36
 
37
- Before consumer delivery, run available managed-baseline integrity checks. If Core- or Deployment-Kit-managed files have unexplained local drift, stop before staging/commit/push and route the reusable change through `/upstream-fix`. Fix the owning canonical repository, deliver/merge it there under normal gates, then adopt the exact accepted shared commit back into the consumer through the appropriate update boundary and retest in consumer context.
37
+ When reusable Project Forge drift is detected, distinguish unexplained drift from an explained temporary upstream proof. Unexplained managed drift remains fail-closed before delivery writes. For explained drift, route through `/upstream-fix`, preserve `.project-forge/UPSTREAM_FIX_HANDOFF.md`, and offer one explicit `Continue consumer work with acknowledged Project Forge drift` override when the current work can proceed without committing the managed workaround. That override is session/work-item continuation authority only; it does not authorize committing shared-managed paths, editing baselines, bypassing required CI/policy, or claiming that the canonical fix has been adopted.
38
+
39
+ After an accepted continuation override, do not repeatedly halt normal consumer implementation solely because the same documented managed workaround remains present. Keep the handoff and workaround unstaged. Before consumer `/deliver`, warn about the acknowledged drift, selectively stage only accepted consumer-owned changes, and disclose when local validation depended on the workaround. Required CI/policy remains authoritative. If the workaround is staged, appears in the proposed consumer commit/PR, no longer matches the handoff, or ownership becomes ambiguous, stop and re-evaluate.
38
40
 
39
41
  Package-managed generated Projects use `/project-forge-update`. Direct `/core-sync` remains only for component-only Core consumers without `PROJECT_FORGE_BASELINE.json` and is not part of the normal greenfield Project command surface.
40
42
 
@@ -132,6 +132,8 @@ When application source/runtime exists, converge only the repository-owned local
132
132
 
133
133
  Verify supported tools/versions using repository setup/doctor tooling when present. Run repository-defined dependency restore/setup commands when missing or stale. Preserve pinned versions and project conventions.
134
134
 
135
+ Treat **installation**, **version compatibility**, and **operational readiness** as separate evidence when tooling exposes those distinctions. A successful CLI/version probe does not prove that the backing service/runtime is operational. For Docker-based setup, do not call the runtime ready merely because `docker --version` succeeds; require the repository/doctor operational probe before relying on Docker Engine capability.
136
+
135
137
  ### B. Local persistence
136
138
 
137
139
  For SQLite local development, resolve the project-owned database path and migration/initialization contract from repository evidence. Prefer installed Deployment Kit local SQLite ensure/status primitives when available.
@@ -244,6 +246,63 @@ For remote SSH preserve strict host identity. Unknown/changed host identity is a
244
246
 
245
247
  Remote readiness does not require configuring Production when the selected environment is non-Production. Production classification remains project topology/policy, not a literal-name check.
246
248
 
249
+ ### Guided remote failure recovery is part of `/setup`
250
+
251
+ A supported deterministic setup/readiness failure is not, by itself, the end of `/setup`. When installed Deployment Kit tooling returns structured diagnosis or a bounded next action, continue through that diagnosis automatically until one of these boundaries is reached:
252
+
253
+ - the failure is repaired through already-authorized routine setup work;
254
+ - a missing human fact is required;
255
+ - a separate write/Production/destructive authorization is required;
256
+ - a trusted-console or already-authorized administrative action is required;
257
+ - the capability is unsupported or remains blocked after bounded diagnosis.
258
+
259
+ Do **not** merely repeat an opaque subprocess exit code and tell the developer to fix access independently when deterministic diagnosis is available.
260
+
261
+ For SSH target-access failure, prefer the Deployment Kit's structured environment setup status/plan evidence. Preserve distinct categories such as:
262
+
263
+ ```text
264
+ name resolution / address path
265
+ TCP reachability
266
+ host identity/trust
267
+ server-advertised authentication methods
268
+ configured identity fingerprint/offered key
269
+ local signing/passphrase/agent failure
270
+ remote public-key rejection
271
+ remote account/source-policy rejection
272
+ ```
273
+
274
+ Keep credentials, private keys, raw secure-prompt content, and unbounded SSH transcripts out of conversational diagnostics and journals.
275
+
276
+ If client-side evidence shows that the configured key reached the server but access is still rejected, stop reinstalling the same key. Route to a trusted target console or already-authorized administrative session to inspect effective account/source policy. Do not guess that `AllowUsers`, `AllowGroups`, PAM, or another server rule is the exact cause until server-side evidence establishes it.
277
+
278
+ ### Gate password-assisted bootstrap on server capability
279
+
280
+ Before recommending a password-assisted/Home Lab bootstrap against a reachable server, use deterministic evidence of the server-advertised authentication methods when the installed Deployment Kit supports that probe.
281
+
282
+ - If password or keyboard-interactive authentication is not advertised, do not send the developer through a password bootstrap that cannot succeed.
283
+ - Route instead to strict key onboarding plus a trusted console/already-authorized session for any required server-side key/account-policy change.
284
+ - Never recommend enabling password SSH merely to make Project Forge onboarding work.
285
+
286
+ For Production-class environments, prefer the higher-assurance Strict onboarding path for new target trust/access unless the project/operator explicitly chooses a different supported security profile. Staging and other non-Production environments use the same target-access mechanics, with their own environment classification and authorization policy.
287
+
288
+ ### Console-assisted recovery instructions
289
+
290
+ When a trusted-console action is required, optimize for reliable execution rather than dense shell snippets:
291
+
292
+ - one short command or one coherent semicolon-separated command per step;
293
+ - avoid unnecessary wildcards, escaping, and shell-specific quoting;
294
+ - say explicitly what the developer should run versus what output to return;
295
+ - state the expected evidence and the stop condition;
296
+ - use screenshot inspection when transcription is repeatedly failing.
297
+
298
+ Never silently edit `sshd`, widen account/source policy, disable host verification, or switch authentication policy merely to make setup pass.
299
+
300
+ ### Treat target evidence and environment evidence separately
301
+
302
+ A verified workstation-to-target access relationship may be reused by multiple Projects/environments that bind to the same logical target. Environment proof remains specific to the Project + named environment + target + adapter/isolation contract.
303
+
304
+ When Staging and Production share one physical target, explicitly surface the shared failure domain and verify that their Project/environment-owned runtime identity, compose project, route/port allocation, persistence paths, and locking cannot collide. Staging evidence does not become Production evidence merely because the host is shared.
305
+
247
306
  ## 8. Prove supported remote mechanics with a disposable Project Forge probe
248
307
 
249
308
  When the installed Deployment Kit exposes environment proof operations, a selected remote environment should normally be taken through an end-to-end **environment proof deployment** during setup.
@@ -276,6 +335,8 @@ For a Production-class environment, keep the proof explicitly labeled as a **PRO
276
335
 
277
336
  If cleanup fails, report `PROOF PASSED — CLEANUP ACTION NEEDED`; do not claim a clean setup.
278
337
 
338
+ When installed Deployment Kit provides a durable local proof receipt or equivalent discoverable evidence, record/reuse it rather than relying on chat history. Reuse only while its target binding, host identity, workstation identity, adapter/provenance, logical environment, and cleanup result remain applicable. A new chat alone must not invalidate valid machine evidence.
339
+
279
340
  ## 9. `repair` is bounded and fail-closed
280
341
 
281
342
  `/setup repair` may re-run safe deterministic setup/readiness operations after classifying the blocker. It may create missing local directories/caches, restore dependencies, rebuild outputs, create a new owned local database, run normal forward initialization, or recreate an owned disposable/local runtime when the repository contract permits those actions.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: upstream-fix
3
- description: Route reusable bugs discovered in a consumer to the canonical shared repository, allow bounded upstream implementation, and return adoption through the consumer's actual provenance/update boundary.
3
+ description: Route reusable bugs discovered in a consumer to the canonical shared repository, allow bounded upstream implementation, preserve a portable handoff, and let consumer work continue with explicitly acknowledged temporary Project Forge drift.
4
4
  argument-hint: "[optional problem summary]"
5
5
  user-invocable: true
6
6
  disable-model-invocation: true
@@ -15,8 +15,10 @@ The governing rule is:
15
15
  ```text
16
16
  discover in consumer
17
17
  → diagnose/prove in consumer
18
- → fix in owning canonical repository
19
- → deliver there
18
+ → classify canonical owner
19
+ → preserve a portable upstream handoff
20
+ → optionally continue consumer work with acknowledged temporary drift
21
+ → fix/deliver in owning canonical repository
20
22
  → adopt through the consumer's recorded distribution boundary
21
23
  → verify again in consumer
22
24
  ```
@@ -29,10 +31,11 @@ Invoking `/upstream-fix` authorizes:
29
31
 
30
32
  - read-only ownership/provenance inspection in the consumer;
31
33
  - classification to the smallest canonical owner;
34
+ - creation/update of the ignored local handoff artifact `.project-forge/UPSTREAM_FIX_HANDOFF.md`;
32
35
  - inspection of already-available local canonical repository candidates;
33
36
  - when ownership and the bounded patch are clear and a canonical checkout is safe, routine creation/use of one short-lived canonical work branch and application of only that bounded fix plus focused tests/docs.
34
37
 
35
- Invocation does **not** authorize commit, push, PR creation, merge, release publication, package publication, deployment, rewriting/discarding consumer work, or changing multiple canonical repositories in one bounded fix.
38
+ Invocation does **not** authorize commit, push, PR creation, merge, release publication, package publication, deployment, rewriting/discarding consumer work, changing multiple canonical repositories in one bounded fix, or committing a temporary shared-managed consumer workaround.
36
39
 
37
40
  Normal review and `/deliver` occur later while focused on the owning canonical repository.
38
41
 
@@ -99,7 +102,7 @@ Owner: package/platform repository supported by evidence
99
102
 
100
103
  If the package payload is correct but generation/publication/orchestration materializes it incorrectly, classify Bootstrap/control-plane ownership from evidence rather than patching a generated consumer.
101
104
 
102
- If ownership is genuinely ambiguous, stop at `UPSTREAM OWNER UNCLEAR`. Do not write to multiple repositories speculatively.
105
+ If ownership is genuinely ambiguous, report `UPSTREAM OWNER UNCLEAR`. Preserve the observed evidence in the handoff artifact, but do not write to multiple repositories speculatively.
103
106
 
104
107
  ## 4. Temporary consumer proof
105
108
 
@@ -111,12 +114,95 @@ Report it explicitly:
111
114
  TEMPORARY SHARED-MANAGED PROOF
112
115
  Consumer path: <path>
113
116
  Canonical owner: <repo>
114
- Do not deliver this consumer copy.
117
+ Do not deliver this consumer copy as product code.
115
118
  ```
116
119
 
117
120
  Do not silently discard the proof and do not stage/commit it as ordinary consumer implementation.
118
121
 
119
- ## 5. Resolve a safe canonical checkout
122
+ ## 5. Preserve a portable handoff
123
+
124
+ Once a likely shared owner exists, create or refresh:
125
+
126
+ ```text
127
+ .project-forge/UPSTREAM_FIX_HANDOFF.md
128
+ ```
129
+
130
+ This file is workstation/session evidence for transfer into ChatGPT or another canonical-owner workspace. It is not product documentation and must remain unstaged/uncommitted. Generated Project Forge projects normally ignore `.project-forge/`; if repository policy does not ignore it, keep the handoff out of the consumer delivery diff.
131
+
132
+ Include only observed/non-secret evidence:
133
+
134
+ ```markdown
135
+ # Project Forge Upstream Fix Handoff
136
+
137
+ ## Consumer context
138
+ - Repository: <owner/repo or local identity>
139
+ - Branch/work item: <observed>
140
+ - Project Forge package/baseline: <observed version/commit/profile>
141
+
142
+ ## Classification
143
+ - Owner: <Core | Deployment Kit | Platform | Bootstrap | Control Plane | unclear>
144
+ - Canonical repository: <repo when known>
145
+ - Managed consumer paths involved: <paths>
146
+
147
+ ## Problem
148
+ <concise symptom and expected behavior>
149
+
150
+ ## Reproduction
151
+ <minimal observed reproduction>
152
+
153
+ ## Temporary consumer proof
154
+ - Status: <none | local proof present>
155
+ - Paths: <paths>
156
+ - Diff summary: <summary, not secrets>
157
+ - Validation: <observed checks>
158
+
159
+ ## Recommended upstream scope
160
+ <smallest reusable change and focused regression coverage>
161
+
162
+ ## Adoption boundary
163
+ <package release / component sync / regeneration / other evidence-backed path>
164
+
165
+ ## Consumer continuation
166
+ - Override: <not requested | accepted>
167
+ - Managed workaround must remain unstaged/uncommitted: yes
168
+ - Known dependency of current consumer checks on workaround: <yes/no/unknown>
169
+ ```
170
+
171
+ The handoff is useful even when a canonical checkout is unavailable or the upstream fix will be handled later.
172
+
173
+ ## 6. Consumer continuation override
174
+
175
+ A reusable-platform defect is **not automatically a reason to halt the consumer work item**.
176
+
177
+ After classification/handoff, when the current consumer work can still proceed without committing the temporary shared-managed workaround, present one bounded single-select choice through the host-native question UI when available:
178
+
179
+ - `Continue consumer work with acknowledged Project Forge drift` — permits the current consumer session/work item to continue while the shared-managed workaround remains local and excluded from delivery. **RECOMMENDED** when the workaround is isolated and continuing will produce useful consumer-owned work.
180
+ - `Resolve the upstream fix now` — switch focus to the canonical owner and continue the upstream workflow.
181
+ - `Stop here` — preserve state without further writes.
182
+
183
+ Use a numbered text list only when native structured choice UI is unavailable.
184
+
185
+ Selecting the continuation option means:
186
+
187
+ ```text
188
+ PROJECT FORGE DRIFT OVERRIDE ACCEPTED
189
+ ```
190
+
191
+ Record that choice in `.project-forge/UPSTREAM_FIX_HANDOFF.md` and continue normal consumer implementation. Do not repeatedly ask the same override question in the same unchanged session/work-item state.
192
+
193
+ The override authorizes **continuation only**. It does not authorize:
194
+
195
+ - staging/committing/pushing shared-managed drift;
196
+ - editing baselines to bless the drift;
197
+ - bypassing required CI, Reviewer, merge, release, or Production gates;
198
+ - destructive cleanup of the workaround;
199
+ - claiming the consumer has adopted the canonical fix.
200
+
201
+ If consumer-owned implementation genuinely cannot be separated from the modified managed file, report that dependency clearly. The human may still continue exploratory/product work under the override, but normal delivery can only stage consumer-owned paths and required CI/policy may still fail until the upstream fix is distributed.
202
+
203
+ Unexplained managed drift, suspected secrets, ambiguous ownership, or a staged/shared-managed workaround remains a stop condition until classified or removed from the proposed consumer delivery scope.
204
+
205
+ ## 7. Resolve a safe canonical checkout
120
206
 
121
207
  For the classified owner consider, in order:
122
208
 
@@ -128,7 +214,9 @@ Do not broadly scan the filesystem and do not clone automatically merely to cont
128
214
 
129
215
  A candidate is safe only when it is the expected repository, has no merge/rebase/cherry-pick in progress, has no unrelated local work, and does not require stash/reset/rebase/force/discard operations.
130
216
 
131
- ## 6. Port the bounded fix upstream
217
+ If no safe canonical checkout is available, the handoff plus continuation override is a valid outcome; do not block consumer implementation solely because canonical work cannot start immediately.
218
+
219
+ ## 8. Port the bounded fix upstream
132
220
 
133
221
  When a safe canonical checkout exists and the equivalent reusable fix is clear:
134
222
 
@@ -141,9 +229,9 @@ When a safe canonical checkout exists and the equivalent reusable fix is clear:
141
229
  7. run relevant local checks;
142
230
  8. show the meaningful canonical diff and observed validation.
143
231
 
144
- If the consumer proof cannot be generalized safely, stop and reclassify rather than forcing it upstream.
232
+ If the consumer proof cannot be generalized safely, reclassify and update the handoff rather than forcing it upstream.
145
233
 
146
- ## 7. Handoff to canonical delivery
234
+ ## 9. Handoff to canonical delivery
147
235
 
148
236
  When the upstream implementation is ready:
149
237
 
@@ -153,13 +241,16 @@ UPSTREAM FIX READY
153
241
  Owner: <canonical repo>
154
242
  Branch: <branch>
155
243
  Consumer proof: <path/status>
244
+ Portable handoff: .project-forge/UPSTREAM_FIX_HANDOFF.md
156
245
  Validation: <observed checks>
157
246
  Next: focus the canonical repository and run /deliver
158
247
  ```
159
248
 
160
249
  `/upstream-fix` does not commit/push/open/merge the canonical PR itself.
161
250
 
162
- ## 8. Adopt the accepted fix through the right boundary
251
+ If the consumer continuation override was accepted, returning to consumer work does not wait for canonical delivery unless current work truly requires the distributed fix.
252
+
253
+ ## 10. Adopt the accepted fix through the right boundary
163
254
 
164
255
  After the canonical PR is merged and required default-branch CI is green, re-read the consumer provenance before choosing adoption.
165
256
 
@@ -182,7 +273,8 @@ Until that package exists, report:
182
273
 
183
274
  ```text
184
275
  PACKAGE RELEASE REQUIRED
185
- Consumer adoption is blocked on a Project Forge package that contains the accepted upstream commit.
276
+ Canonical consumer adoption requires a Project Forge package that contains the accepted upstream commit.
277
+ Consumer work may continue under an accepted drift override as long as shared-managed workaround paths remain outside consumer delivery.
186
278
  ```
187
279
 
188
280
  Do not silently patch `PROJECT_FORGE_BASELINE.json`, `CORE_BASELINE.json`, or `DEPLOYMENT_BASELINE.json` to pretend the package contains the new component.
@@ -199,15 +291,40 @@ A Deployment-owned fix may return through the canonical Deployment Kit component
199
291
 
200
292
  Validate through that platform's canonical regeneration/update path, never by manually editing generated managed files.
201
293
 
202
- Then rerun the original reproduction and baseline checks in the consumer.
294
+ Then rerun the original reproduction and baseline checks in the consumer when adoption actually occurs.
295
+
296
+ ## 11. Consumer delivery guard
297
+
298
+ Before consumer `/deliver`, distinguish **unexplained managed drift** from **explained/acknowledged temporary upstream proof**.
299
+
300
+ ### Unexplained managed drift
301
+
302
+ If `/deliver` finds Core-, Deployment-, or Project Forge-package-managed drift with no matching upstream classification/handoff/override, stop before staging/commit/push and route through `/upstream-fix`.
303
+
304
+ ### Explained drift with accepted continuation override
203
305
 
204
- ## 9. Consumer delivery guard
306
+ When `.project-forge/UPSTREAM_FIX_HANDOFF.md` records the current managed paths and the human accepted continuation for the unchanged issue:
307
+
308
+ 1. warn prominently that Project Forge managed drift is still present;
309
+ 2. keep all shared-managed drift and the handoff file unstaged/uncommitted;
310
+ 3. selectively stage only the human-accepted consumer-owned implementation;
311
+ 4. disclose in the PR body that local validation may have used an acknowledged Project Forge workaround when that is true;
312
+ 5. proceed with normal PR/CI mechanics rather than hard-stopping solely because the local workaround exists.
313
+
314
+ Use a compact warning such as:
315
+
316
+ ```text
317
+ PROJECT FORGE DRIFT WARNING
318
+ Upstream handoff: .project-forge/UPSTREAM_FIX_HANDOFF.md
319
+ Managed workaround: present locally, excluded from consumer delivery
320
+ Consumer delivery: continuing under accepted override
321
+ ```
205
322
 
206
- If `/deliver` is invoked in a consumer with unexplained Core-, Deployment-, or Project Forge-package-managed drift, stop before staging/commit/push. Route reusable managed-file changes through `/upstream-fix` and then through the appropriate accepted update boundary.
323
+ Required CI/policy remains authoritative. Do not waive a failing required check because the failure is caused by the absent upstream fix.
207
324
 
208
- Consumer-owned changes may be delivered normally when managed baselines are clean.
325
+ If any shared-managed path is already staged, appears in the proposed consumer commit/PR, no longer matches the handoff, or ownership becomes ambiguous, stop and re-evaluate before writing.
209
326
 
210
- ## 10. Boundaries
327
+ ## 12. Boundaries
211
328
 
212
329
  `/upstream-fix` never:
213
330
 
@@ -218,4 +335,6 @@ Consumer-owned changes may be delivered normally when managed baselines are clea
218
335
  - auto-stashes, resets, rebases, force-pushes, or discards work;
219
336
  - requires ordinary consumer users to clone shared repositories;
220
337
  - treats a temporary managed consumer edit as a permanent fork;
221
- - bypasses `PROJECT_FORGE_BASELINE.json` with component-only sync.
338
+ - bypasses `PROJECT_FORGE_BASELINE.json` with component-only sync;
339
+ - treats the continuation override as authorization to commit shared-managed drift;
340
+ - treats the continuation override as a waiver of required CI or merge policy.
@@ -56,6 +56,8 @@ project-forge-deploy environment setup plan <target> \
56
56
 
57
57
  These commands never perform the proof or authorize a write. They make `TARGET ACCESS READY`, `HOST PLATFORM READY`, and `DEPLOYMENT PATH PROVEN` separate states.
58
58
 
59
+ When owner/repository and logical environment context are supplied, setup planning also checks the current workstation for a still-applicable prior proof receipt before recommending another proof run.
60
+
59
61
  ## Commands
60
62
 
61
63
  Read-only plan:
@@ -120,6 +122,8 @@ mutated
120
122
  finalMutationState
121
123
  error
122
124
  cleanupError
125
+ receipt
126
+ receiptError
123
127
  ```
124
128
 
125
129
  A read-only plan does not claim `mutated: false` as though it were the eventual run result. The run reports whether transfer/runtime mutation actually occurred and whether cleanup completed.
@@ -136,6 +140,28 @@ A loaded Docker image may remain cached after runtime cleanup. That state is rep
136
140
 
137
141
  The probe must not delete another Project, another application, another logical environment, or shared host platform state.
138
142
 
143
+ ## Workstation-local proof receipt
144
+
145
+ Every terminal proof run attempts to write a compact workstation-local proof receipt under the user's Project Forge evidence directory. The receipt is diagnostic/readiness evidence only; it is not deployment authorization and is not repository content.
146
+
147
+ The receipt records only non-secret evidence needed to decide whether the prior proof is still applicable, including:
148
+
149
+ - Project owner/repository;
150
+ - exact logical environment;
151
+ - logical target name and Production classification;
152
+ - Deployment Kit/proof contract version;
153
+ - proof/cleanup/final mutation state;
154
+ - immutable probe artifact identities when available;
155
+ - a hash-based signature of the current target profile, configured workstation identity fingerprint, and target trust file.
156
+
157
+ It never stores private keys, passwords, tokens, known-host contents, or application secrets.
158
+
159
+ `environment setup plan` treats the receipt as `PROVEN` only when the latest receipt passed with terminal cleanup and still matches the current Project/environment/target context and current workstation target identity/trust. A target/profile/trust change, Production-classification change, proof-contract change, or Deployment Kit version change makes the evidence stale and causes a new proof to be planned.
160
+
161
+ A **new chat or new assistant session alone does not invalidate proof**. Evidence validity is based on machine/project/environment facts, not conversation history.
162
+
163
+ A failed proof may also leave a receipt, but that receipt is explicitly `not-proven` and is never promoted to readiness.
164
+
139
165
  ## Relationship to `/setup` and `/deploy`
140
166
 
141
167
  `/setup remote` or `/setup <environment>` may use deterministic setup status/plan first, then run this proof after the developer selects the named remote environment and the relevant write authorization is granted.
@@ -14,6 +14,7 @@ from .app_runtime_workstation import apply_app_deploy_with_preloaded_image
14
14
  from .box_platform import platform_status
15
15
  from .errors import DeploymentKitError
16
16
  from .image_transfer import remote_image_present, transfer_image, verify_local_image
17
+ from .proof_receipt import write_environment_proof_receipt
17
18
  from .registry_access import normalize_registry_image
18
19
  from .teardown import tear_down_project
19
20
 
@@ -152,6 +153,8 @@ def _proof_result(plan: dict[str, Any]) -> dict[str, Any]:
152
153
  "finalMutationState": "none",
153
154
  "error": None,
154
155
  "cleanupError": None,
156
+ "receipt": None,
157
+ "receiptError": None,
155
158
  }
156
159
 
157
160
 
@@ -298,4 +301,8 @@ def run_environment_proof(plan: dict[str, Any]) -> dict[str, Any]:
298
301
  result["error"] = "Environment proof cleanup did not return terminal runtime cleanup evidence."
299
302
 
300
303
  result["finalMutationState"] = _final_mutation_state(result)
304
+ try:
305
+ result["receipt"] = write_environment_proof_receipt(result)
306
+ except Exception as error: # proof result stays truthful even if local evidence persistence fails
307
+ result["receiptError"] = str(error)
301
308
  return result