@vimhead.dev/norn-cli 0.1.0-tip.35359392805.1 → 0.1.0-tip.35436871363.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/assets/README.md +22 -27
- package/assets/docs/README.md +5 -5
- package/assets/docs/agents.md +48 -9
- package/assets/docs/cli.md +7 -7
- package/assets/docs/composition.md +25 -25
- package/assets/docs/persistence.md +34 -23
- package/assets/docs/projects.md +30 -18
- package/assets/docs/providers.md +3 -3
- package/assets/docs/recovery.md +13 -9
- package/assets/docs/schemas.md +1 -1
- package/assets/docs/workflows.md +105 -12
- package/assets/examples/agent-then-analysis/README.md +10 -10
- package/assets/examples/agent-then-analysis/input.json +1 -1
- package/assets/examples/agent-then-analysis/norn.project.json +1 -1
- package/assets/examples/agent-then-analysis/plugin.ts +57 -68
- package/assets/examples/caller-selected-continuation/README.md +15 -14
- package/assets/examples/caller-selected-continuation/caller.ts +37 -38
- package/assets/examples/caller-selected-continuation/input.json +2 -2
- package/assets/examples/caller-selected-continuation/norn.project.json +1 -1
- package/assets/examples/caller-selected-continuation/producer.ts +19 -24
- package/assets/examples/coordinating-multiple-agents/README.md +27 -17
- package/assets/examples/coordinating-multiple-agents/input.json +1 -1
- package/assets/examples/coordinating-multiple-agents/norn.project.json +1 -1
- package/assets/examples/coordinating-multiple-agents/plugin.ts +79 -60
- package/assets/examples/coordinating-multiple-agents/queue-tools.ts +43 -0
- package/assets/examples/coordinating-multiple-agents/work-queue.ts +60 -65
- package/assets/examples/getting-started/README.md +2 -2
- package/assets/examples/getting-started/norn.project.json +1 -1
- package/assets/examples/getting-started/plugin.ts +20 -26
- package/assets/examples/minimal-workflow/README.md +13 -12
- package/assets/examples/minimal-workflow/norn.project.json +1 -1
- package/assets/examples/minimal-workflow/plugin.ts +14 -25
- package/assets/examples/shared-state/README.md +12 -4
- package/assets/examples/shared-state/input.json +1 -1
- package/assets/examples/shared-state/norn.project.json +1 -1
- package/assets/examples/shared-state/plugin.ts +49 -41
- package/assets/examples/shared-state/shared-state.ts +56 -0
- package/assets/examples/shared-state/state-tools.ts +68 -0
- package/assets/examples/worktree-development-loop/README.md +18 -17
- package/assets/examples/worktree-development-loop/norn.project.json +1 -1
- package/assets/examples/worktree-development-loop/plugin.ts +6 -26
- package/assets/examples/worktree-development-loop/scope.ts +4 -0
- package/assets/examples/worktree-development-loop/workflows/development-loop/execute.ts +14 -15
- package/assets/examples/worktree-development-loop/workflows/development-loop/index.ts +3 -4
- package/assets/examples/worktree-development-loop/workflows/development-loop/repository.ts +5 -3
- package/assets/examples/worktree-development-loop/workflows/development-loop/schema.ts +2 -2
- package/assets/examples/worktree-development-loop/workflows/implementation/execute.ts +35 -33
- package/assets/examples/worktree-development-loop/workflows/implementation/index.ts +2 -3
- package/assets/examples/worktree-development-loop/workflows/implementation/schema.ts +6 -3
- package/assets/examples/worktree-development-loop/workflows/planning/execute.ts +27 -16
- package/assets/examples/worktree-development-loop/workflows/planning/index.ts +2 -3
- package/assets/examples/worktree-development-loop/workflows/planning/schema.ts +4 -2
- package/assets/examples/worktree-development-loop/workflows/review/execute.ts +43 -31
- package/assets/examples/worktree-development-loop/workflows/review/index.ts +3 -4
- package/assets/examples/worktree-development-loop/workflows/review/schema.ts +6 -6
- package/assets/examples/worktree-development-loop/workflows/review-router/execute.ts +50 -44
- package/assets/examples/worktree-development-loop/workflows/review-router/index.ts +2 -3
- package/assets/examples/worktree-development-loop/workflows/review-router/schema.ts +5 -5
- package/assets/package.json +1 -1
- package/assets/packages/cli/src/cli.ts +44 -37
- package/assets/packages/cli/src/client.ts +9 -16
- package/assets/packages/cli/src/documentation-intro.ts +1 -1
- package/assets/packages/cli/src/generated-build-info.ts +2 -2
- package/assets/packages/cli/src/internal/agent-response-tool.ts +3 -3
- package/assets/packages/cli/src/internal/agents.ts +24 -32
- package/assets/packages/cli/src/internal/commands.ts +2 -14
- package/assets/packages/cli/src/internal/engine.ts +63 -101
- package/assets/packages/cli/src/internal/errors.ts +4 -4
- package/assets/packages/cli/src/internal/launch-request.ts +6 -6
- package/assets/packages/cli/src/internal/logs.ts +1 -1
- package/assets/packages/cli/src/internal/run-log.ts +1 -1
- package/assets/packages/cli/src/internal/run-state.ts +38 -23
- package/assets/packages/cli/src/internal/run.ts +4 -62
- package/assets/packages/cli/src/internal/worker-directory.ts +17 -0
- package/assets/packages/cli/src/internal/workflow-registry.ts +126 -111
- package/assets/packages/cli/src/internal/working-directory.ts +6 -0
- package/assets/packages/cli/src/workflow-loader.ts +213 -0
- package/assets/packages/core/src/workflow-transition.ts +2 -2
- package/assets/packages/sdk/src/api.ts +141 -329
- package/assets/packages/sdk/src/index.ts +1 -4
- package/assets/packages/sdk/src/schema.ts +3 -3
- package/assets/tests/workflow-ref.test.ts +53 -55
- package/dist/cli.js +41 -35
- package/dist/client.d.ts +3 -4
- package/dist/client.js +3 -8
- package/dist/documentation-intro.js +1 -1
- package/dist/generated-build-info.d.ts +2 -2
- package/dist/generated-build-info.js +2 -2
- package/dist/internal/agent-response-tool.js +3 -3
- package/dist/internal/agents.d.ts +0 -4
- package/dist/internal/agents.js +30 -46
- package/dist/internal/commands.d.ts +0 -4
- package/dist/internal/commands.js +2 -10
- package/dist/internal/engine.d.ts +4 -8
- package/dist/internal/engine.js +57 -84
- package/dist/internal/errors.d.ts +3 -3
- package/dist/internal/errors.js +1 -1
- package/dist/internal/file-coordinator.d.ts +17 -0
- package/dist/internal/file-coordinator.js +162 -0
- package/dist/internal/launch-request.d.ts +4 -4
- package/dist/internal/launch-request.js +2 -2
- package/dist/internal/logs.d.ts +1 -1
- package/dist/internal/run-log.d.ts +1 -1
- package/dist/internal/run-state.d.ts +11 -8
- package/dist/internal/run-state.js +34 -22
- package/dist/internal/run.d.ts +3 -23
- package/dist/internal/run.js +4 -50
- package/dist/internal/worker-directory.d.ts +1 -0
- package/dist/internal/worker-directory.js +26 -0
- package/dist/internal/workflow-registry.d.ts +35 -17
- package/dist/internal/workflow-registry.js +110 -73
- package/dist/internal/working-directory.d.ts +1 -0
- package/dist/internal/working-directory.js +9 -0
- package/dist/{plugin-loader.d.ts → workflow-loader.d.ts} +7 -8
- package/dist/workflow-loader.js +234 -0
- package/package.json +2 -2
- package/assets/docs/resources.md +0 -61
- package/assets/examples/coordinating-multiple-agents/queue-adapter.ts +0 -51
- package/assets/examples/worktree-development-loop/manifest.ts +0 -26
- package/assets/examples/worktree-development-loop/state.ts +0 -23
- package/assets/examples/worktree-development-loop/workflows/development-loop/declaration.ts +0 -8
- package/assets/examples/worktree-development-loop/workflows/implementation/declaration.ts +0 -8
- package/assets/examples/worktree-development-loop/workflows/planning/declaration.ts +0 -8
- package/assets/examples/worktree-development-loop/workflows/review/declaration.ts +0 -8
- package/assets/examples/worktree-development-loop/workflows/review-router/declaration.ts +0 -12
- package/assets/packages/cli/src/internal/artifacts.ts +0 -26
- package/assets/packages/cli/src/internal/resource-bindings.ts +0 -35
- package/assets/packages/cli/src/internal/run-resources.ts +0 -23
- package/assets/packages/cli/src/internal/state-store.ts +0 -83
- package/assets/packages/cli/src/plugin-loader.ts +0 -400
- package/assets/packages/cli/src/resources.ts +0 -69
- package/assets/packages/sdk/src/agent-resource-adapter.ts +0 -11
- package/assets/packages/sdk/src/resources.ts +0 -20
- package/assets/packages/sdk/src/state-adapter.ts +0 -75
- package/dist/internal/artifacts.d.ts +0 -10
- package/dist/internal/artifacts.js +0 -29
- package/dist/internal/resource-bindings.d.ts +0 -13
- package/dist/internal/resource-bindings.js +0 -34
- package/dist/internal/run-resources.d.ts +0 -6
- package/dist/internal/run-resources.js +0 -26
- package/dist/internal/state-store.d.ts +0 -23
- package/dist/internal/state-store.js +0 -103
- package/dist/plugin-loader.js +0 -341
- package/dist/resources.d.ts +0 -11
- package/dist/resources.js +0 -100
- /package/assets/packages/{sdk/src/files.ts → cli/src/internal/file-coordinator.ts} +0 -0
package/assets/README.md
CHANGED
|
@@ -9,39 +9,34 @@ through the CLI from any harness. Agents run on the bundled
|
|
|
9
9
|
|
|
10
10
|
1. [Install Norn](#installation), including agent authentication.
|
|
11
11
|
|
|
12
|
-
2. **Combine an agent with code.** The agent writes a summary; code saves it as
|
|
12
|
+
2. **Combine an agent with code.** The agent writes a summary; code saves it as a file.
|
|
13
13
|
|
|
14
14
|
```ts
|
|
15
|
-
import {
|
|
15
|
+
import { writeFile } from "node:fs/promises";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { workflow } from "@vimhead.dev/norn";
|
|
16
18
|
import { Type } from "typebox";
|
|
17
19
|
|
|
18
|
-
const
|
|
19
|
-
id: "summary",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
const summarize = workflow({
|
|
21
|
+
id: "summary.write",
|
|
22
|
+
isEntrypoint: true,
|
|
23
|
+
instructions: "Summarize supplied text and save the result.",
|
|
24
|
+
args: Type.Object({ text: Type.String() }),
|
|
25
|
+
async execute({ args, paths, run }) {
|
|
26
|
+
const summary = await run.agents.prompt({
|
|
27
|
+
label: "summarize",
|
|
28
|
+
cwd: paths.workspace,
|
|
29
|
+
tools: [],
|
|
30
|
+
prompt: `Summarize this text in one sentence:\n${args.text}`,
|
|
31
|
+
response: Type.Object({ text: Type.String() }),
|
|
32
|
+
});
|
|
33
|
+
const summaryPath = "summary.txt";
|
|
34
|
+
await writeFile(join(paths.workspace, summaryPath), summary.text);
|
|
35
|
+
return run.complete({ data: { summaryPath } });
|
|
26
36
|
},
|
|
27
37
|
});
|
|
28
38
|
|
|
29
|
-
export default
|
|
30
|
-
workflows: {
|
|
31
|
-
write: {
|
|
32
|
-
async execute(run, { text }) {
|
|
33
|
-
const summary = await run.agents.prompt({
|
|
34
|
-
label: "summarize",
|
|
35
|
-
tools: [],
|
|
36
|
-
prompt: `Summarize this text in one sentence:\n${text}`,
|
|
37
|
-
response: Type.Object({ text: Type.String() }),
|
|
38
|
-
});
|
|
39
|
-
const artifact = await run.artifacts.write("summary.txt", summary.text);
|
|
40
|
-
return run.complete({ artifacts: { summary: artifact } });
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
});
|
|
39
|
+
export default [summarize];
|
|
45
40
|
```
|
|
46
41
|
|
|
47
42
|
[Full example and project configuration](examples/getting-started/README.md)
|
|
@@ -49,7 +44,7 @@ through the CLI from any harness. Agents run on the bundled
|
|
|
49
44
|
3. **Run it** from the example directory:
|
|
50
45
|
|
|
51
46
|
```sh
|
|
52
|
-
printf '%s\n' '{"
|
|
47
|
+
printf '%s\n' '{"args":{"text":"Norn workflows combine agents and code. They run from any harness through the CLI."}}' \
|
|
53
48
|
| norn runs start summary.write
|
|
54
49
|
|
|
55
50
|
norn runs wait <run-id>
|
package/assets/docs/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Norn documentation
|
|
2
2
|
|
|
3
|
-
Norn capabilities are ordinary TypeScript
|
|
3
|
+
Norn capabilities are ordinary TypeScript workflows: an agent can write one during a task, register it in that project, exercise it, change it, and retain it for another caller. No generated project hierarchy or separate compilation step is required.
|
|
4
4
|
|
|
5
5
|
## Read by task
|
|
6
6
|
|
|
@@ -10,10 +10,10 @@ Norn capabilities are ordinary TypeScript plugins: an agent can write one during
|
|
|
10
10
|
| Define TypeBox schemas, constraints, or codecs | [TypeBox schemas](schemas.md) | — |
|
|
11
11
|
| Discover contracts or invoke Norn from another harness | [CLI and client](cli.md) | [Create → run → change](../examples/minimal-workflow/README.md) |
|
|
12
12
|
| Configure providers, models, and authentication for Norn agents | [Providers and authentication](providers.md) | — |
|
|
13
|
-
| Delegate work with explicit inputs and structured results | [Norn agents](agents.md) | [Norn agent → saved
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
| Retain evidence or choose a filesystem boundary | [
|
|
13
|
+
| Delegate work with explicit inputs and structured results | [Norn agents](agents.md) | [Norn agent → saved file → analysis](../examples/agent-then-analysis/README.md) |
|
|
14
|
+
| Supply tools or tool wrappers to agents | [Custom tools](agents.md#custom-tools) | [Explicit shared state](../examples/shared-state/README.md) |
|
|
15
|
+
| Persist application state or coordinate concurrent mutations | [Workflow-owned storage](persistence.md#workflow-owned-storage) | [Explicit shared state](../examples/shared-state/README.md), [Example-local work queue](../examples/coordinating-multiple-agents/README.md) |
|
|
16
|
+
| Retain evidence or choose a filesystem boundary | [Persistence, files, and workspaces](persistence.md) | [Norn agent → saved file → analysis](../examples/agent-then-analysis/README.md) |
|
|
17
17
|
| Reuse a workflow with a caller-selected continuation | [Composition](composition.md) | [Caller-selected continuation](../examples/caller-selected-continuation/README.md) |
|
|
18
18
|
| Repair a failed run without repeating earlier work | [Recovery and gates](recovery.md) | [Analysis-only repair](../examples/agent-then-analysis/README.md#repair-only-the-analysis-step) |
|
|
19
19
|
|
package/assets/docs/agents.md
CHANGED
|
@@ -2,18 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
A Norn agent is a workflow-managed session powered by the bundled, open-source and extensible [Pi coding agent](https://pi.dev). Pi supplies the agent implementation regardless of which [outer harness invokes Norn](cli.md#javascript-client-and-other-harnesses). Extensions, skills, and custom providers can customize these sessions; their loading and boundaries are described below.
|
|
4
4
|
|
|
5
|
-
The [Norn agent → saved
|
|
5
|
+
The [Norn agent → saved file → analysis example](../examples/agent-then-analysis/README.md) is a complete two-session application. Agent outputs flow through a saved contract, not shared conversation history.
|
|
6
|
+
|
|
7
|
+
## Authoring types
|
|
8
|
+
|
|
9
|
+
Import Pi types used by Norn directly from the SDK:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import type { CreateAgentSessionOptions, EventBus, PromptOptions, ToolDefinition } from "@vimhead.dev/norn";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
These are Pi's original types, not Norn-specific copies. Installing the SDK
|
|
16
|
+
installs its Pi dependency automatically; no separate Pi installation is needed.
|
|
6
17
|
|
|
7
18
|
## One prompt or a retained session
|
|
8
19
|
|
|
9
|
-
`run.agents.prompt({ label, prompt, response, ...sessionOptions })` creates a Pi session for one prompt and returns the value described by the response schema, including any codec transformations—not `{ response, raw }`. You do not need to dispose this one-prompt session. See [schema input/output types](schemas.md#codecs-and-inputoutput-types).
|
|
20
|
+
`run.agents.prompt({ label, cwd, prompt, response, ...sessionOptions })` creates a Pi session for one prompt and returns the value described by the response schema, including any codec transformations—not `{ response, raw }`. You do not need to dispose this one-prompt session. See [schema input/output types](schemas.md#codecs-and-inputoutput-types).
|
|
10
21
|
|
|
11
|
-
For follow-up turns in the same conversation:
|
|
22
|
+
Both session creation and one-prompt calls require an absolute `cwd`; choose from the workflow's [paths](persistence.md#filesystem-boundaries) or supply another prepared directory. For follow-up turns in the same conversation:
|
|
12
23
|
|
|
13
24
|
```ts
|
|
25
|
+
import { writeFile } from "node:fs/promises";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
|
|
14
28
|
const agentSession = await run.agents.createSession({
|
|
15
29
|
label: "implementation",
|
|
16
|
-
cwd:
|
|
30
|
+
cwd: paths.workspace,
|
|
17
31
|
tools: ["read", "bash", "edit", "write"],
|
|
18
32
|
});
|
|
19
33
|
try {
|
|
@@ -27,8 +41,9 @@ try {
|
|
|
27
41
|
response: verificationSchema,
|
|
28
42
|
maxAttempts: 2,
|
|
29
43
|
});
|
|
30
|
-
const
|
|
31
|
-
|
|
44
|
+
const verificationPath = join(paths.workspace, "verification.json");
|
|
45
|
+
await writeFile(verificationPath, JSON.stringify(verification));
|
|
46
|
+
return run.complete({ data: { verificationPath } });
|
|
32
47
|
} finally {
|
|
33
48
|
await agentSession.dispose();
|
|
34
49
|
}
|
|
@@ -46,11 +61,35 @@ Successful results and raw attempts are written under `current/logs/agents/`; Pi
|
|
|
46
61
|
|---|---|---|
|
|
47
62
|
| IF later work needs independent judgment, THEN create a fresh session and pass only its input/evidence contract. ELSE retain a session for conversation-dependent follow-up. | Analysis receives saved source and draft, not the author's conversation. | Call an author again and describe its self-review as independent. |
|
|
48
63
|
| IF a Norn agent claims a verifiable result, THEN verify the evidence before accepting it. ELSE preserve the uncertainty in the result. | Check quotations against source bytes and command outcomes against logs. | Treat a schema-valid `passed: true` as proof that tests ran. |
|
|
49
|
-
| IF a result must survive a workflow transition, THEN save its content/ref using [persistence](persistence.md). ELSE keep it local to the active step. | Save a draft
|
|
64
|
+
| IF a result must survive a workflow transition, THEN save its content/ref using [persistence](persistence.md). ELSE keep it local to the active step. | Save a draft file, then pass its path to analysis. | Expect the next workflow to recover a local variable or an undisposed session object. |
|
|
50
65
|
|
|
51
|
-
##
|
|
66
|
+
## Custom tools
|
|
67
|
+
|
|
68
|
+
Both session creation and one-shot prompting accept Pi `ToolDefinition` objects through `customTools`. Each definition supplies a name, description, parameter schema, and execution function. Tools can close over files, services, or author-owned storage handles. The [state tools](../examples/shared-state/state-tools.ts) and [queue tools](../examples/coordinating-multiple-agents/queue-tools.ts) are complete example-owned factories.
|
|
69
|
+
|
|
70
|
+
`customTools` registers definitions; an explicit `tools` array selects enabled names across built-in, custom, and loaded extension tools. The response tool is always included. `tools: []` requests only that response tool, even when custom definitions are supplied. Omitting `tools` uses Pi's configured default tools (`read`, `bash`, `edit`, `write` when unconfigured), plus custom and extension tools.
|
|
52
71
|
|
|
53
|
-
|
|
72
|
+
```ts
|
|
73
|
+
const result = await run.agents.prompt({
|
|
74
|
+
label: "lookup",
|
|
75
|
+
cwd: paths.workspace,
|
|
76
|
+
customTools: [lookupTool],
|
|
77
|
+
tools: ["read", lookupTool.name],
|
|
78
|
+
prompt: "Look up the requested information and summarize it.",
|
|
79
|
+
response: Type.Object({ summary: Type.String() }),
|
|
80
|
+
});
|
|
81
|
+
return run.complete({ summary: result.summary });
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`lookupTool` is an author-provided `ToolDefinition` in this fragment. Custom tool names must be unique and must not collide with built-ins, the response tool, or already-loaded extension tools. Authors own tool dependencies and their cleanup, including when session creation fails; closing an agent does not close a database or delete stored data captured by its tools.
|
|
85
|
+
|
|
86
|
+
| Decision | GOOD | BAD |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| IF supplying an explicit `tools` list, THEN include each custom or extension tool name the agent needs. ELSE Pi's default selection applies. | Register `lookupTool` and select `lookupTool.name`. | Expect `customTools: [lookupTool]` to bypass `tools: []`. |
|
|
89
|
+
| IF tool closures contain per-agent state, THEN create fresh definitions for each agent. ELSE shared definitions can use a shared dependency. | Create queue tools separately for each claim owner. | Reuse one owner's closures across competing workers. |
|
|
90
|
+
| IF tool dependencies need cleanup, THEN retain ownership with `try/finally` around session creation and use. ELSE no cleanup wrapper is necessary. | Close an author-opened connection after the agent finishes or fails. | Expect a tool definition to provide automatic connection disposal. |
|
|
91
|
+
|
|
92
|
+
## Prompts, tools, and resource loading
|
|
54
93
|
|
|
55
94
|
Each session loads resources for its `cwd` and [Norn configuration](providers.md#norn-configuration). Installed provider extensions register before default-model selection. Both `run.agents.createSession` and `run.agents.prompt` accept per-session `model` and `thinkingLevel` overrides; omitted values use Pi's configured selection and defaults. Discoverable settings, skills, context files, and extensions can therefore affect it. It does **not** inherit the outer conversation or its in-memory tool registrations. Loaded extensions may change active tools; the requested tool list alone is not an adversarial restriction.
|
|
56
95
|
|
package/assets/docs/cli.md
CHANGED
|
@@ -108,7 +108,7 @@ norn commands inspect runs.start
|
|
|
108
108
|
norn help runs start
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
Default workflow listing shows entrypoints; `--all` includes internal steps. Workflow inspection returns instructions,
|
|
111
|
+
Default workflow listing shows entrypoints; `--all` includes internal steps. Workflow inspection returns instructions, args JSON Schema, gate metadata, workflow/scope configuration schemas and keys, and registration source locations. [Loading diagnostics](projects.md#diagnose-registration) are part of the discovery envelope.
|
|
112
112
|
|
|
113
113
|
Help is text; ordinary results are JSON. `runs logs` emits JSONL events.
|
|
114
114
|
`norn pi [arguments...]` is a passthrough to bundled Pi, preserving Pi's native
|
|
@@ -121,7 +121,7 @@ Commands and schemas from the invoked executable are authoritative when a checko
|
|
|
121
121
|
From inside the target project:
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
|
-
printf '%s\n' '{"
|
|
124
|
+
printf '%s\n' '{"args":{"name":"Ada"}}' | norn runs start greeting.write
|
|
125
125
|
norn runs wait <run>
|
|
126
126
|
norn runs inspect <run>
|
|
127
127
|
norn runs metrics <run>
|
|
@@ -129,13 +129,13 @@ norn runs metrics <run>
|
|
|
129
129
|
|
|
130
130
|
Start returns `{ "run": ... }` with `id`, `name`, and `path`, after launching a detached executor. This is acceptance of the launch, not success of the task. `runs wait` returns when the run is no longer running or inspection reports it unhealthy. Its successful process exit does not mean the workflow completed; callers check `run.status`, `run.health`, and outcome/failure information.
|
|
131
131
|
|
|
132
|
-
A completed capability's outputs are in `run.outcome.metadata
|
|
132
|
+
Run results expose `run.paths.project` and `run.paths.workspace` as absolute directories. `run.path` identifies the complete run storage directory, not the workspace. A completed capability's outputs are in `run.outcome.metadata`; file paths in `data` follow that workflow's declared convention. The [minimal example](../examples/minimal-workflow/README.md) returns a `greetingPath` relative to `run.paths.workspace`.
|
|
133
133
|
|
|
134
|
-
Start stdin accepts `
|
|
134
|
+
Start stdin accepts `args` and optional `config`, with config overrides keyed independently by workflow ID or scope ID. Args are JSON, not CLI flags or TOON. For display, a JSON viewer can format a finite result; keep machine artifacts and JSONL events in their native format.
|
|
135
135
|
|
|
136
136
|
| Decision | GOOD | BAD |
|
|
137
137
|
|---|---|---|
|
|
138
|
-
| IF start returns a run ID, THEN retain it and inspect the terminal outcome. ELSE handle the launch error. | Wait, then verify `status === "completed"` and expected
|
|
138
|
+
| IF start returns a run ID, THEN retain it and inspect the terminal outcome. ELSE handle the launch error. | Wait, then verify `status === "completed"` and expected file content. | Report task success from `runs start` alone. |
|
|
139
139
|
| IF a new capability is written or registered, THEN query the current catalogue and schema. ELSE use the inspected contract. | `workflows inspect greeting.write` after editing. | Rely on a cached session-start list that cannot contain the new workflow. |
|
|
140
140
|
|
|
141
141
|
For live monitoring and explicit lifecycle control:
|
|
@@ -167,7 +167,7 @@ import { createNornClient } from "@vimhead.dev/norn-cli/client";
|
|
|
167
167
|
const client = createNornClient({ spawnCwd: "/absolute/path/to/project" });
|
|
168
168
|
const started = await client.runs.start({
|
|
169
169
|
workflowId: "greeting.write",
|
|
170
|
-
|
|
170
|
+
args: { name: "Ada" },
|
|
171
171
|
});
|
|
172
172
|
const finished = await client.runs.wait(started.id);
|
|
173
173
|
if (finished.status !== "completed" || finished.health !== "healthy") {
|
|
@@ -178,6 +178,6 @@ console.log(finished.outcome?.metadata);
|
|
|
178
178
|
|
|
179
179
|
The client defaults to its own package's `bin/norn.mjs`. Its optional `executablePath` is a script launched through `process.execPath`, not an arbitrary standalone binary or shell command. Other languages can invoke the CLI directly with cwd, JSON stdin, and parsed stdout.
|
|
180
180
|
|
|
181
|
-
`workflows.list()` and `inspect()` use fresh
|
|
181
|
+
`workflows.list()` and `inspect()` use fresh discovery. `workflows.entries()` retains its loaded catalogue; create a new client to refresh those entries after source edits.
|
|
182
182
|
|
|
183
183
|
Sources: [CLI declarations and handlers](../packages/cli/src/cli.ts), [client API](../packages/cli/src/client.ts).
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
## Transfer, not a returning call
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
return
|
|
6
|
+
return analyze({ draftPath });
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
Return a workflow call to select the next step in the same run. Supply its complete input; TypeScript checks it against the declaration's
|
|
9
|
+
Return a workflow call to select the next step in the same run. Supply its complete input; TypeScript checks it against the declaration's args schema. The target must be registered in the loaded project.
|
|
10
10
|
|
|
11
|
-
This transfers control rather than calling a subroutine: awaiting the declaration does not execute the target or return its eventual result. Steps share
|
|
11
|
+
This transfers control rather than calling a subroutine: awaiting the declaration does not execute the target or return its eventual result. Steps share workspace files, not local variables or agent conversations. `run.complete` completes the whole run.
|
|
12
12
|
|
|
13
|
-
For a dynamically selected string ID, use `return run.next(workflowId,
|
|
13
|
+
For a dynamically selected string ID, use `return run.next(workflowId, args)`. The selected target checks its input at runtime. `run.next` accepts IDs, not declarations or reference functions.
|
|
14
14
|
|
|
15
15
|
## Caller-selected workflow reference
|
|
16
16
|
|
|
@@ -18,18 +18,18 @@ The [caller-selected continuation example](../examples/caller-selected-continuat
|
|
|
18
18
|
runs a producer with either of two caller-selected consumers, forwarding caller
|
|
19
19
|
context alongside the producer's results. It needs no model or credentials.
|
|
20
20
|
|
|
21
|
-
A reusable capability can accept a workflow reference whose schema describes the values it contributes. The caller supplies the target and captures the remaining
|
|
21
|
+
A reusable capability can accept a workflow reference whose schema describes the values it contributes. The caller supplies the target and captures the remaining args:
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
-
import {
|
|
24
|
+
import { workflowRefSchema } from "@vimhead.dev/norn";
|
|
25
25
|
import { Type } from "typebox";
|
|
26
26
|
|
|
27
|
-
const
|
|
27
|
+
const argsSchema = Type.Object({
|
|
28
28
|
task: Type.String(),
|
|
29
29
|
next: Type.Union([
|
|
30
30
|
workflowRefSchema({
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
args: Type.Object({
|
|
32
|
+
resultPath: Type.String(),
|
|
33
33
|
summary: Type.String(),
|
|
34
34
|
}),
|
|
35
35
|
}),
|
|
@@ -42,33 +42,33 @@ A caller supplies the target and its own parameters:
|
|
|
42
42
|
|
|
43
43
|
```json
|
|
44
44
|
{
|
|
45
|
-
"
|
|
45
|
+
"args": {
|
|
46
46
|
"task": "Assess this import",
|
|
47
47
|
"next": {
|
|
48
48
|
"workflow": "importer.deliver",
|
|
49
|
-
"
|
|
49
|
+
"forwardArgs": { "batchId": "batch-17" }
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
Code uses a declaration's `.id` in the reference payload, not the declaration itself. A bare ID string is shorthand for an object reference with empty `
|
|
55
|
+
Code uses a declaration's `.id` in the reference payload, not the declaration itself. A bare ID string is shorthand for an object reference with empty `forwardArgs`.
|
|
56
56
|
|
|
57
|
-
Inside the workflow, `
|
|
57
|
+
Inside the workflow, `args.next` is a function. Supply only the result fields declared above:
|
|
58
58
|
|
|
59
59
|
```ts
|
|
60
|
-
return
|
|
61
|
-
?
|
|
62
|
-
: run.complete({ summary,
|
|
60
|
+
return args.next
|
|
61
|
+
? args.next({ resultPath, summary })
|
|
62
|
+
: run.complete({ summary, data: { resultPath } });
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
`importer.deliver` receives `batchId` from the caller plus `
|
|
65
|
+
`importer.deliver` receives `batchId` from the caller plus `resultPath` and `summary` from the producer. Its args schema must accept all three. Produced fields replace caller fields with the same name; nested objects are replaced, not deep-merged.
|
|
66
66
|
|
|
67
67
|
Contributions must be JSON objects matching the declared input type. Object-valued records, unions, intersections and codecs are supported. With codecs, supply `StaticEncode` values, just as for a direct workflow call—not transformed `StaticDecode` values.
|
|
68
68
|
|
|
69
|
-
`workflows inspect` shows the contribution contract under `x-norn-workflow-ref.
|
|
69
|
+
`workflows inspect` shows the contribution contract under `x-norn-workflow-ref.contributedArgsSchema`. Use it alongside the target's args schema to check that the combined input fits.
|
|
70
70
|
|
|
71
|
-
When passing a reference as input to another workflow, supply its JSON form shown above, not the function received in `
|
|
71
|
+
When passing a reference as input to another workflow, supply its JSON form shown above, not the function received in `args.next`.
|
|
72
72
|
|
|
73
73
|
## Multiple outcomes and direct targets
|
|
74
74
|
|
|
@@ -77,21 +77,21 @@ References can be nested under ordinary author-selected names with independent c
|
|
|
77
77
|
```ts
|
|
78
78
|
const next = Type.Object({
|
|
79
79
|
success: workflowRefSchema({
|
|
80
|
-
|
|
80
|
+
args: Type.Object({ resultPath: Type.String() }),
|
|
81
81
|
}),
|
|
82
82
|
failure: workflowRefSchema({
|
|
83
|
-
|
|
83
|
+
args: Type.Object({ reason: Type.String() }),
|
|
84
84
|
}),
|
|
85
85
|
});
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
An implementation can return `
|
|
88
|
+
An implementation can return `args.next.success({ resultPath })`, `args.next.failure({ reason })`, or select its own known target with `manualReviewWorkflow({ task, reason })`. A dynamic target still uses `run.next(selectedId, input)`.
|
|
89
89
|
|
|
90
90
|
These are alternative transitions, not fan-out. `success` and `failure` are not reserved names, and a failure reference does not catch unhandled exceptions automatically.
|
|
91
91
|
|
|
92
92
|
| Decision | GOOD | BAD |
|
|
93
93
|
|---|---|---|
|
|
94
|
-
| IF the caller selects the next step, THEN invoke its reference with the declared contribution. ELSE call a known declaration or use a dynamic ID. | `
|
|
94
|
+
| IF the caller selects the next step, THEN invoke its reference with the declared contribution. ELSE call a known declaration or use a dynamic ID. | `args.next({ resultPath })` | Manually reconstruct captured forwarding input. |
|
|
95
95
|
| IF additional caller work follows the result, THEN represent it as the supplied reference. ELSE complete the run. | `assess → caller.deliver` | Expect execution to return to the line following a workflow call. |
|
|
96
96
|
| IF a target schema changes, THEN exercise the assembled input contract. ELSE preserve its existing input contract. | Verify the target accepts captured context and contributed results. | Treat contribution metadata as end-to-end compatibility proof. |
|
|
97
97
|
|
|
@@ -99,8 +99,8 @@ The [worktree development loop](../examples/worktree-development-loop/README.md)
|
|
|
99
99
|
|
|
100
100
|
## Another project or harness
|
|
101
101
|
|
|
102
|
-
Reuse source by explicitly registering it, directly or through [included config](projects.md). There is no required package layout.
|
|
102
|
+
Reuse source by explicitly registering it, directly or through [included config](projects.md). There is no required package layout. Workflow IDs must remain unique within a project; shared scopes follow the [scope declaration contract](workflows.md#shared-scopes-and-configuration). Resources and workspace files belong to the invoking run, not the workflow source directory.
|
|
103
103
|
|
|
104
|
-
An external shell, Python program, or agent harness can call the [CLI](cli.md) from the target project directory. The JavaScript client offers the same lifecycle without inventing another orchestration layer. Separate CLI starts create separate runs; connecting their
|
|
104
|
+
An external shell, Python program, or agent harness can call the [CLI](cli.md) from the target project directory. The JavaScript client offers the same lifecycle without inventing another orchestration layer. Separate CLI starts create separate runs; connecting their files is a caller responsibility. Relative paths must use the base declared by the producing workflow; see [file persistence](persistence.md).
|
|
105
105
|
|
|
106
106
|
Sources: [reference schemas and controls](../packages/sdk/src/api.ts), [scheduler](../packages/cli/src/internal/engine.ts), [reference contract tests](../tests/workflow-ref.test.ts).
|
|
@@ -1,26 +1,34 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Persistence, files, and workspaces
|
|
2
2
|
|
|
3
3
|
## Choose what survives
|
|
4
4
|
|
|
5
5
|
| Value | Lifetime and access |
|
|
6
6
|
|---|---|
|
|
7
|
-
| Local variables /
|
|
8
|
-
|
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
| `run.artifacts` | Text files addressed by `{ path }` relative to this run's artifacts directory. Write content, pass the ref, read and validate at the consumer. |
|
|
12
|
-
| Outcome metadata | Caller-facing summary, artifact/log refs and small data, exposed by run inspection. |
|
|
13
|
-
| Workflow params | Explicit input to the current/next step, persisted for recovery. |
|
|
7
|
+
| Local variables / module memory | Current invocation or executor only; not a resume contract. |
|
|
8
|
+
| Workspace files | Ordinary files under `paths.workspace`, saved in checkpoints and restored on rollback. |
|
|
9
|
+
| Outcome metadata | Caller-facing summary, log refs and workflow-defined `data`, exposed by run inspection. |
|
|
10
|
+
| Workflow args | Explicit input to the current/next step, persisted for recovery. |
|
|
14
11
|
|
|
15
|
-
|
|
12
|
+
Use arguments for step inputs and workspace files for retained content. The [shared-state example](../examples/shared-state/README.md) owns a SQLite store in its workspace. The [agent example](../examples/agent-then-analysis/plugin.ts) writes a JSON file with ordinary filesystem APIs and passes its path to analysis.
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
File names, formats, and path conventions belong to the workflow. Return relevant paths in outcome `data`; declare whether they are absolute or relative and, for relative paths, their base. Norn does not interpret arbitrary strings in args or outcomes as paths. A JSON consumer still needs parsing and schema validation.
|
|
18
15
|
|
|
19
16
|
| Decision | GOOD | BAD |
|
|
20
17
|
|---|---|---|
|
|
21
18
|
| IF earlier work must survive retry of a later step, THEN persist it before a transition and recover from that boundary. ELSE expect the active step to be repeated. | Save assessments, transition to delivery, retry delivery. | Keep assessments in a closure and restart the entire coordinator. |
|
|
22
|
-
| IF evidence must remain distinguishable across attempts, THEN use distinct
|
|
23
|
-
| IF a
|
|
19
|
+
| IF evidence must remain distinguishable across attempts, THEN use distinct file paths or retain the relevant checkpoint. ELSE document intentional replacement. | `attempt-2/analysis.json`. | Overwrite `analysis.json` while promising both revisions remain in the current files. |
|
|
20
|
+
| IF a consumer receives a relative file path, THEN resolve it against the base declared by the workflow. ELSE use the absolute path directly. | Resolve a workspace-relative `draftPath` against `run.paths.workspace` from inspection. | Resolve it against the caller's cwd or the run storage root. |
|
|
21
|
+
|
|
22
|
+
## Workflow-owned storage
|
|
23
|
+
|
|
24
|
+
Workflows can use ordinary filesystem APIs or a storage library. Storage formats, initialization, validation, and concurrency belong to that application code. The [shared-state](../examples/shared-state/README.md) and [work-queue](../examples/coordinating-multiple-agents/README.md) examples use SQLite through `node:sqlite`, without a separate dependency installation.
|
|
25
|
+
|
|
26
|
+
Finish writers and close database connections before returning a transition. Checkpoints preserve files, not live connections or closures; later steps reopen storage from `paths.workspace`. Stop all users of a store before rollback. An external database is not restored by a workspace checkpoint.
|
|
27
|
+
|
|
28
|
+
| Decision | GOOD | BAD |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| IF agents mutate shared data concurrently, THEN use storage transactions or serialize the complete mutation. ELSE ordinary independent file writes can suffice. | Claim and acknowledge queue work transactionally. | Read the same JSON file in two agents and overwrite each other's changes. |
|
|
31
|
+
| IF returning a transition after database work, THEN commit writes and close owned handles before returning. ELSE the workspace may not contain a consistent recoverable database. | Close the SQLite store in `finally`. | Leave writers running while the next step begins. |
|
|
24
32
|
|
|
25
33
|
## Filesystem boundaries
|
|
26
34
|
|
|
@@ -29,30 +37,33 @@ Each run is stored under `<project>/.norn/runs/<id>/`:
|
|
|
29
37
|
```text
|
|
30
38
|
current/
|
|
31
39
|
workspace/ working files
|
|
32
|
-
artifacts/ capability evidence and results
|
|
33
|
-
resources/ resource definitions and data
|
|
34
|
-
state.json workflow state values
|
|
35
40
|
run-state.json scheduler state
|
|
36
41
|
manifest.json recorded events
|
|
37
42
|
logs/ command and agent output
|
|
38
43
|
sessions/ Pi conversations
|
|
39
44
|
checkpoints.json
|
|
40
|
-
locks/
|
|
45
|
+
locks/ runtime locks; not snapshotted
|
|
41
46
|
store/ snapshot manifests and content-addressed objects
|
|
42
47
|
```
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
Every workflow and gate description receives `paths`:
|
|
50
|
+
|
|
51
|
+
| Path | Directory | Checkpoint and rollback behavior |
|
|
45
52
|
|---|---|---|
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
53
|
+
| `paths.project` | Absolute root of the loaded project | Project edits are excluded. |
|
|
54
|
+
| `paths.workspace` | Absolute, initially empty run workspace | Workspace files are saved in checkpoints and restored on rollback. |
|
|
55
|
+
|
|
56
|
+
Run start, list, inspect, and wait results expose these same directories under `run.paths`. The separate `run.path` is the storage root, not the workspace. These locations remain discoverable for interrupted and failed runs as well as completed ones.
|
|
57
|
+
|
|
58
|
+
Use ordinary path utilities to address files or subdirectories. The workspace is not a checkout or copy of the project. Commands and agents require an explicit absolute `cwd`, such as `paths.project`, `paths.workspace`, or a prepared subdirectory.
|
|
48
59
|
|
|
49
|
-
|
|
60
|
+
The dedicated run worker uses an empty, read-only cwd to guard against accidental relative writes to the project. This is not a security sandbox: enforcement depends on filesystem permissions and process privileges. Explicit project paths and other external locations remain accessible.
|
|
50
61
|
|
|
51
62
|
| Decision | GOOD | BAD |
|
|
52
63
|
|---|---|---|
|
|
53
|
-
| IF work needs existing project files, THEN
|
|
54
|
-
| IF rollback must undo a change, THEN keep it in snapshotted run files or separately manage the external effect. ELSE do not promise rollback of that change. | Reconcile a project-root edit or remote delivery explicitly. | Assume snapshots restore project
|
|
64
|
+
| IF work needs existing project files, THEN use `paths.project` or explicitly prepare a copy/worktree inside `paths.workspace`. ELSE use the empty run workspace. | A verifier chooses `cwd: paths.project`; an editing workflow prepares its own worktree. | Run `npm test` in an empty workspace and assume the repository is present. |
|
|
65
|
+
| IF rollback must undo a change, THEN keep it in snapshotted run files or separately manage the external effect. ELSE do not promise rollback of that change. | Reconcile a project-root edit or remote delivery explicitly. | Assume snapshots restore project workflow source, remote APIs, or symlink targets. |
|
|
55
66
|
|
|
56
67
|
Snapshots cover `current/`, preserve symlinks as links rather than copying targets, and do not include project-root source. [Recovery](recovery.md) defines when snapshots are taken and how to select a retry boundary.
|
|
57
68
|
|
|
58
|
-
Sources: [
|
|
69
|
+
Sources: [public path and outcome types](../packages/sdk/src/api.ts), [snapshot store](../packages/cli/src/internal/run-store.ts).
|
package/assets/docs/projects.md
CHANGED
|
@@ -8,44 +8,54 @@ norn project init
|
|
|
8
8
|
|
|
9
9
|
Initialization creates `norn.project.json`, `.norn/runs/`, and a run-state exclusion in `.gitignore`. Project discovery walks upward from the invocation directory to the nearest `norn.project.json`.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Register workflow modules explicitly:
|
|
12
12
|
|
|
13
13
|
```json
|
|
14
14
|
{
|
|
15
15
|
"version": 1,
|
|
16
|
-
"
|
|
17
|
-
"config": {
|
|
18
|
-
"example": { "repositoryRoot": "." }
|
|
19
|
-
}
|
|
16
|
+
"workflows": ["./workflows/index.ts"]
|
|
20
17
|
}
|
|
21
18
|
```
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
Each module default-exports an array of complete [workflow definitions](workflows.md):
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
```ts
|
|
23
|
+
import { summarize } from "./summarize.ts";
|
|
24
|
+
import { save } from "./save.ts";
|
|
25
|
+
|
|
26
|
+
export default [summarize, save];
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Arrays may contain standalone workflows and workflows from multiple scopes. Only array entries are registered; importing or calling a target does not register it. Include internal transition targets as well as entrypoints. The [minimal example](../examples/minimal-workflow/README.md) needs only its project file and workflow module.
|
|
30
|
+
|
|
31
|
+
The optional `config` object contains independently keyed [workflow and scope configuration](workflows.md#shared-scopes-and-configuration). Omit entries for owners without a config schema.
|
|
32
|
+
|
|
33
|
+
Reusable config files, conventionally `norn.json`, can declare `workflows`, `includes`, and `config`:
|
|
26
34
|
|
|
27
35
|
```json
|
|
28
36
|
{
|
|
29
37
|
"version": 1,
|
|
30
|
-
"
|
|
38
|
+
"workflows": ["./local-workflows.ts"],
|
|
31
39
|
"includes": ["./packages/*/norn.json"]
|
|
32
40
|
}
|
|
33
41
|
```
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
Workflow and include paths resolve relative to the file declaring them. `*` matches one directory segment. There is no automatic workflow tree scan or inclusion of a sibling `norn.json`. Project config overrides included values; conflicting reusable values are rejected. `version` belongs only in the project file.
|
|
44
|
+
|
|
45
|
+
Workflow IDs must be unique. Workflows can share a scope across modules by importing one scope definition; independent declarations of the same scope ID conflict.
|
|
36
46
|
|
|
37
47
|
## Import and reload
|
|
38
48
|
|
|
39
|
-
|
|
49
|
+
TypeScript modules need no local build. Runtime imports are supplied for `@vimhead.dev/norn`, its `/files` and `/schema` subpaths, `typebox`, `typebox/value`, `typebox/compile`, and `typebox/schema`. Other dependencies need normal package resolution from the workflow module's location.
|
|
40
50
|
|
|
41
|
-
Runtime
|
|
51
|
+
Runtime imports do not configure TypeScript or an editor. A matching `@vimhead.dev/norn` installation provides SDK types; the source checkout's examples are checked by its `tsconfig.json`. A successful runtime import alone is not a type check.
|
|
42
52
|
|
|
43
|
-
New CLI discovery/start/resume invocations load current source; an already executing workflow retains its loaded
|
|
53
|
+
New CLI discovery/start/resume invocations load current source; an already executing workflow retains its loaded definition. Discovery does not invoke workflow execution or gate descriptions. Module-level code still executes during import.
|
|
44
54
|
|
|
45
55
|
| Decision | GOOD | BAD |
|
|
46
56
|
|---|---|---|
|
|
47
|
-
| IF source changes, THEN inspect it through a new invocation before starting or resuming. ELSE use the inspected
|
|
48
|
-
| IF importing a
|
|
57
|
+
| IF source changes, THEN inspect it through a new invocation before starting or resuming. ELSE use the inspected definition. | Edit a workflow, inspect it, then resume. | Assume a running executor hot-reloads edits. |
|
|
58
|
+
| IF importing a module can mutate files or start work, THEN move those effects into workflow execution. ELSE keep import-time definitions. | `execute` launches the command. | `workflows list` starts a delivery from top-level code. |
|
|
49
59
|
|
|
50
60
|
## Diagnose registration
|
|
51
61
|
|
|
@@ -55,12 +65,14 @@ norn workflows list --all
|
|
|
55
65
|
norn workflows inspect example.plan
|
|
56
66
|
```
|
|
57
67
|
|
|
58
|
-
Discovery returns `isComplete` and `diagnostics
|
|
68
|
+
Discovery returns `isComplete` and `diagnostics`, with source paths, stage, message, and schema issues when available. An invalid registration module is excluded as a whole; conflicting workflow IDs or scope declarations exclude the conflicting modules. `import` covers module evaluation as well as syntax/import errors.
|
|
69
|
+
|
|
70
|
+
Workflow inspection exposes argument and configuration schemas, separate workflow/scope config keys, and the registration module and declaring configuration file. The registration module is not necessarily the file containing the implementation.
|
|
59
71
|
|
|
60
|
-
Discovery can exit successfully with an incomplete catalogue. Start, resume, and executable client entries require the entire project to load; otherwise they report `NORN_PROJECT_INVALID`. Malformed project/include configuration
|
|
72
|
+
Discovery can exit successfully with an incomplete catalogue. Start, resume, and executable client entries require the entire project to load; otherwise they report `NORN_PROJECT_INVALID`. Malformed project/include configuration is fatal rather than producing a partial catalogue.
|
|
61
73
|
|
|
62
74
|
| Decision | GOOD | BAD |
|
|
63
75
|
|---|---|---|
|
|
64
|
-
| IF `isComplete` is false, THEN repair or explicitly remove the
|
|
76
|
+
| IF `isComplete` is false, THEN repair or explicitly remove the invalid registration and inspect again. ELSE select from the loaded contracts. | Fix the named config field or default export. | Launch a valid sibling from an incomplete project. |
|
|
65
77
|
|
|
66
|
-
|
|
78
|
+
Next: [write a workflow](workflows.md), [reuse across projects](composition.md).
|
package/assets/docs/providers.md
CHANGED
|
@@ -46,7 +46,7 @@ Finding a configured key or listing a model is not proof that a provider accepts
|
|
|
46
46
|
|
|
47
47
|
## Third-party provider packages
|
|
48
48
|
|
|
49
|
-
Pi provider extensions are separate from Norn workflow
|
|
49
|
+
Pi provider extensions are separate from Norn workflow modules and outer-harness
|
|
50
50
|
adapters. They register providers through Pi's APIs; do not put them in
|
|
51
51
|
`norn.project.json` or install them only in Cursor's plugin marketplace.
|
|
52
52
|
|
|
@@ -83,8 +83,8 @@ with `/model`. A newly started session reloads the provider; its model listing c
|
|
|
83
83
|
contain fallback models even without working credentials.
|
|
84
84
|
|
|
85
85
|
Keep the provider's **local runtime and Pi tool bridge enabled** for Norn agents.
|
|
86
|
-
Norn requires its structured-response tool, and
|
|
87
|
-
|
|
86
|
+
Norn requires its structured-response tool, and workflow-supplied custom tools use
|
|
87
|
+
the same bridge. The provider's cloud mode does not expose that local bridge. Cursor-native
|
|
88
88
|
tools are a separate surface: restricting Norn's `tools` list does not disable
|
|
89
89
|
Cursor's own tools or ambient configuration. See the package's documentation for
|
|
90
90
|
its runtime and isolation controls.
|