@jmfederico/pi-web 1.202608.0 → 1.202608.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cli.js +287 -113
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/CodeViewer-BMWwxG7q.js +4 -0
- package/dist/client/assets/{TerminalPanel-fYrKc3jh.js → TerminalPanel-CacQDIYn.js} +6 -6
- package/dist/client/assets/index-DUW2xnoV.js +4279 -0
- package/dist/client/assets/vendor-editor-core-CXO8gGab.js +12 -0
- package/dist/client/assets/vendor-editor-languages-CpW4sJsX.js +46 -0
- package/dist/client/index.html +3 -3
- package/dist/config.js +110 -73
- package/dist/config.js.map +1 -1
- package/dist/docker/piWebDockerCommandPlan.js +4 -3
- package/dist/docker/piWebDockerCommandPlan.js.map +1 -1
- package/dist/environment.js +4 -0
- package/dist/environment.js.map +1 -0
- package/dist/nativeServices/installedServiceDefinitions.js +602 -0
- package/dist/nativeServices/installedServiceDefinitions.js.map +1 -0
- package/dist/nativeServices/serviceAction.js +174 -0
- package/dist/nativeServices/serviceAction.js.map +1 -0
- package/dist/nativeServices/serviceDoctor.js +374 -71
- package/dist/nativeServices/serviceDoctor.js.map +1 -1
- package/dist/nativeServices/servicePlan.js +1 -1
- package/dist/nativeServices/servicePlan.js.map +1 -1
- package/dist/{pi-web-plugins → pi-packages}/relays/markdownDocument.js +1 -1
- package/dist/pi-packages/relays/package.json +11 -0
- package/dist/{pi-web-plugins → pi-packages}/relays/pi-web-plugin.js +4 -4
- package/dist/pi-packages/relays/prompts/relay-worktree.md +157 -0
- package/dist/pi-packages/relays/prompts/relay.md +152 -0
- package/dist/{pi-web-plugins → pi-packages}/relays/relayDiscovery.js +1 -1
- package/dist/{pi-web-plugins → pi-packages}/relays/relaysPanelElement.js +1 -1
- package/dist/pi-packages/relays/skills/relay/SKILL.md +123 -0
- package/dist/pi-web-plugins/git/browser/git-contract.js +108 -0
- package/dist/pi-web-plugins/git/browser/git-panel.js +609 -0
- package/dist/pi-web-plugins/git/browser/gitFileList.js +43 -0
- package/dist/pi-web-plugins/git/browser/gitFileShared.js +16 -0
- package/dist/pi-web-plugins/git/browser/gitFileTree.js +81 -0
- package/dist/pi-web-plugins/git/browser/gitFileViewPreference.js +35 -0
- package/dist/pi-web-plugins/git/browser/gitRoute.js +42 -0
- package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +10 -0
- package/dist/pi-web-plugins/git/browser/unifiedDiff.js +301 -0
- package/dist/{server/git/gitService.js → pi-web-plugins/git/git-backend.js} +209 -60
- package/dist/pi-web-plugins/git/package.json +16 -0
- package/dist/pi-web-plugins/git/server-plugin.js +176 -0
- package/dist/pi-web-plugins/info/infoInternals.js +16 -2
- package/dist/pi-web-plugins/info/package.json +1 -1
- package/dist/pi-web-plugins/info/pi-web-plugin.js +2 -2
- package/dist/pi-web-plugins/updates/package.json +1 -1
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +1 -1
- package/dist/pi-web-plugins/workspace-tasks/package.json +1 -1
- package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +3 -3
- package/dist/piWebVersionReport.js +63 -10
- package/dist/piWebVersionReport.js.map +1 -1
- package/dist/plugin-api.d.ts +33 -16
- package/dist/pluginRecoveryCli.js +172 -0
- package/dist/pluginRecoveryCli.js.map +1 -0
- package/dist/server/activity/workspaceActivityService.js +27 -19
- package/dist/server/activity/workspaceActivityService.js.map +1 -1
- package/dist/server/app.js +41 -15
- package/dist/server/app.js.map +1 -1
- package/dist/server/configRoutes.js +3 -21
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/knownAutoInstallPiPackages.js +30 -0
- package/dist/server/knownAutoInstallPiPackages.js.map +1 -0
- package/dist/server/machines/machineClient.js +23 -4
- package/dist/server/machines/machineClient.js.map +1 -1
- package/dist/server/machines/machinePluginProxyRoutes.js +74 -17
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineProxyRoutes.js +165 -8
- package/dist/server/machines/machineProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineService.js +23 -0
- package/dist/server/machines/machineService.js.map +1 -1
- package/dist/server/piPackageIdentity.js +25 -0
- package/dist/server/piPackageIdentity.js.map +1 -0
- package/dist/server/piPackageService.js +69 -8
- package/dist/server/piPackageService.js.map +1 -1
- package/dist/server/piWebPluginCatalog.js +584 -0
- package/dist/server/piWebPluginCatalog.js.map +1 -0
- package/dist/server/piWebPluginLifecycle.js +162 -0
- package/dist/server/piWebPluginLifecycle.js.map +1 -0
- package/dist/server/piWebPluginService.js +159 -261
- package/dist/server/piWebPluginService.js.map +1 -1
- package/dist/server/piWebStatus.js +41 -9
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/plugins/pluginBackendProxyRoutes.js +69 -0
- package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -0
- package/dist/server/plugins/serverPluginExec.js +184 -0
- package/dist/server/plugins/serverPluginExec.js.map +1 -0
- package/dist/server/plugins/serverPluginRuntime.js +480 -0
- package/dist/server/plugins/serverPluginRuntime.js.map +1 -0
- package/dist/server/projectTrustRoutes.js +80 -0
- package/dist/server/projectTrustRoutes.js.map +1 -0
- package/dist/server/projects/projectService.js +3 -1
- package/dist/server/projects/projectService.js.map +1 -1
- package/dist/server/realtime/sessionEventHub.js +26 -11
- package/dist/server/realtime/sessionEventHub.js.map +1 -1
- package/dist/server/requestCancellation.js +32 -0
- package/dist/server/requestCancellation.js.map +1 -0
- package/dist/server/sessiond/agentProcessEnvironment.js +29 -30
- package/dist/server/sessiond/agentProcessEnvironment.js.map +1 -1
- package/dist/server/sessiond/autoInstallPiPackages.js +63 -0
- package/dist/server/sessiond/autoInstallPiPackages.js.map +1 -0
- package/dist/server/sessiond/pluginBackendRoutes.js +64 -0
- package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -0
- package/dist/server/sessiond/sessionDaemonShutdown.js +24 -0
- package/dist/server/sessiond/sessionDaemonShutdown.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +2 -2
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond/sessionServiceDependencies.js +2 -1
- package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
- package/dist/server/sessiond/sessiondStateOwnership.js +235 -0
- package/dist/server/sessiond/sessiondStateOwnership.js.map +1 -0
- package/dist/server/sessiond/workspaceCatalogRoutes.js +31 -0
- package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -0
- package/dist/server/sessiond/workspaceRemovalRoutes.js +41 -0
- package/dist/server/sessiond/workspaceRemovalRoutes.js.map +1 -0
- package/dist/server/sessiond.js +284 -98
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/authService.js +15 -54
- package/dist/server/sessions/authService.js.map +1 -1
- package/dist/server/sessions/dockerEnvironmentFacts.js +254 -0
- package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -0
- package/dist/server/sessions/modelCatalogRefresher.js +4 -3
- package/dist/server/sessions/modelCatalogRefresher.js.map +1 -1
- package/dist/server/sessions/piSessionManagerGateway.js +18 -67
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +495 -142
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +24 -1
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionEnvironmentFacts.js +48 -0
- package/dist/server/sessions/sessionEnvironmentFacts.js.map +1 -0
- package/dist/server/sessions/sessionFileFormat.js +27 -0
- package/dist/server/sessions/sessionFileFormat.js.map +1 -0
- package/dist/server/sessions/sessionFileHeader.js +1 -14
- package/dist/server/sessions/sessionFileHeader.js.map +1 -1
- package/dist/server/sessions/sessionModelScope.js +160 -0
- package/dist/server/sessions/sessionModelScope.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +6 -6
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +55 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/sessionSummaryScanner.js +96 -224
- package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +5 -9
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/server/sessions/spawnTargetResolver.js +1 -1
- package/dist/server/status/machineStatusRoutes.js +8 -0
- package/dist/server/status/machineStatusRoutes.js.map +1 -0
- package/dist/server/status/machineStatusService.js +181 -0
- package/dist/server/status/machineStatusService.js.map +1 -0
- package/dist/server/status/workspaceAttribution.js +87 -0
- package/dist/server/status/workspaceAttribution.js.map +1 -0
- package/dist/server/storage/piPackageDismissalStore.js +78 -0
- package/dist/server/storage/piPackageDismissalStore.js.map +1 -0
- package/dist/server/terminalProxyRoutes.js +2 -1
- package/dist/server/terminalProxyRoutes.js.map +1 -1
- package/dist/server/workspaceExplorerRoutes.js +20 -13
- package/dist/server/workspaceExplorerRoutes.js.map +1 -1
- package/dist/server/workspaces/fileContentService.js +18 -9
- package/dist/server/workspaces/fileContentService.js.map +1 -1
- package/dist/server/workspaces/filePreviewResponseHeaders.js +18 -0
- package/dist/server/workspaces/filePreviewResponseHeaders.js.map +1 -0
- package/dist/server/workspaces/filePreviewResponsePolicy.js +55 -0
- package/dist/server/workspaces/filePreviewResponsePolicy.js.map +1 -0
- package/dist/server/workspaces/filePreviewService.js +81 -0
- package/dist/server/workspaces/filePreviewService.js.map +1 -0
- package/dist/server/workspaces/projectWorkspaceCwds.js +0 -5
- package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -1
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +402 -0
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -0
- package/dist/server/workspaces/workspaceCatalog.js +47 -0
- package/dist/server/workspaces/workspaceCatalog.js.map +1 -0
- package/dist/server/workspaces/workspaceContext.js +1 -3
- package/dist/server/workspaces/workspaceContext.js.map +1 -1
- package/dist/server/workspaces/workspaceDeletionRoutes.js +35 -125
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
- package/dist/server/workspaces/workspaceProviderRegistry.js +651 -0
- package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -0
- package/dist/server/workspaces/workspaceRemovalService.js +256 -0
- package/dist/server/workspaces/workspaceRemovalService.js.map +1 -0
- package/dist/server/workspaces/workspaceRouteErrors.js +7 -0
- package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -0
- package/dist/server/workspaces/worktreePreRemoveHook.js +39 -0
- package/dist/server/workspaces/worktreePreRemoveHook.js.map +1 -0
- package/dist/server-plugin-api.d.ts +140 -0
- package/dist/server-plugin-api.js +2 -0
- package/dist/server-plugin-api.js.map +1 -0
- package/dist/serverPluginRecovery.js +138 -0
- package/dist/serverPluginRecovery.js.map +1 -0
- package/dist/sessiond/activeAgentProfile.js +3 -22
- package/dist/sessiond/activeAgentProfile.js.map +1 -1
- package/dist/sessiond/config.js +11 -0
- package/dist/sessiond/config.js.map +1 -1
- package/dist/sessiond/sessionDaemonClient.js +11 -9
- package/dist/sessiond/sessionDaemonClient.js.map +1 -1
- package/dist/shared/activeAgentProfile.js +2 -41
- package/dist/shared/activeAgentProfile.js.map +1 -1
- package/dist/shared/activity.js +0 -3
- package/dist/shared/activity.js.map +1 -1
- package/dist/shared/apiTypes.js +7 -5
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +8 -6
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +36 -5
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/machinePluginIds.js +4 -2
- package/dist/shared/machinePluginIds.js.map +1 -1
- package/dist/shared/machineStatus.js +94 -0
- package/dist/shared/machineStatus.js.map +1 -0
- package/dist/shared/piWebStatusParsing.js +33 -0
- package/dist/shared/piWebStatusParsing.js.map +1 -1
- package/dist/shared/pluginApiTypes.d.ts +150 -0
- package/dist/shared/pluginApiTypes.js +3 -0
- package/dist/shared/pluginApiTypes.js.map +1 -0
- package/dist/shared/pluginBackendProtocol.js +110 -0
- package/dist/shared/pluginBackendProtocol.js.map +1 -0
- package/dist/shared/pluginIds.js +5 -0
- package/dist/shared/pluginIds.js.map +1 -1
- package/dist/shared/pluginRecoveryCommands.js +14 -0
- package/dist/shared/pluginRecoveryCommands.js.map +1 -0
- package/dist/shared/workspaceFiles.js +41 -2
- package/dist/shared/workspaceFiles.js.map +1 -1
- package/dist/shared/workspaceRemovalProtocol.js +24 -0
- package/dist/shared/workspaceRemovalProtocol.js.map +1 -0
- package/docs/config.md +105 -52
- package/docs/plugins.md +403 -146
- package/examples/workspace-provider-plugin/README.md +52 -0
- package/examples/workspace-provider-plugin/package.json +25 -0
- package/examples/workspace-provider-plugin/src/browser/index.ts +69 -0
- package/examples/workspace-provider-plugin/src/server.ts +64 -0
- package/examples/workspace-provider-plugin/tsconfig.json +21 -0
- package/package.json +30 -11
- package/server-plugin-api.d.ts +1 -0
- package/dist/client/assets/CodeViewer-D91Sp61M.js +0 -4
- package/dist/client/assets/UnifiedDiffViewer-BafLWGtF.js +0 -39
- package/dist/client/assets/index-CA8q9_o7.js +0 -4025
- package/dist/client/assets/vendor-editor-core-vUi74DnD.js +0 -12
- package/dist/client/assets/vendor-editor-languages-DoaXUodB.js +0 -46
- package/dist/pi-web-plugins/relays/package.json +0 -9
- package/dist/plugin-api/unstable.d.ts +0 -22
- package/dist/server/activity/workspaceActivityRoutes.js +0 -4
- package/dist/server/activity/workspaceActivityRoutes.js.map +0 -1
- package/dist/server/git/gitService.js.map +0 -1
- package/dist/server/gitRoutes.js +0 -23
- package/dist/server/gitRoutes.js.map +0 -1
- package/dist/server/sessions/parentSessionLocator.js +0 -75
- package/dist/server/sessions/parentSessionLocator.js.map +0 -1
- package/dist/server/workspaces/gitWorktreeDiscovery.js +0 -43
- package/dist/server/workspaces/gitWorktreeDiscovery.js.map +0 -1
- package/dist/server/workspaces/imagePreviewService.js +0 -40
- package/dist/server/workspaces/imagePreviewService.js.map +0 -1
- package/dist/server/workspaces/workspaceService.js +0 -52
- package/dist/server/workspaces/workspaceService.js.map +0 -1
- package/dist/shared/apiTypes.d.ts +0 -1217
- package/dist/shared/thinkingLevels.d.ts +0 -27
- package/plugin-api/unstable.d.ts +0 -1
- /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/README.md +0 -0
- /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/marked.esm.js +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: relay
|
|
3
|
+
description: "How the Relay method works: executing a plan as a chain of independent sessions that each do one slice and hand off to the next via spawn_session. Load this skill only when you already know you are in a relay: a prompt states you are working under the Relay framework (or relay/chain), points you at a relay charter/status/log, or the user invokes this skill directly. Do not load it for generic multi-step plans or ordinary spawn_session use."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Relay
|
|
7
|
+
|
|
8
|
+
Relay is a way to execute a long or complex plan as a chain of independent sessions. Each session runs **one leg** — a single well-sized slice of the work — then hands the work off to a fresh session that runs the next leg. The chain continues until the goal is reached.
|
|
9
|
+
|
|
10
|
+
There is no coordinator and no referee. Each runner is the coordinator for their own leg: smart enough to do the work, adapt to what they discover, and hand off cleanly. Trust is distributed to every agent, not held by a god-agent above them.
|
|
11
|
+
|
|
12
|
+
Relay works because it does not try to recreate human management structures. The point is fewer boundaries, less hierarchy, and more fluid execution. The thing that makes that safe is **context containment**: every leg starts with a fresh, small context, and the accumulated knowledge lives in compact documents on disk rather than in any one session's memory.
|
|
13
|
+
|
|
14
|
+
## The hard constraint that shapes everything
|
|
15
|
+
|
|
16
|
+
`spawn_session` is fire-and-forget. When you spawn the next leg, **you do not see its output and you cannot correct it.** The only thing that travels down the chain is what you wrote to disk. A human may be watching, but they intervene through the Relay's durable state and intervention signal, not by relaying messages between sessions.
|
|
17
|
+
|
|
18
|
+
Two consequences follow, and they govern the whole method:
|
|
19
|
+
|
|
20
|
+
- **Make your work durable before you hand off.** Update the status, append the log, and preserve artifacts in the way the charter defines before spawning the next leg. Anything not on disk is lost.
|
|
21
|
+
- **If you hand off, do it exactly once, at the end.** Do not spawn early, do not spawn several runners "to parallelize," and never spawn while you still have work in flight. One leg, at most one handoff.
|
|
22
|
+
|
|
23
|
+
## The relay packet
|
|
24
|
+
|
|
25
|
+
A relay is carried by a small packet of documents. By default, its root is `.pi-web/relays/<name>/`. A user or dispatching instruction may choose another root. Record the actual root in the charter and use it consistently.
|
|
26
|
+
|
|
27
|
+
Every relay has these three core files.
|
|
28
|
+
|
|
29
|
+
**Authority follows role, not recency.** The charter is authoritative for where the relay is going and the bounds within which it runs; status is authoritative for where it is now and what comes next; the log is history. A later status update does not override the charter. This split lets every runner adapt the route without silently moving the destination.
|
|
30
|
+
|
|
31
|
+
**Charter** (`charter.md`) — the stable agreement, written when the relay is planned. It must contain, at minimum:
|
|
32
|
+
|
|
33
|
+
- **Relay identity.** The relay name and root path, so runners know exactly which relay they are on.
|
|
34
|
+
- **Goal / finish line.** A concrete, achievable end state with enough stable boundaries to decide whether it has been reached. The charter must state the finish line. It may define supporting requirements by reference only when it explicitly designates the referenced artifact as part of the stable agreement; neither `status.md` nor `log.md` may be the sole source of what “done” means. Without a finish line the relay runs forever — this is non-negotiable.
|
|
35
|
+
- **Sizing.** How much is *one leg*? This is project- and plan-specific; the charter defines it (a task, a slice, a time/scope budget — whatever fits). The skill does not decide this for you.
|
|
36
|
+
- **Task selection policy.** How a runner chooses the next task when `status.md` does not name one explicitly.
|
|
37
|
+
- **Handover.** How a runner hands off: what the spawn prompt should say and what the next runner must read. A normal handoff starts with a natural header containing the relay name and next leg identifier, then points at `charter.md` and `status.md`, not the full log.
|
|
38
|
+
- **Intervention signal.** When and how a runner must stop and get the human, and how that is made visible. The charter defines relay-specific triggers and signaling. A runner who would need to change the agreed finish line without explicit human direction must always stop and raise that signal.
|
|
39
|
+
- **Reading discipline.** The files a runner should read to orient, and any files that should not be read defensively.
|
|
40
|
+
|
|
41
|
+
The charter *can* be edited. Clarifications and maintenance are fine, but changing the goal, finish line, or a supporting artifact that the charter designates as part of them changes the relay's agreement; it is not ordinary leg-level adaptation. Runners adapt the route, not the destination. Make such a change only with explicit human agreement, record it in `log.md`, and update the charter before continuing. If you believe the change is needed and do not already have that agreement, stop and raise the intervention signal. Frequent charter edits are still a smell that the design is unsettled.
|
|
42
|
+
|
|
43
|
+
**Status** (`status.md`) — the compact baton/current state. This is the file every runner reads after the charter, and every runner updates before handoff or stop. Keep it short enough that a fresh runner can load it cheaply.
|
|
44
|
+
|
|
45
|
+
The baton carries position, not destination. `status.md` is authoritative for current state and next-leg selection only. It may describe a leg task or point to relevant context, but it must fit the charter's finish line and must not redefine, narrow, or extend it. Information needed to judge whether the relay itself is complete needs a stable home in the charter or a supporting artifact the charter designates; status points there rather than becoming its replacement.
|
|
46
|
+
|
|
47
|
+
It should answer:
|
|
48
|
+
|
|
49
|
+
- **Current position.** Where the relay is now.
|
|
50
|
+
- **Current or next task.** The next leg if known; otherwise enough information to apply the charter's task selection policy.
|
|
51
|
+
- **Leg tracking.** The last completed leg and the next leg to run. Keep this explicit so runners do not have to infer whether “current leg” means the leg just finished or the leg being handed off, and so the handoff prompt can identify the next leg accurately.
|
|
52
|
+
- **Relevant context.** Only the files, sections, commands, artifacts, or specific log entries needed for the next leg.
|
|
53
|
+
- **Progress documentation.** Where and how this runner must make progress durable: update `status.md`, append `log.md`, update artifacts, or follow another workflow named by the charter.
|
|
54
|
+
- **Blockers / intervention state.** Current risks, open decisions, or active reasons to stop.
|
|
55
|
+
|
|
56
|
+
Leg identifiers distinguish handoffs; they do not predict a fixed route or total number of legs.
|
|
57
|
+
|
|
58
|
+
Think of `status.md` as the thing passed from runner to runner. If it grows into a history dump, compress it back into current state plus pointers. If finish-line-defining content has crept into status without a stable home, restore it to the charter or a charter-designated artifact before compressing it away. If an older relay lacks leg tracking, repair it when you update status; prefer the leg identifier from the prompt or status, and do not read `log.md` end-to-end just to reconstruct prior identifiers.
|
|
59
|
+
|
|
60
|
+
**Log** (`log.md`) — append-only history. Each leg appends a concise entry recording what it did, decisions made and why, durable artifacts changed, status updates made, and blockers. The log preserves auditability, including agreed changes to the charter, but it is **not** orientation memory and does not replace the charter as the current agreement.
|
|
61
|
+
|
|
62
|
+
Do not read `log.md` end-to-end by default. Read targeted log entries only when `status.md` points to them, when the charter requires a specific lookup, or when there is an inconsistency you must resolve before continuing.
|
|
63
|
+
|
|
64
|
+
Optional files such as `plan.md`, `backlog.md`, specifications, or artifact notes are fine, but runners should read them only when the charter/status points to the relevant part. If the charter designates one as part of the finish line, changing that part follows the same agreement rule as changing the charter itself.
|
|
65
|
+
|
|
66
|
+
## Context containment rule
|
|
67
|
+
|
|
68
|
+
A runner normally reads:
|
|
69
|
+
|
|
70
|
+
1. `charter.md`
|
|
71
|
+
2. `status.md`
|
|
72
|
+
3. Only the specific files or log entries referenced for the current leg
|
|
73
|
+
|
|
74
|
+
Do not defensively rebuild the relay's full history. Do not read the full log, the full backlog, or a large artifact tree just because they exist. The relay stays scalable because each runner pays only for the context needed now.
|
|
75
|
+
|
|
76
|
+
If `status.md` is insufficient, fix the baton rather than compensating by reading everything. Here, fixing means restoring an accurate account of current state, tasks, and pointers within the charter's bounds; it does not mean reconstructing or revising the finish line in status. Use targeted inspection to clarify the current state, update `status.md` so the next runner has a clean start, and continue only if the task is still clear. If resolving the gap would require broad archaeology or judgment about past intent or what “done” should mean, stop and raise the intervention signal.
|
|
77
|
+
|
|
78
|
+
## Running one leg
|
|
79
|
+
|
|
80
|
+
This is the loop you run when you are dispatched into a relay.
|
|
81
|
+
|
|
82
|
+
1. **Orient from the packet.** Read `charter.md` and `status.md`. Confirm from the charter the relay identity/root, finish line, sizing, task-selection policy, handoff protocol, intervention signal, and reading discipline. Confirm from status the current position, last completed leg, next leg to run, current/next task, and blockers. If you are not sure whether a Relay is active, the dispatch prompt or packet must establish it; loading this skill alone does not.
|
|
83
|
+
2. **Choose the leg.** Prefer the explicit current/next task in `status.md`, provided it serves the charter's finish line and fits its sizing. If none is named, apply the charter's task selection policy. If that still requires context, inspect only the referenced plan/backlog/artifact sections. Do not adopt a task merely because status is newer. If the next task is still ambiguous, falls outside the charter's bounds, or would require moving the finish line, stop and involve the human.
|
|
84
|
+
3. **Re-anchor to the charter.** Does the chosen leg still serve the finish line, and does reality still permit it? Adapting how to get there is your job. If reality indicates that what “done” means should change, stop and raise the intervention signal rather than quietly redefining it.
|
|
85
|
+
4. **Run one leg.** Do exactly one well-sized slice, per the charter's sizing. Resist doing "just a bit more" — extra scope bloats context and breaks the containment that makes Relay work.
|
|
86
|
+
5. **Document progress.** Make all work durable. Update `status.md` with the new current state, last completed leg, next leg to run (if any), next task or task-selection pointer, relevant context for the next runner, and blockers. Append a concise `log.md` entry with what you did, why, decisions made, artifacts changed, and whether you are handing off or stopping.
|
|
87
|
+
6. **Decide: hand off, or stop.**
|
|
88
|
+
- **Hand off** if there is a clear next leg and you are on track. Use `spawn_session` once, with a prompt whose first line is a natural task header containing the relay name and next leg identifier (for example, `Relay "<name>" leg <identifier> begins now.`), followed by the Relay method and pointers to `charter.md` and `status.md` (so this skill loads and they can orient cheaply). Then you are done. Handoff is deliberately fire-and-forget: `spawn_session` starts an independent session you will not see and cannot steer — do not reach for a tracked subsession to keep an eye on it. Letting go is the point. The next runner is trusted to run their own leg, and the relay packet is the only thread between you; if you feel the need to watch downstream work, that usually means the leg wasn't sized or handed off cleanly, or an intervention signal should have fired.
|
|
89
|
+
- **Stop — do not spawn —** if the goal is reached, or you are blocked, or the charter's intervention signal fires. Update `status.md`, append a clear note in `log.md`, and raise the intervention signal so the watching human sees exactly what happened and what they need to decide. A stalled relay that stopped cleanly with a clear blocker is a success; a relay that spawned a confused next runner is a failure.
|
|
90
|
+
|
|
91
|
+
A good handoff prompt is short and explicit. The example below uses the default packet root; substitute the root recorded in the charter when it differs. Put the relay identity and leg identifier at the very beginning so the handoff is immediately distinguishable:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
Relay "<name>" leg <identifier> begins now.
|
|
95
|
+
|
|
96
|
+
You are the next runner in this Relay method chain.
|
|
97
|
+
|
|
98
|
+
Read:
|
|
99
|
+
- .pi-web/relays/<name>/charter.md
|
|
100
|
+
- .pi-web/relays/<name>/status.md
|
|
101
|
+
|
|
102
|
+
Do not read log.md end-to-end. Use it only for targeted lookup if status.md or charter.md points you there.
|
|
103
|
+
|
|
104
|
+
Run one leg according to the charter. Before handing off, update status.md, append log.md, make work durable, then either spawn the next leg once or stop with a clear intervention note.
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Planning a relay
|
|
108
|
+
|
|
109
|
+
When the user asks to set up a relay, your job is to produce the relay packet: `charter.md`, `status.md`, and `log.md`. The charter must have the required slots filled: relay identity, goal, sizing, task selection policy, handover, intervention signal, and reading discipline. Before dispatch, preserve the agreed finish line and the stable boundaries needed to judge it in the charter or in supporting material the charter explicitly designates. Do not make the initial status or planning conversation the only place those requirements exist. The initial status must give the first runner a compact baton: current position, leg tracking (for a numeric scheme, usually last completed leg 0 and next leg to run 1 for a new relay), first task or task selection pointer, relevant context, documentation expectations, and known blockers. The log may start empty or with a short seed entry explaining that the relay was created.
|
|
110
|
+
|
|
111
|
+
Unless the user or dispatching instructions provide these choices or a rule for deriving them, draw them out from the user rather than inventing them: ask what the finish line is, how much should be one leg, how runners pick tasks, how runners hand off, what they should read, and when they must stop and get the human. Sizing, task selection, and the intervention signal especially are not for the generic method to decide — propose options if it helps, but do not quietly settle them yourself.
|
|
112
|
+
|
|
113
|
+
Do **not** invent what a "good" plan, leg size, or cadence looks like when no policy is supplied — those choices are deeply project-, plan-, and human-specific. Explicit user, project, or dispatch instructions may provide defaults; follow them rather than replacing them with the skill's preferences. Your value in planning is making sure the relay is *runnable*: the finish line exists, sizing is stated, task selection is stated, handover is stated, reading discipline is stated, and the intervention signal is stated. Once the packet is agreed, you can dispatch the first leg with `spawn_session`.
|
|
114
|
+
|
|
115
|
+
## Smells to watch for
|
|
116
|
+
|
|
117
|
+
- **No stable finish line** → infinite or self-redefining relay. Refuse to run when “done” exists only in mutable state.
|
|
118
|
+
- **Goal drift / baton authority creep** → a leg or `status.md` quietly restates, narrows, or extends what the relay is for. Re-anchor to the charter; changing the destination requires human agreement.
|
|
119
|
+
- **Charter churn** → stable policy changes every leg. The design isn't settled; involve the human.
|
|
120
|
+
- **Status bloat** → `status.md` turns into a history dump. Compress it to current state plus targeted pointers.
|
|
121
|
+
- **Defensive reading** → reading the full log/backlog/artifact tree to feel safe. Use the packet and targeted lookups; stop if the baton is not enough.
|
|
122
|
+
- **Eager spawning** → spawning early, spawning several runners, or spawning before work is durable. One leg, at most one handoff, at the end.
|
|
123
|
+
- **Silent stall** → getting stuck and stopping with no note, or spawning anyway. Always update status, log the blocker, and surface it.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Generated from pi-web-plugins/git/browser/git-contract.ts. Do not edit directly.
|
|
2
|
+
export const GIT_STATUS_OPERATION = "status";
|
|
3
|
+
export const GIT_DIFF_OPERATION = "diff";
|
|
4
|
+
export function parseGitStatusResponse(value) {
|
|
5
|
+
const record = requireRecord(value, "Git status response");
|
|
6
|
+
const branch = optionalString(record, "branch");
|
|
7
|
+
const upstream = optionalString(record, "upstream");
|
|
8
|
+
const ahead = optionalNumber(record, "ahead");
|
|
9
|
+
const behind = optionalNumber(record, "behind");
|
|
10
|
+
return {
|
|
11
|
+
isGitRepo: requireBoolean(record, "isGitRepo"),
|
|
12
|
+
hash: requireString(record, "hash"),
|
|
13
|
+
...(branch === undefined ? {} : { branch }),
|
|
14
|
+
...(upstream === undefined ? {} : { upstream }),
|
|
15
|
+
...(ahead === undefined ? {} : { ahead }),
|
|
16
|
+
...(behind === undefined ? {} : { behind }),
|
|
17
|
+
files: requireArray(record, "files").map(parseGitStatusFile),
|
|
18
|
+
submodules: record["submodules"] === undefined ? [] : requireStringArray(record["submodules"], "submodules"),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function parseGitDiffResponse(value) {
|
|
22
|
+
const record = requireRecord(value, "Git diff response");
|
|
23
|
+
const path = optionalString(record, "path");
|
|
24
|
+
return {
|
|
25
|
+
...(path === undefined ? {} : { path }),
|
|
26
|
+
staged: requireBoolean(record, "staged"),
|
|
27
|
+
hash: requireString(record, "hash"),
|
|
28
|
+
diff: requireString(record, "diff"),
|
|
29
|
+
truncated: requireBoolean(record, "truncated"),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function parseGitStatusFile(value) {
|
|
33
|
+
const record = requireRecord(value, "Git status file");
|
|
34
|
+
const oldPath = optionalString(record, "oldPath");
|
|
35
|
+
const submoduleFromCommit = optionalString(record, "submoduleFromCommit");
|
|
36
|
+
const submoduleToCommit = optionalString(record, "submoduleToCommit");
|
|
37
|
+
return {
|
|
38
|
+
path: requireString(record, "path"),
|
|
39
|
+
...(oldPath === undefined ? {} : { oldPath }),
|
|
40
|
+
index: parseGitFileState(record["index"]),
|
|
41
|
+
workingTree: parseGitFileState(record["workingTree"]),
|
|
42
|
+
...(submoduleFromCommit === undefined ? {} : { submoduleFromCommit }),
|
|
43
|
+
...(submoduleToCommit === undefined ? {} : { submoduleToCommit }),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function parseGitFileState(value) {
|
|
47
|
+
switch (value) {
|
|
48
|
+
case "unmodified":
|
|
49
|
+
case "modified":
|
|
50
|
+
case "added":
|
|
51
|
+
case "deleted":
|
|
52
|
+
case "renamed":
|
|
53
|
+
case "copied":
|
|
54
|
+
case "untracked":
|
|
55
|
+
case "ignored":
|
|
56
|
+
case "conflicted":
|
|
57
|
+
return value;
|
|
58
|
+
default:
|
|
59
|
+
throw new Error("Invalid Git file state");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function requireRecord(value, label) {
|
|
63
|
+
if (!isRecord(value))
|
|
64
|
+
throw new Error(`${label} must be an object`);
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
function requireArray(record, key) {
|
|
68
|
+
const value = record[key];
|
|
69
|
+
if (!Array.isArray(value))
|
|
70
|
+
throw new Error(`Expected array field: ${key}`);
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
function requireString(record, key) {
|
|
74
|
+
const value = record[key];
|
|
75
|
+
if (typeof value !== "string")
|
|
76
|
+
throw new Error(`Expected string field: ${key}`);
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
function requireBoolean(record, key) {
|
|
80
|
+
const value = record[key];
|
|
81
|
+
if (typeof value !== "boolean")
|
|
82
|
+
throw new Error(`Expected boolean field: ${key}`);
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
function optionalString(record, key) {
|
|
86
|
+
const value = record[key];
|
|
87
|
+
if (value === undefined)
|
|
88
|
+
return undefined;
|
|
89
|
+
if (typeof value !== "string")
|
|
90
|
+
throw new Error(`Expected string field: ${key}`);
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
function optionalNumber(record, key) {
|
|
94
|
+
const value = record[key];
|
|
95
|
+
if (value === undefined)
|
|
96
|
+
return undefined;
|
|
97
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
98
|
+
throw new Error(`Expected number field: ${key}`);
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
function requireStringArray(value, key) {
|
|
102
|
+
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string"))
|
|
103
|
+
throw new Error(`Expected string array field: ${key}`);
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
function isRecord(value) {
|
|
107
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
108
|
+
}
|