taskflow-mcp-core 0.3.0-beta.1.1 → 1.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/CONTROL_GUIDE.md +113 -0
- package/README.md +34 -25
- package/dist/control/admission-service.d.ts +15 -0
- package/dist/control/admission-service.d.ts.map +1 -0
- package/dist/control/admission-service.js +64 -0
- package/dist/control/admission-service.js.map +1 -0
- package/dist/control/approval-edits.d.ts +12 -0
- package/dist/control/approval-edits.d.ts.map +1 -0
- package/dist/control/approval-edits.js +66 -0
- package/dist/control/approval-edits.js.map +1 -0
- package/dist/control/approval-service.d.ts +173 -0
- package/dist/control/approval-service.d.ts.map +1 -0
- package/dist/control/approval-service.js +342 -0
- package/dist/control/approval-service.js.map +1 -0
- package/dist/control/authorization.d.ts +94 -0
- package/dist/control/authorization.d.ts.map +1 -0
- package/dist/control/authorization.js +302 -0
- package/dist/control/authorization.js.map +1 -0
- package/dist/control/control-cli.d.ts +3 -0
- package/dist/control/control-cli.d.ts.map +1 -0
- package/dist/control/control-cli.js +279 -0
- package/dist/control/control-cli.js.map +1 -0
- package/dist/control/control-console.d.ts +17 -0
- package/dist/control/control-console.d.ts.map +1 -0
- package/dist/control/control-console.js +67 -0
- package/dist/control/control-console.js.map +1 -0
- package/dist/control/control-host.d.ts +98 -0
- package/dist/control/control-host.d.ts.map +1 -0
- package/dist/control/control-host.js +459 -0
- package/dist/control/control-host.js.map +1 -0
- package/dist/control/control-mcp.d.ts +11 -0
- package/dist/control/control-mcp.d.ts.map +1 -0
- package/dist/control/control-mcp.js +78 -0
- package/dist/control/control-mcp.js.map +1 -0
- package/dist/control/errors.d.ts +44 -0
- package/dist/control/errors.d.ts.map +1 -0
- package/dist/control/errors.js +93 -0
- package/dist/control/errors.js.map +1 -0
- package/dist/control/hello.d.ts +39 -0
- package/dist/control/hello.d.ts.map +1 -0
- package/dist/control/hello.js +80 -0
- package/dist/control/hello.js.map +1 -0
- package/dist/control/host-runtime.d.ts +32 -0
- package/dist/control/host-runtime.d.ts.map +1 -0
- package/dist/control/host-runtime.js +542 -0
- package/dist/control/host-runtime.js.map +1 -0
- package/dist/control/index.d.ts +32 -0
- package/dist/control/index.d.ts.map +1 -0
- package/dist/control/index.js +32 -0
- package/dist/control/index.js.map +1 -0
- package/dist/control/legacy-conflict.d.ts +19 -0
- package/dist/control/legacy-conflict.d.ts.map +1 -0
- package/dist/control/legacy-conflict.js +176 -0
- package/dist/control/legacy-conflict.js.map +1 -0
- package/dist/control/local-bootstrap.d.ts +21 -0
- package/dist/control/local-bootstrap.d.ts.map +1 -0
- package/dist/control/local-bootstrap.js +224 -0
- package/dist/control/local-bootstrap.js.map +1 -0
- package/dist/control/modes.d.ts +60 -0
- package/dist/control/modes.d.ts.map +1 -0
- package/dist/control/modes.js +86 -0
- package/dist/control/modes.js.map +1 -0
- package/dist/control/project-admin-cli.d.ts +3 -0
- package/dist/control/project-admin-cli.d.ts.map +1 -0
- package/dist/control/project-admin-cli.js +155 -0
- package/dist/control/project-admin-cli.js.map +1 -0
- package/dist/control/project-registry.d.ts +20 -0
- package/dist/control/project-registry.d.ts.map +1 -0
- package/dist/control/project-registry.js +181 -0
- package/dist/control/project-registry.js.map +1 -0
- package/dist/control/runtime-checkpoint.d.ts +11 -0
- package/dist/control/runtime-checkpoint.d.ts.map +1 -0
- package/dist/control/runtime-checkpoint.js +39 -0
- package/dist/control/runtime-checkpoint.js.map +1 -0
- package/dist/control/runtime-provider.d.ts +100 -0
- package/dist/control/runtime-provider.d.ts.map +1 -0
- package/dist/control/runtime-provider.js +258 -0
- package/dist/control/runtime-provider.js.map +1 -0
- package/dist/control/schema/approval.d.ts +108 -0
- package/dist/control/schema/approval.d.ts.map +1 -0
- package/dist/control/schema/approval.js +65 -0
- package/dist/control/schema/approval.js.map +1 -0
- package/dist/control/schema/commands.d.ts +663 -0
- package/dist/control/schema/commands.d.ts.map +1 -0
- package/dist/control/schema/commands.js +147 -0
- package/dist/control/schema/commands.js.map +1 -0
- package/dist/control/schema/common.d.ts +24 -0
- package/dist/control/schema/common.d.ts.map +1 -0
- package/dist/control/schema/common.js +38 -0
- package/dist/control/schema/common.js.map +1 -0
- package/dist/control/schema/coordinator.d.ts +98 -0
- package/dist/control/schema/coordinator.d.ts.map +1 -0
- package/dist/control/schema/coordinator.js +87 -0
- package/dist/control/schema/coordinator.js.map +1 -0
- package/dist/control/schema/evidence.d.ts +140 -0
- package/dist/control/schema/evidence.d.ts.map +1 -0
- package/dist/control/schema/evidence.js +64 -0
- package/dist/control/schema/evidence.js.map +1 -0
- package/dist/control/schema/header.d.ts +79 -0
- package/dist/control/schema/header.d.ts.map +1 -0
- package/dist/control/schema/header.js +66 -0
- package/dist/control/schema/header.js.map +1 -0
- package/dist/control/schema/index.d.ts +31 -0
- package/dist/control/schema/index.d.ts.map +1 -0
- package/dist/control/schema/index.js +31 -0
- package/dist/control/schema/index.js.map +1 -0
- package/dist/control/schema/plan.d.ts +291 -0
- package/dist/control/schema/plan.d.ts.map +1 -0
- package/dist/control/schema/plan.js +80 -0
- package/dist/control/schema/plan.js.map +1 -0
- package/dist/control/schema/policy.d.ts +96 -0
- package/dist/control/schema/policy.d.ts.map +1 -0
- package/dist/control/schema/policy.js +73 -0
- package/dist/control/schema/policy.js.map +1 -0
- package/dist/control/schema/run.d.ts +61 -0
- package/dist/control/schema/run.d.ts.map +1 -0
- package/dist/control/schema/run.js +56 -0
- package/dist/control/schema/run.js.map +1 -0
- package/dist/control/schema/te-mirrors.d.ts +145 -0
- package/dist/control/schema/te-mirrors.d.ts.map +1 -0
- package/dist/control/schema/te-mirrors.js +145 -0
- package/dist/control/schema/te-mirrors.js.map +1 -0
- package/dist/control/schema/transport.d.ts +479 -0
- package/dist/control/schema/transport.d.ts.map +1 -0
- package/dist/control/schema/transport.js +181 -0
- package/dist/control/schema/transport.js.map +1 -0
- package/dist/control/singleton.d.ts +135 -0
- package/dist/control/singleton.d.ts.map +1 -0
- package/dist/control/singleton.js +607 -0
- package/dist/control/singleton.js.map +1 -0
- package/dist/control/store/coordinator-store.d.ts +143 -0
- package/dist/control/store/coordinator-store.d.ts.map +1 -0
- package/dist/control/store/coordinator-store.js +620 -0
- package/dist/control/store/coordinator-store.js.map +1 -0
- package/dist/control/store/evidence-adapter.d.ts +10 -0
- package/dist/control/store/evidence-adapter.d.ts.map +1 -0
- package/dist/control/store/evidence-adapter.js +114 -0
- package/dist/control/store/evidence-adapter.js.map +1 -0
- package/dist/control/store/evidence-explanation.d.ts +55 -0
- package/dist/control/store/evidence-explanation.d.ts.map +1 -0
- package/dist/control/store/evidence-explanation.js +50 -0
- package/dist/control/store/evidence-explanation.js.map +1 -0
- package/dist/control/store/evidence-store.d.ts +143 -0
- package/dist/control/store/evidence-store.d.ts.map +1 -0
- package/dist/control/store/evidence-store.js +437 -0
- package/dist/control/store/evidence-store.js.map +1 -0
- package/dist/control/store/index.d.ts +3 -0
- package/dist/control/store/index.d.ts.map +1 -0
- package/dist/control/store/index.js +2 -0
- package/dist/control/store/index.js.map +1 -0
- package/dist/control/store/journal.d.ts +270 -0
- package/dist/control/store/journal.d.ts.map +1 -0
- package/dist/control/store/journal.js +50 -0
- package/dist/control/store/journal.js.map +1 -0
- package/dist/control/store/project-lifecycle.d.ts +49 -0
- package/dist/control/store/project-lifecycle.d.ts.map +1 -0
- package/dist/control/store/project-lifecycle.js +288 -0
- package/dist/control/store/project-lifecycle.js.map +1 -0
- package/dist/control/store/store.d.ts +93 -0
- package/dist/control/store/store.d.ts.map +1 -0
- package/dist/control/store/store.js +873 -0
- package/dist/control/store/store.js.map +1 -0
- package/dist/control/te-provider.d.ts +86 -0
- package/dist/control/te-provider.d.ts.map +1 -0
- package/dist/control/te-provider.js +131 -0
- package/dist/control/te-provider.js.map +1 -0
- package/dist/control/uds.d.ts +114 -0
- package/dist/control/uds.d.ts.map +1 -0
- package/dist/control/uds.js +456 -0
- package/dist/control/uds.js.map +1 -0
- package/dist/control/web-console/view.d.ts +5 -0
- package/dist/control/web-console/view.d.ts.map +1 -0
- package/dist/control/web-console/view.js +122 -0
- package/dist/control/web-console/view.js.map +1 -0
- package/dist/control/web-console.d.ts +50 -0
- package/dist/control/web-console.d.ts.map +1 -0
- package/dist/control/web-console.js +317 -0
- package/dist/control/web-console.js.map +1 -0
- package/dist/mcp/jsonrpc.d.ts.map +1 -1
- package/dist/mcp/jsonrpc.js +12 -3
- package/dist/mcp/jsonrpc.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +26 -17
- package/dist/mcp/server.js.map +1 -1
- package/package.json +13 -5
package/CONTROL_GUIDE.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Taskflow control plane
|
|
2
|
+
|
|
3
|
+
The implementation lives in a private workspace, but its compiled control and
|
|
4
|
+
project-administration binaries ship inside the existing `taskflow-mcp-core`
|
|
5
|
+
public package. No `taskflow-control` registry package is needed. The current
|
|
6
|
+
1.0.0 candidate is unreleased; publication and new-head CI remain separate gates.
|
|
7
|
+
|
|
8
|
+
A local candidate can be installed from its `taskflow-core` and
|
|
9
|
+
`taskflow-mcp-core` tarballs plus TypeBox, with npm lifecycle scripts disabled.
|
|
10
|
+
The control entry is `node_modules/taskflow-mcp-core/dist/control/control-cli.js`,
|
|
11
|
+
also linked as `node_modules/.bin/taskflow-control`. This guide is shipped as
|
|
12
|
+
`taskflow-mcp-core/CONTROL_GUIDE.md`. After authorized publication, install with
|
|
13
|
+
`npm install --save-exact taskflow-mcp-core@1.0.0 typebox@1.3.30`.
|
|
14
|
+
|
|
15
|
+
The control service mounts explicitly configured projects and routes requests by
|
|
16
|
+
their durable project identity. It authenticates local clients, rereads policy,
|
|
17
|
+
persists command results, coordinates capacity, and executes through the existing TE
|
|
18
|
+
runtime. Durable approval waits can survive an owner crash without repeating completed
|
|
19
|
+
phases. Receipts and explanations come from the project journal and runtime evidence.
|
|
20
|
+
|
|
21
|
+
## Local use
|
|
22
|
+
|
|
23
|
+
Use Node 22.19 or later. Keep the control home outside every execution project.
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
taskflow-control run --root /path/project --flow /path/flow.json --control-home /path/control-home
|
|
27
|
+
taskflow-control serve --root /path/project --root /path/another --control-home /path/control-home --console
|
|
28
|
+
taskflow-control status --root /path/project --control-home /path/control-home
|
|
29
|
+
taskflow-control mcp --root /path/project --control-home /path/control-home
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`auto` starts an owner or attaches to the existing owner. `coordinated` requires an
|
|
33
|
+
existing owner; it does not silently start a standalone service. The console prints
|
|
34
|
+
a private handoff-file path. Its one-use browser token is not placed in a URL or
|
|
35
|
+
printed to stdout. Local policy files under the control home are checked on each
|
|
36
|
+
operation. The CLI runs scripts; embedded callers must configure an agent runner
|
|
37
|
+
for agent phases. MCP exposes the same authenticated Host operations.
|
|
38
|
+
|
|
39
|
+
Approval output edits use validated text artifacts. Plan edits are restricted to
|
|
40
|
+
unstarted downstream phase bodies in the same dependency graph; completed phases,
|
|
41
|
+
top-level settings, and resource declarations cannot be rewritten. Plan edits are
|
|
42
|
+
compiled again before readmission. The existing runtime executes the continuation.
|
|
43
|
+
|
|
44
|
+
## Explicit coordinator operators
|
|
45
|
+
|
|
46
|
+
Normal bootstrap credentials cannot change capacity or force-release reservations.
|
|
47
|
+
An OS owner must explicitly provision the separate operator credential and a
|
|
48
|
+
project-scoped operator policy. The key is never printed; the output identifies
|
|
49
|
+
its principal and policy file. Provisioning does not overwrite an existing policy.
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
taskflow-control operator-provision --root /path/project --control-home /path/control-home
|
|
53
|
+
taskflow-control coordinator-status --root /path/project --control-home /path/control-home --mode auto --operator
|
|
54
|
+
taskflow-control set-max-active-runs --root /path/project --control-home /path/control-home --mode auto --operator --command-id UUID --max-active-runs 4
|
|
55
|
+
taskflow-control force-release --root /path/project --control-home /path/control-home --mode auto --operator --command-id UUID --reservation UUID --acknowledge-risk --reason "operator reviewed retained effects"
|
|
56
|
+
taskflow-control mcp --root /path/project --control-home /path/control-home --operator
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Replace each `UUID` with an actual identifier. Reuse the same command ID and
|
|
60
|
+
identical payload for a retry; a changed payload conflicts, and revocation is
|
|
61
|
+
checked again before replay. Mutations default to `coordinated`; the examples
|
|
62
|
+
explicitly permit `auto` to start the shared owner if absent. Capacity is a
|
|
63
|
+
user-global admitted-run limit, while reservation identifiers and force release
|
|
64
|
+
remain bound to the authenticated project. Reducing capacity below active use is
|
|
65
|
+
rejected. Status shows global aggregate counts and only authorized project rows.
|
|
66
|
+
|
|
67
|
+
Operator credentials grant project read plus the two coordinator mutations;
|
|
68
|
+
they do not inherit run submission or approval authority. Only an explicit
|
|
69
|
+
`mcp --operator` exposes the two operator mutation tools. A caller-supplied role
|
|
70
|
+
or credential label cannot replace the separate HMAC proof. The protected
|
|
71
|
+
`operator-policies` file is reread on each operation; removing a grant or revoking
|
|
72
|
+
the principal also rejects existing sessions and retries. Deleting/replacing
|
|
73
|
+
`operator.key` invalidates sessions; restart clients after deliberate key rotation.
|
|
74
|
+
Possession of that OS-user-protected key is the trust boundary, not isolation
|
|
75
|
+
from arbitrary processes running as the same OS user.
|
|
76
|
+
|
|
77
|
+
Force release frees accounting capacity without proving side effects have stopped.
|
|
78
|
+
It requires both explicit acknowledgement and a nonempty reason, persists the
|
|
79
|
+
request and `CoordinatorCommandRecord`, and records `operator-overridden`.
|
|
80
|
+
It does not fabricate a terminal Run or Receipt. Investigate unknown effects
|
|
81
|
+
before making this explicit decision.
|
|
82
|
+
|
|
83
|
+
## Offline project administration
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
taskflow-project-admin move-rebind --store /moved/project/.taskflow/control
|
|
87
|
+
taskflow-project-admin clone --store /source/.taskflow/control --destination /new/project/.taskflow/control
|
|
88
|
+
taskflow-project-admin export --store /project/.taskflow/control --output /private/export.json --kind readonly
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Stop project writers before an offline filesystem move. `move-rebind` verifies the
|
|
92
|
+
same directory device/inode, absence of the old path, writer exclusion, and settled
|
|
93
|
+
history before preserving identity. `clone` creates a fresh, empty project/domain;
|
|
94
|
+
it does not copy authoritative run history. Export preserves source bytes, including
|
|
95
|
+
damaged journal evidence, and always states `executePromise: false`.
|
|
96
|
+
|
|
97
|
+
## Recovery boundaries
|
|
98
|
+
|
|
99
|
+
Missing or damaged headers, incomplete journals, ambiguous effects, unknown owners,
|
|
100
|
+
and changed directory identities fail closed. An interrupted script can leave a
|
|
101
|
+
dirty TE mutation even after its process exits: status remains `unknown`, capacity
|
|
102
|
+
is retained, and no terminal Receipt is fabricated. SIGINT first records a versioned
|
|
103
|
+
cancellation; a bounded process shutdown fallback still reaps owned children.
|
|
104
|
+
|
|
105
|
+
Legacy conflict detection covers observable core run records and locks. It stops
|
|
106
|
+
new attempts and never kills external writers. The trusted local
|
|
107
|
+
`LegacyConflictGuard.acknowledgeStopped()` API requires captured writers to be dead.
|
|
108
|
+
Invisible unmanaged writers require external service-manager exclusion. The managed
|
|
109
|
+
legacy mutex migration helper applies only to its directly supervised child writers.
|
|
110
|
+
|
|
111
|
+
The provider reports resolve-only containment and admission-time revocation. This
|
|
112
|
+
does not claim an OS sandbox, arbitrary in-flight recovery, cross-domain transfer,
|
|
113
|
+
or general DAG editing. Logical compaction retains the physical evidence journal.
|
package/README.md
CHANGED
|
@@ -11,23 +11,23 @@
|
|
|
11
11
|
|
|
12
12
|
**English** · [简体中文](https://github.com/heggria/taskflow/blob/main/README.zh-CN.md)
|
|
13
13
|
|
|
14
|
-
[0
|
|
14
|
+
[1.0 overview](#taskflow-10-declarative-coding-agent-workflows) · [Quickstart](#quickstart) · [Docs](https://heggria.github.io/taskflow/en/docs) · [Examples](https://github.com/heggria/taskflow/blob/main/examples) · [Changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md)
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
# taskflow 0
|
|
20
|
+
# taskflow 1.0: declarative coding-agent workflows
|
|
21
21
|
|
|
22
|
-
**taskflow is a declarative runtime for coding-agent workflows.** It turns a graph into a verifiable execution contract, runs phases in isolation, and keeps intermediate work out of the host conversation. In
|
|
22
|
+
**taskflow is a declarative runtime for coding-agent workflows.** It turns a graph into a verifiable execution contract, runs phases in isolation, and keeps intermediate work out of the host conversation. In Taskflow 1.0, the contract also describes the effects a phase is allowed to propose.
|
|
23
23
|
|
|
24
|
-
> **
|
|
24
|
+
> **Taskflow 1.0.0** includes the DAG runtime, trusted filesystem effects and complete Control Plane (CLI/MCP/WebUI). [GitHub Releases](https://github.com/heggria/taskflow/releases) and npm establish publication; see the [acceptance scoreboard](https://github.com/heggria/taskflow/blob/main/docs/internal/1.0.0-ga-scoreboard.md) for verified scope and limits.
|
|
25
25
|
|
|
26
|
-
## The
|
|
26
|
+
## The declared-effect contract
|
|
27
27
|
|
|
28
28
|
An agent can propose content. It should not become the mutation authority merely because it can run a command.
|
|
29
29
|
|
|
30
|
-
For admitted, declared filesystem-write targets, taskflow 0
|
|
30
|
+
For admitted, declared filesystem-write targets, taskflow 1.0 makes the path explicit and routes the final mutation through the resources transaction:
|
|
31
31
|
|
|
32
32
|
```text
|
|
33
33
|
flow / .tf.ts
|
|
@@ -47,39 +47,40 @@ flow / .tf.ts
|
|
|
47
47
|
|
|
48
48
|
This is **not** an OS sandbox. Resolve-only hosts cannot prevent every write to an undeclared path. Secret and service references are typed and fail closed in this cut; they do not imply a vault or network backend.
|
|
49
49
|
|
|
50
|
-
##
|
|
50
|
+
## The 1.0 target and current implementation
|
|
51
51
|
|
|
52
|
-
| Layer | What it does |
|
|
52
|
+
| Layer | What it does | Support boundary |
|
|
53
53
|
|---|---|---|
|
|
54
|
-
| **Taskflow runtime** | Declarative DAGs, 12 phase types, budgets, retries, approvals, isolation, resume, replay, trace, and recompute |
|
|
55
|
-
| **Trusted Effects** | Closed `EffectIR`, `PathRef` / `SecretRef` / `ServiceRef`, confidentiality/integrity labels, effect validation, overlap checks, and ledger-backed `why-*` explainers |
|
|
56
|
-
| **Resource transaction** | Snapshot → lease → durable intent/permit → stage → commit, or restore and reject |
|
|
54
|
+
| **Taskflow runtime** | Declarative DAGs, 12 phase types, budgets, retries, approvals, isolation, resume, replay, trace, and recompute | Stable runtime contract |
|
|
55
|
+
| **Trusted Effects** | Closed `EffectIR`, `PathRef` / `SecretRef` / `ServiceRef`, confidentiality/integrity labels, effect validation, overlap checks, and ledger-backed `why-*` explainers | Declared-target contract |
|
|
56
|
+
| **Resource transaction** | Snapshot → lease → durable intent/permit → stage → commit, or restore and reject | Declared-target contract |
|
|
57
57
|
| **Host adapters** | Pi, Codex, Claude Code, OpenCode, Grok Build, and Hermes Agent use the same flow contract | Existing host surface; support remains host-specific |
|
|
58
|
-
| **Control Plane** |
|
|
59
|
-
| **WebUI** | Runs,
|
|
58
|
+
| **Control Plane** | Authenticated multi-project admission, global concurrency, durable replay, approvals/CAS, Receipts and operator CLI/MCP | Bundled in public `taskflow-mcp-core`; Unix UDS, Windows pipes non-GA |
|
|
59
|
+
| **WebUI** | Runs, approval edits, Receipts and evidence browsing | Local token login, live authorization and project isolation |
|
|
60
60
|
|
|
61
|
-
The
|
|
61
|
+
The [1.0 release plan](https://github.com/heggria/taskflow/blob/main/docs/internal/1.0.0-release-plan.md) defines the stable scope and acceptance gates. The filesystem-transaction details are in [`docs/internal/0.3.0-trusted-effects-mvp.md`](https://github.com/heggria/taskflow/blob/main/docs/internal/0.3.0-trusted-effects-mvp.md). The 0.3-C Control Plane plan is [`docs/internal/0.3-c-control-plane-plan.md`](https://github.com/heggria/taskflow/blob/main/docs/internal/0.3-c-control-plane-plan.md).
|
|
62
62
|
|
|
63
63
|
## Quickstart
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Use Node.js **≥ 22.19.0**. To run from the 1.0 source checkout:
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
68
|
git clone https://github.com/heggria/taskflow.git
|
|
69
69
|
cd taskflow
|
|
70
|
-
git checkout
|
|
70
|
+
git checkout v1.0.0
|
|
71
71
|
pnpm install
|
|
72
72
|
pnpm run typecheck
|
|
73
73
|
pnpm test
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
Install the matching 1.0.0 package set after confirming the release is available:
|
|
77
|
+
|
|
77
78
|
```bash
|
|
78
|
-
npm install --global pi-taskflow@
|
|
79
|
-
npm install --global codex-taskflow@
|
|
79
|
+
npm install --global pi-taskflow@1.0.0
|
|
80
|
+
npm install --global codex-taskflow@1.0.0
|
|
80
81
|
```
|
|
81
82
|
|
|
82
|
-
The host-specific plugin and MCP commands remain in the [host guides](https://heggria.github.io/taskflow/en/docs/guides/).
|
|
83
|
+
The host-specific plugin and MCP commands remain in the [host guides](https://heggria.github.io/taskflow/en/docs/guides/).
|
|
83
84
|
|
|
84
85
|
Run the no-LLM Trusted Effects vertical-slice fixture:
|
|
85
86
|
|
|
@@ -88,7 +89,15 @@ pnpm exec node --conditions=development --experimental-strip-types --test \
|
|
|
88
89
|
packages/taskflow-core/test/effects-e2e-fixture.test.ts
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
This exercises the checked-in `examples/trusted-effects-write.json` path without a live LLM. For an interactive run, use the host guide for the adapter you already run. The
|
|
92
|
+
This exercises the checked-in `examples/trusted-effects-write.json` path without a live LLM. For an interactive run, use the host guide for the adapter you already run. The [release guide](https://github.com/heggria/taskflow/blob/main/RELEASE.md) covers packed-consumer validation and release gates.
|
|
93
|
+
|
|
94
|
+
### Local Control Console
|
|
95
|
+
|
|
96
|
+
In Pi, run `/tf web` to start the bundled local Control Console and open the default browser. If browser opening fails, the command shows a manual loopback URL. Use the one-use token in the reported private (0600) handoff file to log in; tokens are never included in the URL or command notifications.
|
|
97
|
+
|
|
98
|
+
The console shows Control Plane runs, approvals, Receipts and existing evidence. Legacy Pi run transcripts are outside this view. Repeating the command in the same project reuses its service; changing projects or leaving the Pi session stops only the console process started by that session. Unix local transport is required. If another host already owns the Control home, stop that owner explicitly before launching this console.
|
|
99
|
+
|
|
100
|
+
See [Pi compatibility](https://github.com/heggria/taskflow/blob/main/docs/pi-compatibility.md) for the tested SDK matrix and the distinction between real-process fixtures and live-provider acceptance.
|
|
92
101
|
|
|
93
102
|
## Declare an effect
|
|
94
103
|
|
|
@@ -191,7 +200,7 @@ Host support is not a blanket security guarantee. Read the [host support baselin
|
|
|
191
200
|
- Writes to undeclared paths remain host-policy dependent under resolve-only execution.
|
|
192
201
|
- `SecretRef` and `ServiceRef` are typed handles only; no vault or live service adapter ships in this cut.
|
|
193
202
|
- There is no FileBroker or full OS sandbox claim in 0.3 MVP.
|
|
194
|
-
- Control Plane
|
|
203
|
+
- Control Plane admission, authorized replay, durable approvals, Receipts, global coordination and WebUI are implemented. Public `taskflow-mcp-core` provides the control binaries; operator actions require an explicitly provisioned separate credential. Request audit fields never grant authority.
|
|
195
204
|
|
|
196
205
|
## Development
|
|
197
206
|
|
|
@@ -210,13 +219,13 @@ The monorepo contains the host-neutral `taskflow-core`, Trusted Effects and reso
|
|
|
210
219
|
|
|
211
220
|
| Start here | Use it for |
|
|
212
221
|
|---|---|
|
|
213
|
-
| [0
|
|
222
|
+
| [1.0 overview](https://heggria.github.io/taskflow/en/docs) | 1.0 scope, support, and the security boundary |
|
|
214
223
|
| [Getting Started](https://heggria.github.io/taskflow/en/docs/getting-started) | First flow and host setup |
|
|
215
224
|
| [Core Concepts](https://heggria.github.io/taskflow/en/docs/concepts/) | DAGs, isolation, verification, resume, and evidence |
|
|
216
225
|
| [Compiler & Runtime](https://heggria.github.io/taskflow/en/docs/compiler-runtime/) | JSON, TypeScript DSL, FlowIR, replay, and recompute |
|
|
217
226
|
| [Host Guides](https://heggria.github.io/taskflow/en/docs/guides/) | Pi, Codex, Claude Code, OpenCode, Grok, and Hermes |
|
|
218
227
|
| [Examples](https://github.com/heggria/taskflow/blob/main/examples) | Runnable flow definitions, including Trusted Effects |
|
|
219
|
-
| [Changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md) | Release history and
|
|
228
|
+
| [Changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md) | Release history and version notes |
|
|
220
229
|
|
|
221
230
|
## License
|
|
222
231
|
|
|
@@ -226,6 +235,6 @@ The monorepo contains the host-neutral `taskflow-core`, Trusted Effects and reso
|
|
|
226
235
|
|
|
227
236
|
**Declare the effect. Verify the path. Commit through one authority.**
|
|
228
237
|
|
|
229
|
-
[Read the docs](https://heggria.github.io/taskflow/en/docs) · [
|
|
238
|
+
[Read the docs](https://heggria.github.io/taskflow/en/docs) · [Install Taskflow 1.0](#quickstart) · [View releases](https://github.com/heggria/taskflow/releases)
|
|
230
239
|
|
|
231
240
|
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConcurrencyReservation } from "./schema/coordinator.ts";
|
|
2
|
+
import type { ControlStore } from "./store/store.ts";
|
|
3
|
+
import type { CoordinatorAdmissionDecision, CoordinatorAdmissionObservation, CoordinatorAdmissionProof } from "./store/coordinator-store.ts";
|
|
4
|
+
export declare class ProjectAdmissionService {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(store: ControlStore);
|
|
7
|
+
readAdmission(reservation: ConcurrencyReservation): CoordinatorAdmissionObservation;
|
|
8
|
+
abandonAdmissionIfAbsent(reservation: ConcurrencyReservation): CoordinatorAdmissionDecision;
|
|
9
|
+
admit(reservation: ConcurrencyReservation, expectedRunVersion: number): CoordinatorAdmissionProof;
|
|
10
|
+
/** Called by the host at its dispatch boundary after live authorization and
|
|
11
|
+
* a current coordinator read. This is a binding check, not a replacement for
|
|
12
|
+
* the host's epoch/provider dispatch fence. No await occurs in this check. */
|
|
13
|
+
assertDispatch(reservation: ConcurrencyReservation): CoordinatorAdmissionProof;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=admission-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission-service.d.ts","sourceRoot":"","sources":["../../../taskflow-control/src/admission-service.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAuC,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAA+B,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAE7I,qBAAa,uBAAuB;;IAEnC,YAAY,KAAK,EAAE,YAAY,EAA0B;IAEzD,aAAa,CAAC,WAAW,EAAE,sBAAsB,GAAG,+BAA+B,CAIlF;IAED,wBAAwB,CAAC,WAAW,EAAE,sBAAsB,GAAG,4BAA4B,CAG1F;IAED,KAAK,CAAC,WAAW,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,GAAG,yBAAyB,CAMhG;IAED;;kFAE8E;IAC9E,cAAc,CAAC,WAAW,EAAE,sBAAsB,GAAG,yBAAyB,CAY7E;CAQD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Project-side admission arbitration. ADMIT and ABANDON are decisions in the
|
|
2
|
+
* actual ControlStore journal, serialized by its writer fence. No side files or
|
|
3
|
+
* observer callbacks carry admission authority. */
|
|
4
|
+
import { ControlError } from "./errors.js";
|
|
5
|
+
export class ProjectAdmissionService {
|
|
6
|
+
#store;
|
|
7
|
+
constructor(store) { this.#store = store; }
|
|
8
|
+
readAdmission(reservation) {
|
|
9
|
+
this.#binding(reservation);
|
|
10
|
+
const decision = this.#store.readAdmission(binding(reservation));
|
|
11
|
+
return decision ? proof(decision) : null;
|
|
12
|
+
}
|
|
13
|
+
abandonAdmissionIfAbsent(reservation) {
|
|
14
|
+
this.#binding(reservation);
|
|
15
|
+
return proof(this.#store.abandonAdmissionIfAbsent(binding(reservation)));
|
|
16
|
+
}
|
|
17
|
+
admit(reservation, expectedRunVersion) {
|
|
18
|
+
this.#binding(reservation);
|
|
19
|
+
if (reservation.state !== "reserved")
|
|
20
|
+
conflict("admission requires a reserved coordinator binding");
|
|
21
|
+
const decision = this.#store.admitRun(binding(reservation), expectedRunVersion);
|
|
22
|
+
if (decision.status !== "admitted")
|
|
23
|
+
conflict("reservation was durably abandoned; a fresh reservation is required");
|
|
24
|
+
return proof(decision);
|
|
25
|
+
}
|
|
26
|
+
/** Called by the host at its dispatch boundary after live authorization and
|
|
27
|
+
* a current coordinator read. This is a binding check, not a replacement for
|
|
28
|
+
* the host's epoch/provider dispatch fence. No await occurs in this check. */
|
|
29
|
+
assertDispatch(reservation) {
|
|
30
|
+
this.#binding(reservation);
|
|
31
|
+
if (reservation.state !== "committed")
|
|
32
|
+
conflict("dispatch requires a committed coordinator reservation");
|
|
33
|
+
const decision = this.#store.readAdmission(binding(reservation));
|
|
34
|
+
if (!decision || decision.status !== "admitted" || decision.decisionCommitSeq !== reservation.projectAdmitCommitSeq) {
|
|
35
|
+
conflict("dispatch requires the exact durable project admission");
|
|
36
|
+
}
|
|
37
|
+
const run = this.#store.readRun(reservation.runId);
|
|
38
|
+
if (!run || run.status !== "running" || !["admitted", "executing"].includes(run.stage)
|
|
39
|
+
|| run.requiresReadmission || run.reservationId !== reservation.reservationId
|
|
40
|
+
|| run.projectAdmitCommitSeq !== decision.decisionCommitSeq)
|
|
41
|
+
conflict("run no longer authorizes this dispatch");
|
|
42
|
+
return proof(decision);
|
|
43
|
+
}
|
|
44
|
+
#binding(reservation) {
|
|
45
|
+
const header = this.#store.header;
|
|
46
|
+
if (reservation.projectId !== header.projectId || reservation.projectControlDomainId !== header.controlDomainId) {
|
|
47
|
+
conflict("admission reservation belongs to another project or control domain");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function proof(decision) {
|
|
52
|
+
const binding = { reservationId: decision.reservationId, projectId: decision.projectId,
|
|
53
|
+
projectControlDomainId: decision.projectControlDomainId, runId: decision.runId, runVersion: decision.runVersion };
|
|
54
|
+
return decision.status === "admitted" ? { ...binding, projectAdmitCommitSeq: decision.decisionCommitSeq }
|
|
55
|
+
: { ...binding, status: "abandoned", abandonmentCommitSeq: decision.decisionCommitSeq };
|
|
56
|
+
}
|
|
57
|
+
function conflict(message) {
|
|
58
|
+
throw new ControlError("TF_ADMISSION_BINDING_CONFLICT", message, { recoveryAction: "operator", sideEffects: "none" });
|
|
59
|
+
}
|
|
60
|
+
function binding(reservation) {
|
|
61
|
+
return { reservationId: reservation.reservationId, projectId: reservation.projectId,
|
|
62
|
+
projectControlDomainId: reservation.projectControlDomainId, runId: reservation.runId };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=admission-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission-service.js","sourceRoot":"","sources":["../../../taskflow-control/src/admission-service.ts"],"names":[],"mappings":"AAAA;;mDAEmD;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,MAAM,OAAO,uBAAuB;IAC1B,MAAM,CAAe;IAC9B,YAAY,KAAmB,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC;IAEzD,aAAa,CAAC,WAAmC;QAChD,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;QACjE,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,CAAC;IAED,wBAAwB,CAAC,WAAmC;QAC3D,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,WAAmC,EAAE,kBAA0B;QACpE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC3B,IAAI,WAAW,CAAC,KAAK,KAAK,UAAU;YAAE,QAAQ,CAAC,mDAAmD,CAAC,CAAC;QACpG,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC,CAAC;QAChF,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU;YAAE,QAAQ,CAAC,oEAAoE,CAAC,CAAC;QACnH,OAAO,KAAK,CAAC,QAAQ,CAA8B,CAAC;IACrD,CAAC;IAED;;kFAE8E;IAC9E,cAAc,CAAC,WAAmC;QACjD,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC3B,IAAI,WAAW,CAAC,KAAK,KAAK,WAAW;YAAE,QAAQ,CAAC,uDAAuD,CAAC,CAAC;QACzG,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,IAAI,QAAQ,CAAC,iBAAiB,KAAK,WAAW,CAAC,qBAAqB,EAAE,CAAC;YACrH,QAAQ,CAAC,uDAAuD,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;eAClF,GAAG,CAAC,mBAAmB,IAAI,GAAG,CAAC,aAAa,KAAK,WAAW,CAAC,aAAa;eAC1E,GAAG,CAAC,qBAAqB,KAAK,QAAQ,CAAC,iBAAiB;YAAE,QAAQ,CAAC,wCAAwC,CAAC,CAAC;QACjH,OAAO,KAAK,CAAC,QAAQ,CAA8B,CAAC;IACrD,CAAC;IAED,QAAQ,CAAC,WAAmC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAClC,IAAI,WAAW,CAAC,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,WAAW,CAAC,sBAAsB,KAAK,MAAM,CAAC,eAAe,EAAE,CAAC;YACjH,QAAQ,CAAC,oEAAoE,CAAC,CAAC;QAChF,CAAC;IACF,CAAC;CACD;AACD,SAAS,KAAK,CAAC,QAA2B;IACzC,MAAM,OAAO,GAAG,EAAE,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS;QACrF,sBAAsB,EAAE,QAAQ,CAAC,sBAAsB,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;IACnH,OAAO,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,qBAAqB,EAAE,QAAQ,CAAC,iBAAiB,EAAE;QACxG,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,oBAAoB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAAC;AAC1F,CAAC;AACD,SAAS,QAAQ,CAAC,OAAe;IAChC,MAAM,IAAI,YAAY,CAAC,+BAA+B,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;AACvH,CAAC;AAED,SAAS,OAAO,CAAC,WAAmC;IACnD,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,aAAa,EAAE,SAAS,EAAE,WAAW,CAAC,SAAS;QAClF,sBAAsB,EAAE,WAAW,CAAC,sBAAsB,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;AACzF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Bounded approval edits: typed UTF-8 output, or replacement of unstarted
|
|
2
|
+
* downstream phase bodies in the already admitted graph. */
|
|
3
|
+
import { type RunState, type Taskflow } from "taskflow-core";
|
|
4
|
+
import type { ArtifactRef } from "./schema/evidence.ts";
|
|
5
|
+
export declare const MAX_APPROVAL_EDIT_BYTES: number;
|
|
6
|
+
export declare function decodeApprovalEdit(bytes: Uint8Array, artifact: ArtifactRef, kind: "output" | "plan"): string;
|
|
7
|
+
export declare function validateApprovalOutputEdit(state: RunState, phaseId: string, text: string): string;
|
|
8
|
+
export declare function validateApprovalPlanEdit(state: RunState, phaseId: string, candidate: unknown): Promise<{
|
|
9
|
+
flow: Taskflow;
|
|
10
|
+
irHash: string;
|
|
11
|
+
}>;
|
|
12
|
+
//# sourceMappingURL=approval-edits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-edits.d.ts","sourceRoot":"","sources":["../../../taskflow-control/src/approval-edits.ts"],"names":[],"mappings":"AAAA;4DAC4D;AAC5D,OAAO,EAA8F,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzJ,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,eAAO,MAAM,uBAAuB,QAAc,CAAC;AAGnD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAO5G;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAUjG;AAED,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBhJ"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Bounded approval edits: typed UTF-8 output, or replacement of unstarted
|
|
2
|
+
* downstream phase bodies in the already admitted graph. */
|
|
3
|
+
import { compileTaskflowToIR, isQuiescentApprovalCheckpoint, transitiveDownstream, validateTaskflow } from "taskflow-core";
|
|
4
|
+
import { contractViolations } from "taskflow-core/contract";
|
|
5
|
+
import { ControlError } from "./errors.js";
|
|
6
|
+
import { commandRequestHash } from "./schema/commands.js";
|
|
7
|
+
export const MAX_APPROVAL_EDIT_BYTES = 1024 * 1024;
|
|
8
|
+
function invalid(message) { throw new ControlError("TF_COMMAND_FAILED", message); }
|
|
9
|
+
export function decodeApprovalEdit(bytes, artifact, kind) {
|
|
10
|
+
if (bytes.byteLength > MAX_APPROVAL_EDIT_BYTES || artifact.storageClass !== "project" || artifact.redactionClass !== "internal")
|
|
11
|
+
invalid("approval edit requires a project/internal artifact of at most 1 MiB");
|
|
12
|
+
if (kind === "output" ? !/^text\/plain(?:;\s*charset=utf-8)?$/i.test(artifact.mediaType) : !/^application\/json(?:;\s*charset=utf-8)?$/i.test(artifact.mediaType))
|
|
13
|
+
invalid("approval edit artifact media type does not match its edit kind");
|
|
14
|
+
let text;
|
|
15
|
+
try {
|
|
16
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return invalid("approval edit must be valid UTF-8");
|
|
20
|
+
}
|
|
21
|
+
if (text.includes("\0"))
|
|
22
|
+
invalid("approval edit must not contain NUL");
|
|
23
|
+
return text;
|
|
24
|
+
}
|
|
25
|
+
export function validateApprovalOutputEdit(state, phaseId, text) {
|
|
26
|
+
const phase = state.def.phases.find(item => item.id === phaseId);
|
|
27
|
+
if (phase?.type !== "approval")
|
|
28
|
+
invalid("output edit target is not an approval phase");
|
|
29
|
+
const output = text.trim();
|
|
30
|
+
if (!output)
|
|
31
|
+
invalid("approval output edit must not be empty");
|
|
32
|
+
// Core approval outputs are text (edit.note), so validate that exact value
|
|
33
|
+
// against its OutputContract before admitting any downstream work.
|
|
34
|
+
const violations = contractViolations(output, phase.expect ?? { type: "string" });
|
|
35
|
+
if (violations.length)
|
|
36
|
+
invalid(`approval output contract failed: ${violations.join("; ")}`);
|
|
37
|
+
return output;
|
|
38
|
+
}
|
|
39
|
+
export async function validateApprovalPlanEdit(state, phaseId, candidate) {
|
|
40
|
+
const check = validateTaskflow(candidate);
|
|
41
|
+
if (!check.ok)
|
|
42
|
+
invalid(`approval plan is invalid: ${check.errors.join("; ")}`);
|
|
43
|
+
if (!state.foregroundOwner?.approvalWait?.includes(phaseId) || !isQuiescentApprovalCheckpoint(state, state.foregroundOwner.approvalWait))
|
|
44
|
+
throw new ControlError("TF_RECONCILE_REQUIRED", "plan edit requires its quiescent approval checkpoint");
|
|
45
|
+
const flow = structuredClone(candidate);
|
|
46
|
+
const { phases: originalPhases, ...originalTop } = state.def, { phases: nextPhases, ...nextTop } = flow;
|
|
47
|
+
if (commandRequestHash(originalTop) !== commandRequestHash(nextTop))
|
|
48
|
+
invalid("plan edit cannot change top-level settings or resource declarations");
|
|
49
|
+
if (commandRequestHash(originalPhases.map(phase => phase.id)) !== commandRequestHash(nextPhases.map(phase => phase.id)))
|
|
50
|
+
invalid("plan edit cannot add, remove, or reorder phases");
|
|
51
|
+
const downstream = new Set(transitiveDownstream(originalPhases, phaseId));
|
|
52
|
+
for (let i = 0; i < originalPhases.length; i++) {
|
|
53
|
+
const previous = originalPhases[i], next = nextPhases[i];
|
|
54
|
+
if (commandRequestHash(previous) === commandRequestHash(next))
|
|
55
|
+
continue;
|
|
56
|
+
if (!downstream.has(previous.id) || state.phases[previous.id] !== undefined)
|
|
57
|
+
invalid("plan edit cannot rewrite completed, active, or non-downstream phases");
|
|
58
|
+
if (commandRequestHash([previous.dependsOn, previous.from, previous.join]) !== commandRequestHash([next.dependsOn, next.from, next.join]))
|
|
59
|
+
invalid("plan edit cannot change phase dependencies or joins");
|
|
60
|
+
}
|
|
61
|
+
const compiled = await compileTaskflowToIR(flow);
|
|
62
|
+
if (!compiled.hash || compiled.usedFallbackHash || compiled.errors.length)
|
|
63
|
+
invalid("edited plan cannot be linked to a content-addressed IR");
|
|
64
|
+
return { flow, irHash: compiled.hash };
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=approval-edits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-edits.js","sourceRoot":"","sources":["../../../taskflow-control/src/approval-edits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { type CommandRecord, type ControlEventPayload } from "./schema/commands.ts";
|
|
2
|
+
import { type ApprovalRequest, type ApprovalMode, type ApprovalDecision } from "./schema/approval.ts";
|
|
3
|
+
import { type ArtifactRef } from "./schema/evidence.ts";
|
|
4
|
+
import { type BoundFragment } from "./schema/plan.ts";
|
|
5
|
+
import type { RunSnapshot } from "./schema/run.ts";
|
|
6
|
+
import type { ExecutionOwner } from "./schema/te-mirrors.ts";
|
|
7
|
+
import type { ConcurrencyReservation } from "./schema/coordinator.ts";
|
|
8
|
+
export type ApprovalRun = RunSnapshot & {
|
|
9
|
+
runVersion: number;
|
|
10
|
+
boundPlanHash: string;
|
|
11
|
+
boundFragmentHash?: string;
|
|
12
|
+
policyHash: string;
|
|
13
|
+
authorityEpoch: number;
|
|
14
|
+
reservationId?: string;
|
|
15
|
+
owner?: ExecutionOwner;
|
|
16
|
+
};
|
|
17
|
+
export type DurableApprovalRequest = ApprovalRequest;
|
|
18
|
+
export interface ApprovalQuiescence {
|
|
19
|
+
proofId: string;
|
|
20
|
+
projectId: string;
|
|
21
|
+
projectControlDomainId: string;
|
|
22
|
+
runId: string;
|
|
23
|
+
projectAdmitCommitSeq: number;
|
|
24
|
+
providerNoLiveProcessTree: boolean;
|
|
25
|
+
noAmbiguousJobs: boolean;
|
|
26
|
+
noPendingResourceIntents: boolean;
|
|
27
|
+
reconcileTimeoutOnly: boolean;
|
|
28
|
+
}
|
|
29
|
+
export type ApprovalReleaseIntent = {
|
|
30
|
+
kind: "approval.release";
|
|
31
|
+
intentId: string;
|
|
32
|
+
approvalRequestId: string;
|
|
33
|
+
runId: string;
|
|
34
|
+
reservationId: string;
|
|
35
|
+
evidence: ApprovalQuiescence;
|
|
36
|
+
complete: boolean;
|
|
37
|
+
};
|
|
38
|
+
export type ApprovalReadmissionIntent = {
|
|
39
|
+
kind: "approval.readmission";
|
|
40
|
+
intentId: string;
|
|
41
|
+
approvalRequestId: string;
|
|
42
|
+
runId: string;
|
|
43
|
+
reservation: ConcurrencyReservation;
|
|
44
|
+
owner: ExecutionOwner;
|
|
45
|
+
fragment: BoundFragment;
|
|
46
|
+
policyHash: string;
|
|
47
|
+
authorizationContextHash: string;
|
|
48
|
+
projectAdmitCommitSeq: number;
|
|
49
|
+
complete: boolean;
|
|
50
|
+
};
|
|
51
|
+
export type ApprovalOutbox = ApprovalReleaseIntent | ApprovalReadmissionIntent;
|
|
52
|
+
export type ApprovalJournalEvent = {
|
|
53
|
+
eventId: string;
|
|
54
|
+
recordedAt: number;
|
|
55
|
+
payload: ControlEventPayload;
|
|
56
|
+
};
|
|
57
|
+
export interface ApprovalJournalState {
|
|
58
|
+
run: ApprovalRun;
|
|
59
|
+
approvals: DurableApprovalRequest[];
|
|
60
|
+
outbox: ApprovalOutbox[];
|
|
61
|
+
}
|
|
62
|
+
export interface ApprovalMutation extends ApprovalJournalState {
|
|
63
|
+
command?: CommandRecord;
|
|
64
|
+
responseJson?: string;
|
|
65
|
+
events: ApprovalJournalEvent[];
|
|
66
|
+
}
|
|
67
|
+
export interface ApprovalCommit extends ApprovalJournalState {
|
|
68
|
+
commitSeq: number;
|
|
69
|
+
responseJson?: string;
|
|
70
|
+
}
|
|
71
|
+
export type CommandBinding = Pick<CommandRecord, "commandId" | "kind" | "requestHash" | "callerPrincipal" | "projectId" | "controlDomainId">;
|
|
72
|
+
export interface ApprovalStorage {
|
|
73
|
+
readCommittedCommand?(binding: CommandBinding): {
|
|
74
|
+
record: CommandRecord;
|
|
75
|
+
responseJson: string;
|
|
76
|
+
} | undefined;
|
|
77
|
+
readRun(runId: string): ApprovalRun | undefined;
|
|
78
|
+
readApproval(approvalRequestId: string): DurableApprovalRequest | undefined;
|
|
79
|
+
listApprovals(): DurableApprovalRequest[];
|
|
80
|
+
readOutbox(runId: string): ApprovalOutbox[];
|
|
81
|
+
/** Synchronous, writer-locked CAS; journal fsync precedes observable state.
|
|
82
|
+
* The adapter checks runVersion and commits the complete batch atomically. */
|
|
83
|
+
mutateRun(runId: string, expectedRunVersion: number, build: (state: ApprovalJournalState, meta: {
|
|
84
|
+
commitSeq: number;
|
|
85
|
+
}) => ApprovalMutation, binding?: CommandBinding): ApprovalCommit;
|
|
86
|
+
}
|
|
87
|
+
export type ApprovalOperation = "request" | "read" | "decide" | "cancel" | "expire" | "park" | "readmit";
|
|
88
|
+
export type ApprovalAuthorization = {
|
|
89
|
+
callerPrincipal: string;
|
|
90
|
+
authorizationContextHash: string;
|
|
91
|
+
};
|
|
92
|
+
export interface ApprovalAuthority<C> {
|
|
93
|
+
/** Context is issued by the host's trusted identity authority; wire identity
|
|
94
|
+
* labels are never an input to authorization. Must evaluate current policy. */
|
|
95
|
+
authorize(context: C, scope: {
|
|
96
|
+
operation: ApprovalOperation;
|
|
97
|
+
run: ApprovalRun;
|
|
98
|
+
request?: DurableApprovalRequest;
|
|
99
|
+
}): Promise<ApprovalAuthorization>;
|
|
100
|
+
validateRequest(context: C, run: ApprovalRun, nodeInstanceId: string): Promise<void>;
|
|
101
|
+
/** Evaluate actual host offers and this authenticated caller's handshake. */
|
|
102
|
+
negotiateDurability(context: C, run: ApprovalRun, mode: ApprovalMode): Promise<boolean>;
|
|
103
|
+
quiescence(context: C, run: ApprovalRun): Promise<ApprovalQuiescence>;
|
|
104
|
+
validateEdit(context: C, run: ApprovalRun, request: DurableApprovalRequest, edit: {
|
|
105
|
+
kind: "output" | "plan";
|
|
106
|
+
artifact: ArtifactRef;
|
|
107
|
+
}): Promise<void>;
|
|
108
|
+
/** Output edits are contract-checked; plan edits must re-Link. Both obtain
|
|
109
|
+
* current policy/capabilities and a new attenuated BoundFragment. */
|
|
110
|
+
prepareReadmission(context: C, run: ApprovalRun, request: DurableApprovalRequest): Promise<{
|
|
111
|
+
fragment: BoundFragment;
|
|
112
|
+
owner: ExecutionOwner;
|
|
113
|
+
policyHash: string;
|
|
114
|
+
authorizationContextHash: string;
|
|
115
|
+
}>;
|
|
116
|
+
validateReadmission(context: C, run: ApprovalRun, intent: ApprovalReadmissionIntent): Promise<void>;
|
|
117
|
+
reserve(context: C, run: ApprovalRun, owner: ExecutionOwner): Promise<ConcurrencyReservation>;
|
|
118
|
+
commitReservation(context: C, intent: ApprovalReadmissionIntent): Promise<void>;
|
|
119
|
+
normalRelease(context: C, intent: ApprovalReleaseIntent): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
export interface ApprovalRequestInput {
|
|
122
|
+
runId: string;
|
|
123
|
+
expectedRunVersion: number;
|
|
124
|
+
nodeInstanceId: string;
|
|
125
|
+
mode: ApprovalMode;
|
|
126
|
+
allowedDecisions: ApprovalDecision[];
|
|
127
|
+
owner: string;
|
|
128
|
+
audience?: string[];
|
|
129
|
+
requiredPrincipals?: string[];
|
|
130
|
+
deadline: number;
|
|
131
|
+
timeoutPolicy: ApprovalRequest["timeoutPolicy"];
|
|
132
|
+
}
|
|
133
|
+
export interface ApprovalDecisionInput {
|
|
134
|
+
commandId: string;
|
|
135
|
+
runId: string;
|
|
136
|
+
approvalRequestId: string;
|
|
137
|
+
expectedRunVersion: number;
|
|
138
|
+
decision: ApprovalDecision;
|
|
139
|
+
editArtifactRef?: ArtifactRef;
|
|
140
|
+
editKind?: "output" | "plan";
|
|
141
|
+
}
|
|
142
|
+
export declare class ApprovalService<C = unknown> {
|
|
143
|
+
#private;
|
|
144
|
+
readonly storage: ApprovalStorage;
|
|
145
|
+
readonly authority: ApprovalAuthority<C>;
|
|
146
|
+
constructor(storage: ApprovalStorage, authority: ApprovalAuthority<C>);
|
|
147
|
+
read(context: C, approvalRequestId: string): Promise<DurableApprovalRequest>;
|
|
148
|
+
request(context: C, input: ApprovalRequestInput): Promise<DurableApprovalRequest>;
|
|
149
|
+
decide(context: C, input: ApprovalDecisionInput): Promise<DurableApprovalRequest>;
|
|
150
|
+
expireDue(context: C): Promise<number>;
|
|
151
|
+
cancel(context: C, input: {
|
|
152
|
+
commandId: string;
|
|
153
|
+
runId: string;
|
|
154
|
+
expectedRunVersion: number;
|
|
155
|
+
}): Promise<ApprovalRun>;
|
|
156
|
+
/** Re-prove quiescence after a non-quiescent pause; never infer it from status. */
|
|
157
|
+
park(context: C, input: {
|
|
158
|
+
runId: string;
|
|
159
|
+
expectedRunVersion: number;
|
|
160
|
+
}): Promise<ApprovalRun>;
|
|
161
|
+
/** Terminal status may precede process/TE settlement. Once settlement is
|
|
162
|
+
* proven, discharge capacity without reopening or changing terminal history. */
|
|
163
|
+
releaseTerminal(context: C, input: {
|
|
164
|
+
runId: string;
|
|
165
|
+
expectedRunVersion: number;
|
|
166
|
+
}): Promise<ApprovalRun>;
|
|
167
|
+
drainReleases(context: C, runId?: string): Promise<void>;
|
|
168
|
+
readmit(context: C, input: {
|
|
169
|
+
approvalRequestId: string;
|
|
170
|
+
expectedRunVersion: number;
|
|
171
|
+
}): Promise<ApprovalRun>;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=approval-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-service.d.ts","sourceRoot":"","sources":["../../../taskflow-control/src/approval-service.ts"],"names":[],"mappings":"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"}
|