@type_of/interlock 0.0.1
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/CONTEXT.md +29 -0
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/dist/cli.js +29955 -0
- package/dist/cli.js.LEGAL.txt +14 -0
- package/dist/ui/assets/flow-BvQd7kaB.js +7 -0
- package/dist/ui/assets/index-Dx6oG2iY.css +1 -0
- package/dist/ui/assets/index-yft-gfwH.js +61 -0
- package/dist/ui/assets/mantine-C23NIffR.js +45 -0
- package/dist/ui/favicon.svg +1 -0
- package/dist/ui/index.html +17 -0
- package/docs/architecture.md +62 -0
- package/docs/connect-harness.md +107 -0
- package/docs/v1.md +30 -0
- package/package.json +59 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="8" fill="#1e1e24"/><g fill="none" stroke="#82b4ff" stroke-width="2"><rect x="6" y="6" width="13" height="13" rx="2"/><rect stroke="#f0a1d3" x="13" y="13" width="13" height="13" rx="2"/></g></svg>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
|
6
|
+
<meta name="theme-color" content="#17171b" />
|
|
7
|
+
<link rel="icon" href="/favicon.svg" />
|
|
8
|
+
<title>Interlock</title>
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-yft-gfwH.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/mantine-C23NIffR.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/flow-BvQd7kaB.js">
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Dx6oG2iY.css">
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<div id="root"></div>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Architecture and execution semantics
|
|
2
|
+
|
|
3
|
+
Interlock keeps workflow behavior in the runtime so that UI, CLI, and MCP callers share the same execution rules.
|
|
4
|
+
|
|
5
|
+
## Packages
|
|
6
|
+
|
|
7
|
+
| Package | Responsibility |
|
|
8
|
+
| --------- | -------------------------------------------------------------------------------- |
|
|
9
|
+
| `core` | Domain types, JSON contracts, graph validation |
|
|
10
|
+
| `runtime` | Execution, child scheduling, work claims, context requirements, script lifecycle |
|
|
11
|
+
| `storage` | SQLite persistence and transaction ownership |
|
|
12
|
+
| `server` | Hono listener, tRPC procedures, run event stream, example seeding |
|
|
13
|
+
| `client` | Typed HTTP client shared by UI, CLI, and MCP |
|
|
14
|
+
| `ui` | React application, React Flow editor, reusable controls, run inspection |
|
|
15
|
+
| `cli` | JSON commands for terminal callers |
|
|
16
|
+
| `mcp` | Stdio MCP tools for agent callers |
|
|
17
|
+
|
|
18
|
+
The client imports the server router type only. It does not bundle or instantiate the engine. The server is the only process that writes application state. MCP adapters and CLI commands can exit without losing runs.
|
|
19
|
+
|
|
20
|
+
SQLite stores workflow, version, run, assignment, and event documents. Each synchronous engine operation uses a transaction. The runtime scans persisted active runs when advancing work. This favors a small local implementation over a distributed scheduler. It is unsuitable for multiple competing server processes or a large run archive without further indexing and scheduling work.
|
|
21
|
+
|
|
22
|
+
## Workflow definitions
|
|
23
|
+
|
|
24
|
+
A workflow has a stable ID, mutable metadata, and an editable draft. Publishing validates graph routes, JSON schemas, and child version references, then creates an immutable version. Draft revisions reject stale edits. Existing runs read their published version, including when the workflow is renamed or its draft changes.
|
|
25
|
+
|
|
26
|
+
One entry begins a run. Each node receives the previous node's output as its whole input. Each ordinary node has one default outgoing route. Conditions have one true route and one false route. Exit nodes have no outgoing route. Loops are allowed and bounded by the workflow step limit.
|
|
27
|
+
|
|
28
|
+
A condition compares a path in its input to a JSON value using structural equality. It passes the input through unchanged. Paths are dot-separated object keys or array indices. Empty paths select the entire input. They are not general JSONPath expressions.
|
|
29
|
+
|
|
30
|
+
Child workflow nodes pin an existing published version. A map reads an array and starts one child run per item, with bounded active children. Results retain input order. The `all` failure policy fails the parent and cancels remaining children. The `collect` policy returns records containing child status, output, and error. Empty arrays produce an empty result.
|
|
31
|
+
|
|
32
|
+
Explicitly retrying a failed map preserves successful children and resumes failed or cancelled children. Published definitions remain unchanged. To fix the procedure itself, publish another version and start a new run.
|
|
33
|
+
|
|
34
|
+
## Agent work
|
|
35
|
+
|
|
36
|
+
Agent nodes persist an assignment and pause. A worker claims available work with an expiring token. Claims check the requested fresh-context mode, required tools, and required skills against worker declarations. The assignment includes the exact prompt, input, context policy, and output contract.
|
|
37
|
+
|
|
38
|
+
Results must satisfy the output schema. Invalid results leave the claim active so the worker can correct them. Repeating an accepted result with the same token is idempotent. A changed duplicate, stale token, or cancelled claim is rejected.
|
|
39
|
+
|
|
40
|
+
A reported failure or expired claim makes work available again until its attempt limit is exhausted. Manual retry starts another attempt sequence and records that intervention. A step budget still bounds execution within each run.
|
|
41
|
+
|
|
42
|
+
Context requirements are a cooperation contract with the executor. Interlock cannot prove that an external harness created a fresh conversation, restrict that harness's other tools, or erase its history. No native MCP sampling callback is required. Work discovery and submission implement the return path.
|
|
43
|
+
|
|
44
|
+
## Scripts and interruptions
|
|
45
|
+
|
|
46
|
+
Scripts run in Bash, receive JSON on stdin, and must emit one JSON value on stdout. They inherit the service environment and OS permissions. The working directory defaults to the repository and can be changed with `INTERLOCK_WORKDIR`.
|
|
47
|
+
|
|
48
|
+
Scripts have time and output limits. Cancellation kills their process group. Shutdown stops local script processes. On restart, persisted interrupted script executions become failures because their side effects are uncertain. Interlock never automatically replays them. An explicit retry can repeat side effects, so inspect the failed step first.
|
|
49
|
+
|
|
50
|
+
Script execution happens outside database transactions. Agent claims and result submission remain available while scripts run. Completed script results are committed before advancing dependent steps.
|
|
51
|
+
|
|
52
|
+
## Local interfaces
|
|
53
|
+
|
|
54
|
+
The service binds to loopback and rejects unexpected request hosts and browser origins. It is a single-user local service without authentication. Local processes can invoke its interfaces. It must not be exposed through a public tunnel.
|
|
55
|
+
|
|
56
|
+
The UI uses tRPC requests and server-sent notifications, with periodic refresh as a reconnect fallback. Events and node execution data remain in SQLite. `INTERLOCK_DB` changes the database location. `INTERLOCK_URL` changes the service URL used by CLI and MCP callers.
|
|
57
|
+
|
|
58
|
+
## UI components
|
|
59
|
+
|
|
60
|
+
Mantine provides dialogs, form controls, tabs, menus, and status badges. The shared theme in `packages/ui/src/theme/theme.ts` defines the dark palette and component defaults. Canvas colors reference those tokens through CSS variables. CSS Modules handle product layouts and React Flow nodes.
|
|
61
|
+
|
|
62
|
+
Use Mantine components directly for standard controls. Keep shared components for Interlock behavior, such as JSON validation, contract editing, action variants, and status-to-color mapping. Settings dialogs hold local edits until Apply changes; contract editing uses a page within that dialog. Cancel discards the settings edit, including applied contract changes.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Connect a harness
|
|
2
|
+
|
|
3
|
+
## Start Interlock
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install -g @type_of/interlock
|
|
7
|
+
interlock
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Keep this process running and open [Interlock](http://127.0.0.1:4310). **Connect with MCP** provides configuration for the running installation, including absolute paths if your harness cannot find the globally installed command.
|
|
11
|
+
|
|
12
|
+
## Codex
|
|
13
|
+
|
|
14
|
+
Add this to `~/.codex/config.toml`:
|
|
15
|
+
|
|
16
|
+
```toml
|
|
17
|
+
[mcp_servers.interlock]
|
|
18
|
+
command = "interlock"
|
|
19
|
+
args = ["mcp"]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
See the [Codex MCP guide](https://developers.openai.com/codex/mcp).
|
|
23
|
+
|
|
24
|
+
## Claude
|
|
25
|
+
|
|
26
|
+
For Claude Code, run:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
claude mcp add --transport stdio --scope user interlock -- interlock mcp
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For Claude Desktop, merge this into its MCP configuration:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"interlock": { "command": "interlock", "args": ["mcp"] }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
See the [Claude Code MCP guide](https://code.claude.com/docs/en/mcp). The connection modal also supplies absolute paths for desktop applications whose PATH does not include global npm commands.
|
|
43
|
+
|
|
44
|
+
## OpenCode
|
|
45
|
+
|
|
46
|
+
Merge this into `opencode.json`:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"$schema": "https://opencode.ai/config.json",
|
|
51
|
+
"mcp": {
|
|
52
|
+
"interlock": {
|
|
53
|
+
"type": "local",
|
|
54
|
+
"command": ["interlock", "mcp"],
|
|
55
|
+
"enabled": true
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
See the [OpenCode MCP guide](https://opencode.ai/docs/mcp-servers/).
|
|
62
|
+
|
|
63
|
+
## Other clients
|
|
64
|
+
|
|
65
|
+
Use a local **stdio** MCP server. Set the command to `interlock` and its argument list to `["mcp"]`. No additional arguments are required. The harness launches this bridge and communicates over stdin/stdout.
|
|
66
|
+
|
|
67
|
+
The bridge connects to the running engine at `http://127.0.0.1:4310`. Set the bridge environment variable `INTERLOCK_URL` when using another port. This engine URL is an internal HTTP API, not an HTTP MCP endpoint.
|
|
68
|
+
|
|
69
|
+
Restart or reconnect your harness after changing configuration. Enable Interlock's tools in its approval settings. Interlock does not modify harness configuration for you.
|
|
70
|
+
|
|
71
|
+
## Complete a run
|
|
72
|
+
|
|
73
|
+
Give the harness a workflow ID and input, then ask it to complete the run through Interlock:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
Start Interlock workflow WORKFLOW_ID with the supplied input.
|
|
77
|
+
Use list_work for the root run, including its child runs.
|
|
78
|
+
Claim assignments with your actual capabilities.
|
|
79
|
+
Perform each assignment using its prompt, input, and context policy.
|
|
80
|
+
Submit JSON matching its output schema.
|
|
81
|
+
Continue until the root run completes or fails.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`start_run` returns a persisted run. `list_work` includes descendants of the requested run. A claim returns its token and expiry. Keep the token for `submit_result`, `renew_claim`, or `fail_work`. Inspect `get_run` to distinguish a completed run from one waiting on claimed work or scripts.
|
|
85
|
+
|
|
86
|
+
If execution will exceed the lease, call `renew_claim` before it expires. If a submission loses its response, submit the identical result again using the same token. If a claim has expired, discover and claim available work again. Do not submit through another worker's claim.
|
|
87
|
+
|
|
88
|
+
A fresh-context assignment requires an isolated agent execution. Do not declare `freshContext: true` merely because the assignment has a focused prompt. Declare required tools and skills only when the executor can actually use them.
|
|
89
|
+
|
|
90
|
+
## Diagnose a connection
|
|
91
|
+
|
|
92
|
+
Check the service first:
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
curl http://127.0.0.1:4310/health
|
|
96
|
+
interlock workflows
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If both succeed but the harness cannot execute Interlock tools, inspect its MCP startup and approval settings. The MCP adapter prints protocol messages to stdout and diagnostics to stderr. Do not wrap its command in a script that prints startup banners to stdout.
|
|
100
|
+
|
|
101
|
+
The automated MCP transport test runs without a model:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
pnpm test
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The optional `scripts/codex-smoke.ts` check invokes the installed Codex CLI with a local text task. The initial host rejected `start_run` because tool approval was required while approval policy was `never`. That result does not establish an Interlock execution failure, and it does not verify a full Codex run.
|
package/docs/v1.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# V1 scope
|
|
2
|
+
|
|
3
|
+
## Implemented
|
|
4
|
+
|
|
5
|
+
- Local Git repository and pnpm workspace packages.
|
|
6
|
+
- Dark UI with workflow search, create, clone, rename, archive, restore, import, and export.
|
|
7
|
+
- React Flow authoring with node configuration and JSON contracts.
|
|
8
|
+
- Editable drafts, immutable published versions, and stale-draft protection.
|
|
9
|
+
- Entry, exit, agent, script, condition, child workflow, and map nodes.
|
|
10
|
+
- Persistent runs, event history, nested run inspection, cancellation, and explicit retry.
|
|
11
|
+
- Work requests, capability checks, expiring claims, lease renewal, schema validation, and duplicate submission protection.
|
|
12
|
+
- Concurrent child dispatch with ordered collection and explicit failure policy.
|
|
13
|
+
- UI-started runs and manual completion of unrestricted current-context assignments.
|
|
14
|
+
- MCP tools for authoring and execution, plus CLI access to the same service.
|
|
15
|
+
- Example protocol research and opportunity synthesis definitions.
|
|
16
|
+
- Changesets configuration for future releases.
|
|
17
|
+
|
|
18
|
+
## Current limits
|
|
19
|
+
|
|
20
|
+
Agent execution requires a connected harness or manual submission. Interlock does not launch fresh agent sessions or provide direct model API execution. Codex can discover the MCP server, but the local noninteractive smoke attempt was blocked by the host's tool approval policy. Full Codex execution remains unverified. Claude and OpenCode have not been tested.
|
|
21
|
+
|
|
22
|
+
Tool and skill requirements are names checked against executor declarations. The executor supplies their implementations. Interlock does not load arbitrary skill files or manage outgoing MCP connections itself.
|
|
23
|
+
|
|
24
|
+
Input and output contracts have a field editor with named fields, display labels, required flags, descriptions, nested objects and lists, and text choices. Pasting example JSON generates a draft contract and highlights assumptions to review. Advanced JSON Schema remains available; schemas outside the visual editor’s supported subset stay intact in advanced mode. The run dialog provides fields for common object schemas and JSON editing for complex values. There is no static proof that every connected node's contracts are compatible. Actual inputs and outputs are checked at execution time.
|
|
25
|
+
|
|
26
|
+
Results are JSON stored in SQLite. The UI exports run records and workflow definitions. Separate artifact storage, rendered recommendation documents, version diffs, and replay against captured sources are not implemented.
|
|
27
|
+
|
|
28
|
+
Maps support at most 200 items, 50 concurrent child runs, and 10 nested workflow levels. Arbitrary parallel graph joins are not supported. Use a map over a child workflow to dispatch and collect.
|
|
29
|
+
|
|
30
|
+
Self-improvement proposals, evaluations, automatic promotion, direct provider adapters, sandboxed script execution, scheduling, and multi-user access remain future work.
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@type_of/interlock",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"packageManager": "pnpm@11.7.0",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": ">=24.13.0"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "concurrently -k -n server,ui \"pnpm --filter @interlock/server dev\" \"pnpm --filter @interlock/ui dev\"",
|
|
10
|
+
"build": "pnpm typecheck && pnpm --filter @interlock/ui build && node scripts/build-package.mjs",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"test": "vitest run",
|
|
13
|
+
"start": "pnpm --filter @interlock/server start",
|
|
14
|
+
"cli": "pnpm --filter @interlock/cli start",
|
|
15
|
+
"mcp": "pnpm --filter @interlock/mcp start",
|
|
16
|
+
"changeset": "changeset",
|
|
17
|
+
"format": "prettier --write .",
|
|
18
|
+
"format:check": "prettier --check .",
|
|
19
|
+
"prepack": "pnpm build",
|
|
20
|
+
"test:package": "node scripts/test-package.mjs"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@changesets/cli": "^2.29.7",
|
|
24
|
+
"@hono/node-server": "^1.19.17",
|
|
25
|
+
"@interlock/client": "workspace:*",
|
|
26
|
+
"@interlock/core": "workspace:*",
|
|
27
|
+
"@interlock/runtime": "workspace:*",
|
|
28
|
+
"@interlock/storage": "workspace:*",
|
|
29
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
30
|
+
"@types/node": "^24.10.0",
|
|
31
|
+
"@types/react": "^19.2.0",
|
|
32
|
+
"@types/react-dom": "^19.2.0",
|
|
33
|
+
"concurrently": "^9.2.1",
|
|
34
|
+
"esbuild": "^0.28.2",
|
|
35
|
+
"prettier": "^3.6.2",
|
|
36
|
+
"tsx": "^4.20.6",
|
|
37
|
+
"typescript": "^5.9.3",
|
|
38
|
+
"vitest": "^3.2.4"
|
|
39
|
+
},
|
|
40
|
+
"version": "0.0.1",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"description": "Local workflow engine and visual editor for agent harnesses",
|
|
43
|
+
"bin": {
|
|
44
|
+
"interlock": "dist/cli.js"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"README.md",
|
|
49
|
+
"CONTEXT.md",
|
|
50
|
+
"docs"
|
|
51
|
+
],
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"os": [
|
|
56
|
+
"darwin",
|
|
57
|
+
"linux"
|
|
58
|
+
]
|
|
59
|
+
}
|