@mriekki/project-forge 2.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/components.json +4 -4
- package/assets/core/distribution.json +0 -4
- package/assets/deployment/distribution.json +1 -1
- package/assets/generated/ASSEMBLY.json +31 -51
- package/assets/generated/core/core/instructions/project-forge-workflow.instructions.md +8 -2
- package/assets/generated/core/core/process/DEPLOYMENT_ENABLEMENT.md +1 -1
- package/assets/generated/core/core/process/INTERACTIVE_SESSION_GUIDE.md +1 -2
- package/assets/generated/core/core/process/OPERATION_JOURNAL.md +1 -2
- package/assets/generated/core/core/process/PROJECT_DOCUMENTATION_FRAMEWORK.md +3 -3
- package/assets/generated/core/core/process/PROJECT_FORGE_ENGINEERING_GUIDE.md +14 -14
- package/assets/generated/core/core/skills/deploy/SKILL.md +1 -1
- package/assets/generated/core/core/skills/deployment-readiness/SKILL.md +1 -1
- package/assets/generated/core/core/skills/grill-me/SKILL.md +84 -46
- package/assets/generated/core/core/skills/progress/SKILL.md +1 -1
- package/assets/generated/core/core/skills/setup/SKILL.md +149 -199
- package/assets/generated/core/core/skills/start-work/SKILL.md +5 -6
- package/assets/generated/core/core/skills/tear-down/SKILL.md +4 -4
- package/assets/generated/deployment/docs/DEVELOPER_ENVIRONMENTS.md +11 -11
- package/assets/generated/deployment/docs/ENVIRONMENT_PROOF.md +2 -2
- package/assets/generated/deployment/docs/WORKSPACE_INSTANCES.md +1 -1
- package/assets/generated/deployment/docs/images/developer-environment-journey.svg +2 -2
- package/assets/generated/deployment/docs/images/{poc-environment-model.svg → project-environment-model.svg} +4 -4
- package/assets/generated/deployment/src/project_forge_deployment/cli.py +1 -1
- package/assets/generated/deployment/src/project_forge_deployment/entrypoint.py +1 -1
- package/assets/generated/deployment/src/project_forge_deployment/environment_probe.py +2 -2
- package/assets/generated/deployment/src/project_forge_deployment/route_registry.py +2 -2
- package/assets/generated/deployment/src/project_forge_deployment/teardown.py +7 -7
- package/assets/generated/deployment/src/project_forge_deployment/teardown_cli.py +6 -6
- package/assets/generated/deployment/src/project_forge_deployment/teardown_remote.py +6 -6
- package/package.json +1 -1
- package/assets/generated/core/core/agents/coach.agent.md +0 -69
- package/assets/generated/core/core/skills/core-sync/SKILL.md +0 -184
- package/assets/generated/core/core/skills/developer-env-mode/SKILL.md +0 -231
- package/assets/generated/core/core/skills/grill-with-docs/SKILL.md +0 -88
|
@@ -13,7 +13,7 @@ The happy path intentionally hides Bootstrap/package/control-plane plumbing. Dev
|
|
|
13
13
|
The normal progression is:
|
|
14
14
|
|
|
15
15
|
```text
|
|
16
|
-
generated
|
|
16
|
+
generated Project repository
|
|
17
17
|
→ clone/open workspace
|
|
18
18
|
→ /setup
|
|
19
19
|
→ LOCAL READY
|
|
@@ -42,7 +42,7 @@ The normal conversational entry point is:
|
|
|
42
42
|
|
|
43
43
|
`/setup` explains the current state/options and invokes the correct repository-local setup launcher. Direct script invocation remains the non-AI/automation fallback.
|
|
44
44
|
|
|
45
|
-
The first local success target is `LOCAL WORKSPACE READY`. Remote access must not block it unless the
|
|
45
|
+
The first local success target is `LOCAL WORKSPACE READY`. Remote access must not block it unless the Project explicitly requires a remote dependency for local development.
|
|
46
46
|
|
|
47
47
|
## Progress and next action
|
|
48
48
|
|
|
@@ -156,11 +156,11 @@ A changed previously pinned host key remains a blocker and requires explicit tru
|
|
|
156
156
|
|
|
157
157
|
## Docker and host preparation
|
|
158
158
|
|
|
159
|
-
Docker is a workstation/target capability, not something every
|
|
159
|
+
Docker is a workstation/target capability, not something every Project should reinstall.
|
|
160
160
|
|
|
161
161
|
### Developer workstation
|
|
162
162
|
|
|
163
|
-
The first
|
|
163
|
+
The first Project on a computer may install/verify required local tools and Docker through the generated setup contract. Later Projects reuse the ready workstation.
|
|
164
164
|
|
|
165
165
|
### Remote Ubuntu target
|
|
166
166
|
|
|
@@ -209,17 +209,17 @@ A credential needed to acquire a private image is entered only through the local
|
|
|
209
209
|
|
|
210
210
|
If the exact immutable image is already cached locally, registry authentication is not required merely to transfer it to the remote target.
|
|
211
211
|
|
|
212
|
-
##
|
|
212
|
+
## Project environment model
|
|
213
213
|
|
|
214
|
-

|
|
215
215
|
|
|
216
|
-
The
|
|
216
|
+
The Project owns project-specific facts such as environment identities/roles, placement, target binding, application image, runtime/health contract, persistence, routes/exposure, and Production classification/authorization.
|
|
217
217
|
|
|
218
|
-
The reusable workstation/target layer owns machine mechanics. A
|
|
218
|
+
The reusable workstation/target layer owns machine mechanics. A Project references targets; it does not own or duplicate a developer's private credentials.
|
|
219
219
|
|
|
220
220
|
## New workstation
|
|
221
221
|
|
|
222
|
-
A developer normally starts from any generated
|
|
222
|
+
A developer normally starts from any generated Project:
|
|
223
223
|
|
|
224
224
|
```text
|
|
225
225
|
clone repository
|
|
@@ -233,7 +233,7 @@ When GitHub is reachable, personal profile sync supplies portable target definit
|
|
|
233
233
|
|
|
234
234
|
## New remote box
|
|
235
235
|
|
|
236
|
-
Adding a new remote target is a workstation-driven onboarding operation, not a
|
|
236
|
+
Adding a new remote target is a workstation-driven onboarding operation, not a Project implementation step:
|
|
237
237
|
|
|
238
238
|
```text
|
|
239
239
|
add/import portable target definition
|
|
@@ -243,7 +243,7 @@ add/import portable target definition
|
|
|
243
243
|
→ TARGET READY
|
|
244
244
|
```
|
|
245
245
|
|
|
246
|
-
Once ready, multiple
|
|
246
|
+
Once ready, multiple Projects can bind logical environments to that target without repeating host bootstrap.
|
|
247
247
|
|
|
248
248
|
## Portable export/import fallback
|
|
249
249
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Environment Proof Deployment
|
|
2
2
|
|
|
3
|
-
A Project Forge environment proof verifies that one developer workstation can exercise the real remote deployment path for one exact named logical environment before the
|
|
3
|
+
A Project Forge environment proof verifies that one developer workstation can exercise the real remote deployment path for one exact named logical environment before the Project application exists or before its first real deployment.
|
|
4
4
|
|
|
5
5
|
It is intentionally **not** the project application.
|
|
6
6
|
|
|
@@ -84,7 +84,7 @@ The proof attempts cleanup even when deployment raises after mutation begins.
|
|
|
84
84
|
|
|
85
85
|
Successful completion requires terminal cleanup evidence (`removed` or already `absent`) for the reserved probe runtime. If deployment succeeds but cleanup cannot be verified, the command fails rather than reporting a clean proof.
|
|
86
86
|
|
|
87
|
-
The probe must not delete another
|
|
87
|
+
The probe must not delete another Project, another application, another logical environment, or shared host platform state.
|
|
88
88
|
|
|
89
89
|
## Relationship to `/setup` and `/deploy`
|
|
90
90
|
|
|
@@ -63,7 +63,7 @@ Local mutable application data is not synchronized between workstations by Proje
|
|
|
63
63
|
|
|
64
64
|
## Setup on another workstation
|
|
65
65
|
|
|
66
|
-
The normal flow for an existing generated
|
|
66
|
+
The normal flow for an existing generated Project is:
|
|
67
67
|
|
|
68
68
|
```text
|
|
69
69
|
clone repository
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="520" viewBox="0 0 1200 520" role="img" aria-labelledby="title desc">
|
|
2
2
|
<title id="title">Project Forge developer environment journey</title>
|
|
3
|
-
<desc id="desc">Generated
|
|
3
|
+
<desc id="desc">Generated Project repository progresses through clone and setup to local ready, then optionally to staging ready and production ready.</desc>
|
|
4
4
|
<defs>
|
|
5
5
|
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
6
6
|
<stop offset="0" stop-color="#0b1220"/>
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<g filter="url(#shadow)" font-family="Inter,Segoe UI,Arial,sans-serif">
|
|
21
21
|
<rect x="70" y="180" width="205" height="128" rx="18" fill="#1e2a40" stroke="#405274" stroke-width="2"/>
|
|
22
22
|
<text x="172" y="222" text-anchor="middle" font-size="15" font-weight="700" fill="#91a4c4">PROJECT</text>
|
|
23
|
-
<text x="172" y="254" text-anchor="middle" font-size="22" font-weight="700" fill="#ffffff">Generated
|
|
23
|
+
<text x="172" y="254" text-anchor="middle" font-size="22" font-weight="700" fill="#ffffff">Generated Project</text>
|
|
24
24
|
<text x="172" y="282" text-anchor="middle" font-size="15" fill="#b8c5d8">clone + open workspace</text>
|
|
25
25
|
|
|
26
26
|
<rect x="360" y="180" width="205" height="128" rx="18" fill="#1f3440" stroke="#3b7584" stroke-width="2"/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="720" viewBox="0 0 1200 720" role="img" aria-labelledby="title desc">
|
|
2
2
|
<title id="title">Project Forge environment model</title>
|
|
3
|
-
<desc id="desc">A
|
|
3
|
+
<desc id="desc">A Project uses local workstation runtime and optional remote logical staging and production environments bound to reusable remote targets and shared host platform infrastructure.</desc>
|
|
4
4
|
<defs>
|
|
5
5
|
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
6
6
|
<stop offset="0" stop-color="#0b1220"/>
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
</marker>
|
|
15
15
|
</defs>
|
|
16
16
|
<rect width="1200" height="720" rx="24" fill="url(#bg)"/>
|
|
17
|
-
<text x="70" y="70" font-family="Inter,Segoe UI,Arial,sans-serif" font-size="30" font-weight="700" fill="#f7f9fc">
|
|
18
|
-
<text x="70" y="102" font-family="Inter,Segoe UI,Arial,sans-serif" font-size="17" fill="#aebbd0">The
|
|
17
|
+
<text x="70" y="70" font-family="Inter,Segoe UI,Arial,sans-serif" font-size="30" font-weight="700" fill="#f7f9fc">Project Environment Model</text>
|
|
18
|
+
<text x="70" y="102" font-family="Inter,Segoe UI,Arial,sans-serif" font-size="17" fill="#aebbd0">The Project owns application/environment facts; reusable workstation and target layers own machine mechanics.</text>
|
|
19
19
|
|
|
20
20
|
<g filter="url(#shadow)" font-family="Inter,Segoe UI,Arial,sans-serif">
|
|
21
21
|
<rect x="390" y="135" width="420" height="106" rx="20" fill="#25294a" stroke="#7277c9" stroke-width="2"/>
|
|
22
|
-
<text x="600" y="176" text-anchor="middle" font-size="15" font-weight="700" fill="#aaaef1">GENERATED
|
|
22
|
+
<text x="600" y="176" text-anchor="middle" font-size="15" font-weight="700" fill="#aaaef1">GENERATED Project</text>
|
|
23
23
|
<text x="600" y="209" text-anchor="middle" font-size="21" font-weight="700" fill="#ffffff">Environment bindings + app runtime facts</text>
|
|
24
24
|
|
|
25
25
|
<rect x="95" y="330" width="300" height="190" rx="20" fill="#173c35" stroke="#3a9d82" stroke-width="2"/>
|
|
@@ -283,7 +283,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
283
283
|
route_inventory_parser.add_argument("--json", action="store_true")
|
|
284
284
|
|
|
285
285
|
route_register = route_sub.add_parser(
|
|
286
|
-
"register", help="Create or update one
|
|
286
|
+
"register", help="Create or update one Project/environment-owned Caddy + mDNS route"
|
|
287
287
|
)
|
|
288
288
|
route_register.add_argument("name")
|
|
289
289
|
route_register.add_argument("--owner-repo", required=True)
|
|
@@ -33,5 +33,5 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
33
33
|
print("Command group: local Loopback-only workstation application runtime")
|
|
34
34
|
print("Command group: registry Read-only exact-image registry access verification")
|
|
35
35
|
print("Command group: sqlite SQLite persistence import/backup/migration/rollback checks")
|
|
36
|
-
print("Command group: tear-down Scoped destructive
|
|
36
|
+
print("Command group: tear-down Scoped destructive Project environment/local cleanup")
|
|
37
37
|
return core_main(args)
|
|
@@ -14,7 +14,7 @@ from .app_runtime_workstation import apply_app_deploy_from_workstation
|
|
|
14
14
|
from .box_platform import platform_status
|
|
15
15
|
from .errors import DeploymentKitError
|
|
16
16
|
from .registry_access import normalize_registry_image
|
|
17
|
-
from .teardown import
|
|
17
|
+
from .teardown import tear_down_project
|
|
18
18
|
|
|
19
19
|
ENVIRONMENT_PROOF_WRITE_PHRASE = "[ENVIRONMENT PROOF WRITE]"
|
|
20
20
|
PRODUCTION_ENVIRONMENT_PROOF_WRITE_PHRASE = "[PRODUCTION ENVIRONMENT PROOF]"
|
|
@@ -171,7 +171,7 @@ def run_environment_proof(plan: dict[str, Any]) -> dict[str, Any]:
|
|
|
171
171
|
deploy_error = error
|
|
172
172
|
finally:
|
|
173
173
|
try:
|
|
174
|
-
cleanup =
|
|
174
|
+
cleanup = tear_down_project(
|
|
175
175
|
{
|
|
176
176
|
"ownerRepo": plan["ownerRepo"],
|
|
177
177
|
"appSlug": plan["probeAppSlug"],
|
|
@@ -270,7 +270,7 @@ def plan_route_registration(
|
|
|
270
270
|
owner_fields = ("ownerRepo", "environment", "appSlug")
|
|
271
271
|
if any(existing[field] != spec[field] for field in owner_fields):
|
|
272
272
|
raise DeploymentKitError(
|
|
273
|
-
f"Route ID {spec['routeId']} is already owned by another
|
|
273
|
+
f"Route ID {spec['routeId']} is already owned by another Project/environment; refusing takeover."
|
|
274
274
|
)
|
|
275
275
|
requested = set(spec["hostnames"])
|
|
276
276
|
for route in inventory["managedRoutes"]:
|
|
@@ -312,7 +312,7 @@ def plan_route_removal(
|
|
|
312
312
|
if existing is None:
|
|
313
313
|
raise DeploymentKitError(f"Managed route does not exist: {route_id}")
|
|
314
314
|
if existing["ownerRepo"] != owner_repo or existing["environment"] != environment or existing["appSlug"] != app_slug:
|
|
315
|
-
raise DeploymentKitError("Route removal ownership does not match the registered
|
|
315
|
+
raise DeploymentKitError("Route removal ownership does not match the registered Project/environment.")
|
|
316
316
|
return {
|
|
317
317
|
"targetName": name,
|
|
318
318
|
"action": "remove",
|
|
@@ -15,7 +15,7 @@ from .route_registry import apply_route_change, plan_route_removal, route_invent
|
|
|
15
15
|
from .ssh import ssh_args, verify_access
|
|
16
16
|
from .teardown_remote import REMOTE_SCRIPT
|
|
17
17
|
|
|
18
|
-
TEAR_DOWN_WRITE_PHRASE = "[
|
|
18
|
+
TEAR_DOWN_WRITE_PHRASE = "[PROJECT TEAR DOWN]"
|
|
19
19
|
PRODUCTION_DATA_DELETE_PHRASE = "[PRODUCTION DATA DELETE]"
|
|
20
20
|
RESERVED_SCOPES = ("local", "all")
|
|
21
21
|
|
|
@@ -167,13 +167,13 @@ def _tear_down_remote_environment(
|
|
|
167
167
|
stderr = completed.stderr.decode("utf-8", errors="replace").strip()
|
|
168
168
|
if completed.returncode != 0:
|
|
169
169
|
raise DeploymentKitError(
|
|
170
|
-
"Remote
|
|
170
|
+
"Remote Project tear-down failed: " + (stderr or stdout or f"exit {completed.returncode}")
|
|
171
171
|
)
|
|
172
172
|
parts = stdout.split("\t")
|
|
173
173
|
if len(parts) not in {4, 5} or parts[0] != "TEAR_DOWN" or parts[1] not in {"absent", "removed"}:
|
|
174
|
-
raise DeploymentKitError("Remote
|
|
174
|
+
raise DeploymentKitError("Remote Project tear-down returned malformed evidence.")
|
|
175
175
|
if parts[2] != app_slug or parts[3] != environment:
|
|
176
|
-
raise DeploymentKitError("Remote
|
|
176
|
+
raise DeploymentKitError("Remote Project tear-down returned mismatched app/environment evidence.")
|
|
177
177
|
result: dict[str, Any] = {"state": parts[1], "mutated": parts[1] == "removed"}
|
|
178
178
|
if len(parts) == 5:
|
|
179
179
|
result["containerName"] = parts[4]
|
|
@@ -219,7 +219,7 @@ def tear_down_workstation_package(package: str) -> dict[str, Any]:
|
|
|
219
219
|
removed = _run_local([docker, "rm", "-f", "-v", *containers])
|
|
220
220
|
if removed.returncode != 0:
|
|
221
221
|
raise DeploymentKitError(
|
|
222
|
-
"Local
|
|
222
|
+
"Local Project container removal failed: " + (removed.stderr or removed.stdout).strip()
|
|
223
223
|
)
|
|
224
224
|
|
|
225
225
|
images_result = _run_local([docker, "images", "--format", "{{.Repository}}:{{.Tag}}"])
|
|
@@ -238,7 +238,7 @@ def tear_down_workstation_package(package: str) -> dict[str, Any]:
|
|
|
238
238
|
removed = _run_local([docker, "image", "rm", "-f", *image_refs])
|
|
239
239
|
if removed.returncode != 0:
|
|
240
240
|
raise DeploymentKitError(
|
|
241
|
-
"Local
|
|
241
|
+
"Local Project image removal failed: " + (removed.stderr or removed.stdout).strip()
|
|
242
242
|
)
|
|
243
243
|
return {
|
|
244
244
|
"state": "removed" if containers or image_refs else "absent",
|
|
@@ -248,7 +248,7 @@ def tear_down_workstation_package(package: str) -> dict[str, Any]:
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
|
|
251
|
-
def
|
|
251
|
+
def tear_down_project(spec: dict[str, Any]) -> dict[str, Any]:
|
|
252
252
|
normalized = normalize_teardown_spec(
|
|
253
253
|
owner_repo=spec.get("ownerRepo"),
|
|
254
254
|
app_slug=spec.get("appSlug"),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""CLI for scoped destructive
|
|
1
|
+
"""CLI for scoped destructive Project tear-down."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ from .teardown import (
|
|
|
12
12
|
normalize_teardown_spec,
|
|
13
13
|
parse_environment_targets,
|
|
14
14
|
render_teardown_summary,
|
|
15
|
-
|
|
15
|
+
tear_down_project,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
@@ -83,7 +83,7 @@ def _preview(spec: dict[str, object]) -> dict[str, object]:
|
|
|
83
83
|
"deletesPersistentData": bool(spec["environmentTargets"]),
|
|
84
84
|
"deletesProductionData": production,
|
|
85
85
|
"preservesSharedPlatform": True,
|
|
86
|
-
"
|
|
86
|
+
"preservesUnrelatedProjects": True,
|
|
87
87
|
"deletesGhcrPackage": False,
|
|
88
88
|
"requiredAuthorization": TEAR_DOWN_WRITE_PHRASE,
|
|
89
89
|
"requiredProductionDataAuthorization": PRODUCTION_DATA_DELETE_PHRASE if production else None,
|
|
@@ -111,7 +111,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
111
111
|
and args.production_data_authorization != PRODUCTION_DATA_DELETE_PHRASE
|
|
112
112
|
)
|
|
113
113
|
if missing_general or missing_production:
|
|
114
|
-
print("
|
|
114
|
+
print("PROJECT TEAR-DOWN PREVIEW")
|
|
115
115
|
print(render_teardown_summary(preview))
|
|
116
116
|
if missing_general:
|
|
117
117
|
print(
|
|
@@ -126,8 +126,8 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
126
126
|
)
|
|
127
127
|
return 2
|
|
128
128
|
|
|
129
|
-
result =
|
|
130
|
-
print("
|
|
129
|
+
result = tear_down_project(spec)
|
|
130
|
+
print("PROJECT TEAR-DOWN COMPLETE")
|
|
131
131
|
print(render_teardown_summary(result))
|
|
132
132
|
return 0
|
|
133
133
|
except DeploymentKitError as exc:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Remote destructive tear-down for one Kit-managed
|
|
1
|
+
"""Remote destructive tear-down for one Kit-managed Project environment."""
|
|
2
2
|
|
|
3
3
|
REMOTE_SCRIPT = r'''#!/usr/bin/env bash
|
|
4
4
|
set -Eeuo pipefail
|
|
@@ -37,7 +37,7 @@ if [[ ! -e "$ROOT" ]]; then
|
|
|
37
37
|
fi
|
|
38
38
|
|
|
39
39
|
[[ -d "$ROOT" && ! -L "$ROOT" ]] || {
|
|
40
|
-
echo "
|
|
40
|
+
echo "Project environment root is not a safe managed directory: $ROOT" >&2
|
|
41
41
|
exit 21
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -46,16 +46,16 @@ HAS_PERSISTENCE=false
|
|
|
46
46
|
[[ -f "$STATE" && ! -L "$STATE" ]] && HAS_STATE=true
|
|
47
47
|
[[ -f "$PERSISTENCE" && ! -L "$PERSISTENCE" ]] && HAS_PERSISTENCE=true
|
|
48
48
|
[[ "$HAS_STATE" == true || "$HAS_PERSISTENCE" == true ]] || {
|
|
49
|
-
echo "
|
|
49
|
+
echo "Project environment root has no managed ownership marker: $ROOT" >&2
|
|
50
50
|
exit 21
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
if [[ "$HAS_STATE" == true ]] && ! assert_owned_marker "$STATE"; then
|
|
54
|
-
echo "
|
|
54
|
+
echo "Project deployment ownership mismatch for $ROOT" >&2
|
|
55
55
|
exit 22
|
|
56
56
|
fi
|
|
57
57
|
if [[ "$HAS_PERSISTENCE" == true ]] && ! assert_owned_marker "$PERSISTENCE"; then
|
|
58
|
-
echo "
|
|
58
|
+
echo "Project persistence ownership mismatch for $ROOT" >&2
|
|
59
59
|
exit 22
|
|
60
60
|
fi
|
|
61
61
|
|
|
@@ -87,7 +87,7 @@ if [[ "$HAS_STATE" == true ]]; then
|
|
|
87
87
|
fi
|
|
88
88
|
fi
|
|
89
89
|
|
|
90
|
-
# The verified environment root is owned by this
|
|
90
|
+
# The verified environment root is owned by this Project/environment. Tear-down
|
|
91
91
|
# removes releases, evidence, persistent data, and backups together.
|
|
92
92
|
rm -rf --one-file-system -- "$ROOT"
|
|
93
93
|
|
package/package.json
CHANGED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Coach
|
|
3
|
-
description: Optional guided engineering-learning agent using actual repository context for concepts, code walkthroughs, debugging, coding/SQL/system-design drills, interviews, diagrams, and resources.
|
|
4
|
-
user-invocable: true
|
|
5
|
-
disable-model-invocation: true
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Coach
|
|
9
|
-
|
|
10
|
-
You are the optional engineering-learning perspective.
|
|
11
|
-
|
|
12
|
-
Coaching is never required to start, continue, review, accept, deliver, merge, or complete engineering work.
|
|
13
|
-
|
|
14
|
-
## Core behavior
|
|
15
|
-
|
|
16
|
-
- Do not edit production code or implement fixes for the developer.
|
|
17
|
-
- Do not invoke subagents.
|
|
18
|
-
- Do not silently broaden product scope.
|
|
19
|
-
- Do not pin/request/switch to a premium model automatically.
|
|
20
|
-
- Read minimum relevant context.
|
|
21
|
-
- Use actual repository code, requirements, tests, diffs, incidents, and decisions when useful.
|
|
22
|
-
- Ask one material question at a time.
|
|
23
|
-
- Continue automatically until stop/natural completion.
|
|
24
|
-
- Adapt difficulty to demonstrated understanding.
|
|
25
|
-
- Challenge shallow explanations.
|
|
26
|
-
- Distinguish actual implementation/understanding from AI-generated work or study.
|
|
27
|
-
|
|
28
|
-
## Depth and levels
|
|
29
|
-
|
|
30
|
-
Depth: Light, Focused, Deep, Broad, or Coach recommends.
|
|
31
|
-
|
|
32
|
-
Levels:
|
|
33
|
-
|
|
34
|
-
```text
|
|
35
|
-
L1 Recognize
|
|
36
|
-
L2 Explain
|
|
37
|
-
L3 Trace
|
|
38
|
-
L4 Apply / Debug
|
|
39
|
-
L5 Defend / Design
|
|
40
|
-
L6 Interview Ready
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Do not inflate mastery.
|
|
44
|
-
|
|
45
|
-
## Modes
|
|
46
|
-
|
|
47
|
-
Support concept learning, real-code walkthroughs, debugging, coding/DSA, SQL/database, design defense, system design, interview drills, gap assessment, learning paths, diagrams, and optional external resources.
|
|
48
|
-
|
|
49
|
-
For a structured walkthrough of a changed implementation across a Git/PR/commit change set, route to `/code-walkthrough` when available. Use Coach directly for ad-hoc code explanation or deeper concept exploration.
|
|
50
|
-
|
|
51
|
-
Use installed learning assets when present; otherwise coach directly from the repository/context.
|
|
52
|
-
|
|
53
|
-
## Adaptive questioning
|
|
54
|
-
|
|
55
|
-
Weak answer → teach/simplify/own-words explanation.
|
|
56
|
-
|
|
57
|
-
Solid answer → application/edge case.
|
|
58
|
-
|
|
59
|
-
Strong answer → tradeoff/debug/design.
|
|
60
|
-
|
|
61
|
-
Very strong answer → scale/change assumptions/interviewer pressure.
|
|
62
|
-
|
|
63
|
-
## Resources and progress
|
|
64
|
-
|
|
65
|
-
Prefer official documentation and a small number of current high-quality tutorials/resources. External material is optional.
|
|
66
|
-
|
|
67
|
-
Only update an optional learning-progress tracker with explicit human choice.
|
|
68
|
-
|
|
69
|
-
Never turn study or personal-project understanding into false claims of professional experience.
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: core-sync
|
|
3
|
-
description: Direct Core-to-consumer synchronization for component-only consumers; package-managed consumers are routed to /project-forge-update so umbrella and component baselines remain coherent.
|
|
4
|
-
argument-hint: "[optional local Core path]"
|
|
5
|
-
user-invocable: true
|
|
6
|
-
disable-model-invocation: true
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Core Sync
|
|
10
|
-
|
|
11
|
-
`/core-sync` is the direct component synchronization path for consumers that are managed directly by `CORE_BASELINE.json` **without** an umbrella `PROJECT_FORGE_BASELINE.json`.
|
|
12
|
-
|
|
13
|
-
For package-managed consumers, `/project-forge-update` is authoritative.
|
|
14
|
-
|
|
15
|
-
Invocation starts read-only. Direct component synchronization must never make a package-managed consumer disagree with its recorded Project Forge package provenance.
|
|
16
|
-
|
|
17
|
-
## 1. Classify the consumer before doing anything else
|
|
18
|
-
|
|
19
|
-
From the consumer repository read, when present:
|
|
20
|
-
|
|
21
|
-
- `PROJECT_FORGE_BASELINE.json`;
|
|
22
|
-
- `CORE_BASELINE.json`;
|
|
23
|
-
- `.github/project-forge-workspace.json`;
|
|
24
|
-
- `.github/project-forge-core-sync.json`;
|
|
25
|
-
- current Git status, branch, remotes, and default branch when observable.
|
|
26
|
-
|
|
27
|
-
### Package-managed consumer
|
|
28
|
-
|
|
29
|
-
If `PROJECT_FORGE_BASELINE.json` exists:
|
|
30
|
-
|
|
31
|
-
```text
|
|
32
|
-
PACKAGE-MANAGED PROJECT FORGE CONSUMER
|
|
33
|
-
Direct Core sync: NOT PERMITTED
|
|
34
|
-
Next: /project-forge-update
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Stop before refreshing a Core checkout, running `tools/package/sync.py`, creating a sync branch, or sending a remote `[sync-core]` request.
|
|
38
|
-
|
|
39
|
-
The umbrella package updates Core and Deployment components together and refreshes `PROJECT_FORGE_BASELINE.json`, `CORE_BASELINE.json`, and `DEPLOYMENT_BASELINE.json` coherently. A Core-only sync would bypass that contract.
|
|
40
|
-
|
|
41
|
-
### Component-only Core consumer
|
|
42
|
-
|
|
43
|
-
If `PROJECT_FORGE_BASELINE.json` is absent and a valid `CORE_BASELINE.json` exists, continue with the component-managed path below.
|
|
44
|
-
|
|
45
|
-
If neither baseline exists, report `CORE SYNC BLOCKED`; do not invent provenance or initialize a consumer implicitly.
|
|
46
|
-
|
|
47
|
-
## 2. Establish the component-only Core baseline
|
|
48
|
-
|
|
49
|
-
Run the repository-local integrity check before planning an update:
|
|
50
|
-
|
|
51
|
-
```text
|
|
52
|
-
python tools/project-forge-core/check-core-baseline.py --root .
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Stop if the managed overlay has unexplained local drift, missing managed files, or invalid baseline metadata.
|
|
56
|
-
|
|
57
|
-
Resolve from `CORE_BASELINE.json`:
|
|
58
|
-
|
|
59
|
-
- canonical Core repository;
|
|
60
|
-
- currently accepted Core commit/version;
|
|
61
|
-
- distribution name;
|
|
62
|
-
- managed-path ownership/hashes.
|
|
63
|
-
|
|
64
|
-
## 3. Resolve the Core source safely
|
|
65
|
-
|
|
66
|
-
Check local candidates in this order:
|
|
67
|
-
|
|
68
|
-
1. an explicit Core path supplied by the human;
|
|
69
|
-
2. an already-open workspace folder that unambiguously resolves to the recorded Core repository;
|
|
70
|
-
3. the sibling checkout derived from the Core repository name, normally `../project-forge-core`.
|
|
71
|
-
|
|
72
|
-
Do not broadly scan the filesystem. A local Core checkout is an optimization, not a prerequisite.
|
|
73
|
-
|
|
74
|
-
A local candidate is usable only when it is the recorded Git repository and its state can be inspected safely.
|
|
75
|
-
|
|
76
|
-
If no usable local Core checkout exists, use the configured remote provider from `.github/project-forge-core-sync.json` when available. Do not ask the developer to clone Core merely to satisfy `/core-sync`.
|
|
77
|
-
|
|
78
|
-
## 4. Classify a local Core checkout
|
|
79
|
-
|
|
80
|
-
Before modifying a local Core checkout inspect:
|
|
81
|
-
|
|
82
|
-
```text
|
|
83
|
-
git -C <core-path> status --short --branch
|
|
84
|
-
git -C <core-path> branch --show-current
|
|
85
|
-
git -C <core-path> remote -v
|
|
86
|
-
git -C <core-path> branch -vv
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
It may be refreshed automatically only when clean, on its normal accepted/default branch, backed by an unambiguous upstream, and fast-forward-safe.
|
|
90
|
-
|
|
91
|
-
Never auto-stash, merge, rebase, reset, clean, force-update, or discard Core work.
|
|
92
|
-
|
|
93
|
-
If the checkout is dirty, ahead, diverged, intentionally pinned, or ambiguous, preserve it unchanged and prefer the configured remote provider when available.
|
|
94
|
-
|
|
95
|
-
## 5. Present one bounded component-sync choice
|
|
96
|
-
|
|
97
|
-
Use the host-native **single-select structured choice UI** when available because exactly one next action is authorized. In VS Code use the native question surface such as `vscode_askQuestions`. Preserve the consequence labels and show the recommended choice. Use a numbered text list only when structured choice UI is unavailable.
|
|
98
|
-
|
|
99
|
-
For a safe local source, show the evidence:
|
|
100
|
-
|
|
101
|
-
```text
|
|
102
|
-
CORE SYNC READY
|
|
103
|
-
|
|
104
|
-
Consumer baseline: <commit/version>
|
|
105
|
-
Source: LOCAL <core-path>
|
|
106
|
-
Distribution: <distribution>
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Then offer:
|
|
110
|
-
|
|
111
|
-
- `Sync the component-only Core baseline` `[GIT + FILE WRITE]` — `RECOMMENDED`
|
|
112
|
-
- `Keep inspecting only` `[READ ONLY]`
|
|
113
|
-
- `Stop` `[NO ACTION]`
|
|
114
|
-
|
|
115
|
-
For a configured remote source, show:
|
|
116
|
-
|
|
117
|
-
```text
|
|
118
|
-
CORE SYNC READY
|
|
119
|
-
|
|
120
|
-
Consumer baseline: <commit/version>
|
|
121
|
-
Source: REMOTE PROVIDER
|
|
122
|
-
Provider: <provider repository>
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Then offer:
|
|
126
|
-
|
|
127
|
-
- `Request remote Core sync` `[REMOTE WRITE]` — `RECOMMENDED`
|
|
128
|
-
- `Keep inspecting only` `[READ ONLY]`
|
|
129
|
-
- `Stop` `[NO ACTION]`
|
|
130
|
-
|
|
131
|
-
The selected choice does not authorize merge, release publication, or deployment.
|
|
132
|
-
|
|
133
|
-
## 6. Local component path
|
|
134
|
-
|
|
135
|
-
After `Sync the component-only Core baseline` is selected:
|
|
136
|
-
|
|
137
|
-
1. Refresh Core remote state.
|
|
138
|
-
2. Reclassify the accepted/default Core branch.
|
|
139
|
-
3. Fast-forward it only when safe.
|
|
140
|
-
4. Run canonical Core sync preview using the distribution recorded by the baseline.
|
|
141
|
-
5. Stop on `LOCAL_DRIFT`, `CONFLICT`, `LOCAL_MISSING`, `UNTRACKED_CONFLICT`, or an unaccepted `RETIRED_PATH`.
|
|
142
|
-
6. If the consumer is on its default branch, create/switch to a short-lived branch such as `chore/sync-core-<version-or-short-sha>`.
|
|
143
|
-
7. Apply only safe Core additions/updates and refresh `CORE_BASELINE.json` using canonical `tools/package/sync.py`.
|
|
144
|
-
|
|
145
|
-
Do not manually copy managed files as a substitute for the canonical tool.
|
|
146
|
-
|
|
147
|
-
## 7. Remote component path
|
|
148
|
-
|
|
149
|
-
Remote orchestration is consumer configuration. Read `.github/project-forge-core-sync.json` and require its configured provider contract, for example `github-issue-control-plane` with an owner/repository title template and an empty body.
|
|
150
|
-
|
|
151
|
-
Create exactly the configured request. Do not put product requirements, baseline JSON, source code, secrets, or other private consumer details into a public request.
|
|
152
|
-
|
|
153
|
-
The provider is expected to validate target authorization, obtain its own short-lived credentials, run canonical Core sync, refuse unsafe drift/conflicts, publish a short-lived consumer branch/PR, and observe consumer CI.
|
|
154
|
-
|
|
155
|
-
If the provider cannot satisfy that contract, report `REMOTE SYNC UNAVAILABLE`; do not silently clone Core or invent another synchronization mechanism.
|
|
156
|
-
|
|
157
|
-
## 8. Verification
|
|
158
|
-
|
|
159
|
-
For a local apply run:
|
|
160
|
-
|
|
161
|
-
```text
|
|
162
|
-
python tools/project-forge-core/check-core-baseline.py --root .
|
|
163
|
-
git status --short --branch
|
|
164
|
-
git diff --stat
|
|
165
|
-
git diff -- CORE_BASELINE.json
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Confirm exact Core provenance, managed hashes, consumer-owned preservation, and intended branch scope. Present the meaningful diff and recommend `/deliver` after human acceptance.
|
|
169
|
-
|
|
170
|
-
For a remote path, report the resulting PR and exact Core commit when observed. Merge remains the normal explicit final gate.
|
|
171
|
-
|
|
172
|
-
## 9. Boundaries
|
|
173
|
-
|
|
174
|
-
`/core-sync` never:
|
|
175
|
-
|
|
176
|
-
- directly synchronizes Core when `PROJECT_FORGE_BASELINE.json` exists;
|
|
177
|
-
- uses direct Core sync as a substitute for `/project-forge-update`;
|
|
178
|
-
- modifies ambiguous local Core state;
|
|
179
|
-
- treats managed consumer drift as disposable;
|
|
180
|
-
- publishes Core or Project Forge package releases/tags;
|
|
181
|
-
- merges the consumer sync PR;
|
|
182
|
-
- deploys production.
|
|
183
|
-
|
|
184
|
-
If reusable Core behavior itself is wrong, fix Core canonically through `/upstream-fix`; then adopt it through the update channel appropriate to the consumer's provenance model.
|