nawabari 0.9.2 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +142 -803
- package/dist/cli-command-registry.js +46 -6
- package/dist/cli-command-registry.js.map +1 -1
- package/dist/cli.d.ts +5 -3
- package/dist/cli.js +157 -34
- package/dist/cli.js.map +1 -1
- package/dist/contract.js +11 -3
- package/dist/contract.js.map +1 -1
- package/dist/domain/compatibility-runtime-projection.d.ts +24 -0
- package/dist/domain/compatibility-runtime-projection.js +197 -0
- package/dist/domain/compatibility-runtime-projection.js.map +1 -0
- package/dist/domain/doctor.d.ts +2 -2
- package/dist/domain/doctor.js +72 -51
- package/dist/domain/doctor.js.map +1 -1
- package/dist/domain/errors.d.ts +1 -1
- package/dist/domain/errors.js +5 -1
- package/dist/domain/errors.js.map +1 -1
- package/dist/domain/fhs-development-runtime.d.ts +90 -0
- package/dist/domain/fhs-development-runtime.js +385 -0
- package/dist/domain/fhs-development-runtime.js.map +1 -0
- package/dist/domain/fhs-runtime.d.ts +36 -0
- package/dist/domain/fhs-runtime.js +776 -0
- package/dist/domain/fhs-runtime.js.map +1 -0
- package/dist/domain/landlock.d.ts +11 -4
- package/dist/domain/landlock.js +44 -21
- package/dist/domain/landlock.js.map +1 -1
- package/dist/domain/nix-runtime-closure.d.ts +70 -0
- package/dist/domain/nix-runtime-closure.js +449 -0
- package/dist/domain/nix-runtime-closure.js.map +1 -0
- package/dist/domain/pnpm-middleware-backend-materialization.d.ts +117 -0
- package/dist/domain/pnpm-middleware-backend-materialization.js +311 -0
- package/dist/domain/pnpm-middleware-backend-materialization.js.map +1 -0
- package/dist/domain/runtime-executable-projection.d.ts +33 -0
- package/dist/domain/runtime-executable-projection.js +204 -0
- package/dist/domain/runtime-executable-projection.js.map +1 -0
- package/dist/domain/runtime-file-identity.d.ts +37 -0
- package/dist/domain/runtime-file-identity.js +114 -0
- package/dist/domain/runtime-file-identity.js.map +1 -0
- package/dist/domain/runtime-profile.d.ts +66 -0
- package/dist/domain/runtime-profile.js +356 -0
- package/dist/domain/runtime-profile.js.map +1 -0
- package/dist/domain/runtime-projection.d.ts +101 -0
- package/dist/domain/runtime-projection.js +316 -0
- package/dist/domain/runtime-projection.js.map +1 -0
- package/dist/domain/runtime-provider-pnpm-middleware.d.ts +41 -0
- package/dist/domain/runtime-provider-pnpm-middleware.js +316 -0
- package/dist/domain/runtime-provider-pnpm-middleware.js.map +1 -0
- package/dist/domain/runtime-provider-tgrep.d.ts +60 -0
- package/dist/domain/runtime-provider-tgrep.js +537 -0
- package/dist/domain/runtime-provider-tgrep.js.map +1 -0
- package/dist/domain/runtime-resolution.d.ts +57 -0
- package/dist/domain/runtime-resolution.js +242 -0
- package/dist/domain/runtime-resolution.js.map +1 -0
- package/dist/domain/sandbox-launcher.d.ts +7 -0
- package/dist/domain/sandbox-launcher.js +380 -56
- package/dist/domain/sandbox-launcher.js.map +1 -1
- package/dist/domain/sandbox.d.ts +59 -4
- package/dist/domain/sandbox.js +100 -5
- package/dist/domain/sandbox.js.map +1 -1
- package/dist/domain/session-backend.js +20 -1
- package/dist/domain/session-backend.js.map +1 -1
- package/dist/domain/session.d.ts +3 -2
- package/dist/domain/session.js.map +1 -1
- package/dist/domain/tgrep-runtime-materialization.d.ts +61 -0
- package/dist/domain/tgrep-runtime-materialization.js +172 -0
- package/dist/domain/tgrep-runtime-materialization.js.map +1 -0
- package/dist/operation-authorization.d.ts +10 -0
- package/dist/operation-authorization.js +12 -1
- package/dist/operation-authorization.js.map +1 -1
- package/dist/presentation.js +6 -3
- package/dist/presentation.js.map +1 -1
- package/dist/session-registry.d.ts +11 -3
- package/dist/session-registry.js +61 -45
- package/dist/session-registry.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,884 +1,223 @@
|
|
|
1
1
|
# Nawabari
|
|
2
2
|
|
|
3
|
-
Nawabari is a
|
|
4
|
-
agents. It gives each active session one exclusively owned worktree and one
|
|
5
|
-
mutable branch. It works without GitHub, `gh`, a network connection, Mottainai,
|
|
6
|
-
or a particular agent runtime.
|
|
7
|
-
|
|
8
|
-
Nawabari governs operations routed through Nawabari. By default it is an
|
|
9
|
-
authorization and ownership boundary, not an operating-system or filesystem
|
|
10
|
-
sandbox: a process that already has filesystem permissions can still edit
|
|
11
|
-
another worktree directly. This default (legacy) mode is unchanged.
|
|
12
|
-
|
|
13
|
-
The opt-in protected session mode defines a Linux-only OS/filesystem/process
|
|
14
|
-
enforcement boundary underneath the existing session/worktree/resource
|
|
15
|
-
authority (`src/domain/sandbox.ts`, contract
|
|
16
|
-
`nawabari.sandbox-execution.v1`). It binds one existing Nawabari session
|
|
17
|
-
resolved through the authoritative registry/guard path to a typed sandbox
|
|
18
|
-
execution request; it does not create a second session identity. A
|
|
19
|
-
machine-readable capability/doctor report distinguishes required Linux
|
|
20
|
-
primitives (bubblewrap, user/mount/PID/IPC/UTS namespaces, the versioned
|
|
21
|
-
seccomp baseline, and capability reduction) from optional defense-in-depth
|
|
22
|
-
primitives (cgroups v2 and Landlock). The sandbox report exposes Landlock's
|
|
23
|
-
observed ABI, support, and effective state (`available`, `enforced`,
|
|
24
|
-
`reduced-defense`, `incompatible`, or `error`). When protected execution is requested and a required capability
|
|
25
|
-
is unavailable or the platform is unsupported, resolution fails closed and
|
|
26
|
-
never returns a request that claims the legacy unsandboxed path is
|
|
27
|
-
protected. The lower-level contract remains responsible only for capability
|
|
28
|
-
detection and the typed request/result shape; `resolveSandboxExecutionRequest()`
|
|
29
|
-
returns a request without invoking bubblewrap. The managed `session run`
|
|
30
|
-
launcher consumes that request and establishes the protected boundary. Network
|
|
31
|
-
mode is honestly reported as `inherited` (shared with the host), not isolated.
|
|
32
|
-
|
|
33
|
-
`git nawabari session run --session <id> -- <command> [args...]` is the
|
|
34
|
-
managed protected execution entry point. It resolves the existing session
|
|
35
|
-
through the normal guard authority and compiles a fixed bubblewrap argv; the
|
|
36
|
-
command is passed after an argv terminator and is never interpreted by a
|
|
37
|
-
shell. Resolution or launch failure never falls back to the legacy ambient
|
|
38
|
-
filesystem view.
|
|
39
|
-
|
|
40
|
-
The canonical profile starts from a private root, mounts only the owned
|
|
41
|
-
worktree read-write, gives each session private `/tmp`, `/proc`, HOME and
|
|
42
|
-
cache state, and exposes no sibling worktree or control-plane path. A small
|
|
43
|
-
repository-owned `nawabari/sandbox/shared-home` subtree is the only HOME state
|
|
44
|
-
shared between sessions. Selected host user-tool directories (`~/.local/bin`
|
|
45
|
-
and pnpm's user bin when present) are read-only; credentials and the rest of
|
|
46
|
-
the host HOME are not mounted. `/dev`, system certificates/configuration, and
|
|
47
|
-
the detected runtime are explicit read-only/runtime inputs.
|
|
48
|
-
|
|
49
|
-
When the host exposes a compatible Landlock ABI, the protected launcher applies
|
|
50
|
-
a rule set derived from this same topology inside bubblewrap. An unavailable
|
|
51
|
-
or incompatible optional ABI leaves bubblewrap active and reports
|
|
52
|
-
`reduced-defense`; an adapter setup failure fails closed, and a profile that
|
|
53
|
-
explicitly requires Landlock also fails closed when its adapter cannot be
|
|
54
|
-
established. Setup diagnostics are bounded and no ambient/unsandboxed retry is
|
|
55
|
-
attempted.
|
|
56
|
-
|
|
57
|
-
On standalone Linux the profile uses existing `/usr`, `/bin`, `/lib*` and
|
|
58
|
-
selected `/etc` paths only when present. On NixOS it additionally selects
|
|
59
|
-
`/nix/store`, `/run/current-system`, `/run/wrappers`, and the per-user profile
|
|
60
|
-
when present; broad FHS views (`/usr`, `/bin`, `/lib*`) are not selected when
|
|
61
|
-
the NixOS closure roots are present. Missing required paths or namespace
|
|
62
|
-
support produces a stable capability/topology error. The protected child uses
|
|
63
|
-
`nawabari.seccomp.v1`, a compatibility-first deny-list whose policy denials
|
|
64
|
-
return `EPERM` rather than hanging or terminating ordinary development
|
|
65
|
-
subprocess trees. Ambient capabilities are empty (`--cap-drop ALL`). Network
|
|
66
|
-
remains inherited by design.
|
|
67
|
-
|
|
68
|
-
The canonical Mottainai NixOS Runtime fixture can run the opt-in compatibility
|
|
69
|
-
conformance matrix as its unprivileged repository principal:
|
|
3
|
+
Nawabari is a local governance layer for parallel coding agents. It gives each agent session an owned Git worktree and branch, records which repository resources that session may use, and checks those boundaries before governed mutations.
|
|
70
4
|
|
|
71
|
-
|
|
72
|
-
NAWABARI_NIXOS_RUNTIME_CONFORMANCE=1 \
|
|
73
|
-
node --test --import tsx src/domain/nixos-runtime-compat.test.ts
|
|
74
|
-
```
|
|
5
|
+
It is for teams and tools that need several agents to work in one repository without silently sharing a worktree, overwriting one another's files, or guessing whether a session is safe to close. Nawabari is local-first: the session registry, Git observations, and authorization decisions do not require GitHub, `gh`, a network connection, or a particular agent runtime.
|
|
75
6
|
|
|
76
|
-
This
|
|
77
|
-
checks explicit NixOS closure paths, private versus repository-shared HOME
|
|
78
|
-
state, Git/checkpoint authority, representative toolchain subprocesses, and
|
|
79
|
-
sequential/concurrent session isolation. It does not create a test-only
|
|
80
|
-
sandbox or treat Mottainai state as Nawabari authority.
|
|
7
|
+
This README describes the current 0.10.x product model. It is an overview and navigation surface, not a copy of generated contracts or implementation history.
|
|
81
8
|
|
|
82
|
-
|
|
9
|
+
The product model is intentionally small:
|
|
83
10
|
|
|
84
|
-
|
|
11
|
+
1. Create a session. Nawabari provisions a dedicated worktree and branch.
|
|
12
|
+
2. Claim the resources the session is allowed to use.
|
|
13
|
+
3. Route governed work through claims, evidence, and mutation authorization.
|
|
14
|
+
4. Inspect the result, then close the session only when integration is proven.
|
|
85
15
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
16
|
+
Nawabari governs operations routed through Nawabari. A normal governed session is an ownership and authorization boundary, not an operating-system or filesystem sandbox. A process with ambient filesystem permissions can still edit another worktree directly.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
89
19
|
|
|
90
|
-
|
|
91
|
-
`git nawabari` external subcommand. Both names use the same entry point.
|
|
20
|
+
Node.js 24 or newer is required.
|
|
92
21
|
|
|
93
22
|
```bash
|
|
94
|
-
|
|
23
|
+
npm install -g nawabari
|
|
95
24
|
nawabari --version
|
|
25
|
+
git nawabari --help
|
|
96
26
|
```
|
|
97
27
|
|
|
98
|
-
|
|
28
|
+
The package installs both `nawabari` and `git-nawabari`; `git nawabari ...` works as Git's external subcommand.
|
|
29
|
+
|
|
30
|
+
## First session
|
|
99
31
|
|
|
100
|
-
|
|
101
|
-
must discover the contract before using the lifecycle:
|
|
32
|
+
Run from the repository's integration worktree. `src/example.ts` below is a placeholder path; substitute a real file that exists in your repository.
|
|
102
33
|
|
|
103
34
|
```bash
|
|
104
35
|
nawabari capabilities --json
|
|
105
|
-
nawabari --version --json
|
|
106
|
-
```
|
|
107
36
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
result-schema versions, identity fields, and stable `failure_codes`. The
|
|
112
|
-
package version is release metadata; it is not a substitute for the
|
|
113
|
-
machine-contract identifier.
|
|
114
|
-
|
|
115
|
-
The `protected-execution` capability separately advertises the versioned
|
|
116
|
-
`nawabari.sandbox-execution.v1` contract, its required and optional host
|
|
117
|
-
capabilities, the canonical `session run` entry point and `session exec` alias,
|
|
118
|
-
`network_mode: "inherited"`, and fail-closed behavior. Use
|
|
119
|
-
`nawabari doctor --json` to inspect the current host without creating or
|
|
120
|
-
selecting a session. Its `sandbox` report is produced by the same
|
|
121
|
-
`sandboxDoctorReport` authority used when resolving protected execution and
|
|
122
|
-
contains `platform_supported`, per-capability status, `ready`, and
|
|
123
|
-
`missing_required`. An unavailable required capability never implies an
|
|
124
|
-
ambient protected fallback.
|
|
125
|
-
|
|
126
|
-
The `resource-claims` capability additionally exposes a machine-readable
|
|
127
|
-
`claim_set_replacement` object (`commands`, `atomic: true`,
|
|
128
|
-
`pairing: "adjacent-resource-mode"`, `idempotent_retry: true`,
|
|
129
|
-
`unchanged_on_rejection: true`) describing the atomic multi-claim replacement
|
|
130
|
-
surface documented above, so a caller can discover this contract instead of
|
|
131
|
-
assuming it from the CLI help text.
|
|
132
|
-
|
|
133
|
-
Resource-claim semantics are generation `nawabari.resource-claims.v2` with
|
|
134
|
-
claim-record schema `2`. The standalone envelope deliberately remains
|
|
135
|
-
`nawabari.standalone-execution.v1`: this is a meaning-compatible top-level
|
|
136
|
-
identity, while callers select the child resource-claim generation before
|
|
137
|
-
operating. A future meaning-changing claim authorization, conflict, transition,
|
|
138
|
-
release, or required-mode change must publish a new resource-claim generation
|
|
139
|
-
and identity; the package version alone is never a compatibility decision.
|
|
140
|
-
The capability binds every lifecycle command and alias to its result schema,
|
|
141
|
-
implementation-owned stable failure vocabulary, transition-matrix identity,
|
|
142
|
-
CAS/force and rejected-non-mutation guarantees, and deterministic recovery
|
|
143
|
-
action schema.
|
|
144
|
-
|
|
145
|
-
The supported standalone sequence is:
|
|
37
|
+
created=$(git nawabari session create --branch feature/example --json)
|
|
38
|
+
session_id=$(printf '%s' "$created" | jq -r .session_id)
|
|
39
|
+
worktree=$(printf '%s' "$created" | jq -r .worktree)
|
|
146
40
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
41
|
+
(cd "$worktree" && git nawabari session claim --session "$session_id" --resource src/example.ts --mode exclusive-write --json)
|
|
42
|
+
(cd "$worktree" && git nawabari guard --session "$session_id" --operation source-write --resource src/example.ts --json)
|
|
43
|
+
(cd "$worktree" && "$EDITOR" src/example.ts)
|
|
44
|
+
(cd "$worktree" && git nawabari checkpoint --session "$session_id" --json)
|
|
45
|
+
(cd "$worktree" && git nawabari commit --session "$session_id" --all-claimed --message "Update example" --json)
|
|
151
46
|
```
|
|
152
47
|
|
|
153
|
-
|
|
154
|
-
`command`, and the command's versioned result fields. Failure has `ok: false`,
|
|
155
|
-
the `command`, a stable `code`, a bounded human-readable `message`, and
|
|
156
|
-
optional structured `details`; JSON mode writes no decorative stderr. Exit
|
|
157
|
-
codes are `0` success, `2` usage, `3` rejected/unsafe operation, `4`
|
|
158
|
-
unavailable capability, `5` failed doctor checks, and `70` unexpected internal
|
|
159
|
-
failure. Consumers must use these fields and codes, never human presentation.
|
|
160
|
-
|
|
161
|
-
The result schemas expose the following identities:
|
|
162
|
-
|
|
163
|
-
| Surface | Versioned identities |
|
|
164
|
-
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
165
|
-
| session lifecycle | `session_id`, `repository`, `worktree`, `branch`, `state` |
|
|
166
|
-
| explicit discard | `previous_head`, `worktree_removed`, `branch_removed`, `released_claims`, `final_state`, final `session.state`/`terminal_operation` |
|
|
167
|
-
| claims | `claim_id`, `session_id`, `resource`, `mode`, `claim_set_generation`, `previous_claim_set_generation` |
|
|
168
|
-
| authorization | `operation`, `allowed`, `code`, `claim_ids` |
|
|
169
|
-
| checkpoint evidence | `head`, `changed`, `staged`, `unstaged`, `untracked`, `in_claim`, `out_of_claim` |
|
|
170
|
-
| repository evidence | `session_id`, `session_updated_at`, `base_revision`, `head`, `clean`, `paths.stats`, `evidence_hash` |
|
|
171
|
-
| bounded diff | `from_revision`, `to_revision`, `paths`, `stats`, `diagnostics`, `patch`, `evidence_hash` |
|
|
172
|
-
| commit/push | `commit_sha`, `remote`, `branch`, `target`, `relation` |
|
|
173
|
-
| reconciliation/cleanup | `clean`, `issues`, `candidates`, `cleaned`, `blocked`, `recovery_hints` |
|
|
174
|
-
|
|
175
|
-
Git subprocesses are bounded at 10 seconds and 64 KiB of output; checkpoint
|
|
176
|
-
evidence is bounded to 4,096 paths. `GIT_SPAWN_FAILED`, `GIT_TIMEOUT`,
|
|
177
|
-
`GIT_OUTPUT_LIMIT`, and `GIT_COMMAND_FAILED` remain distinct failure codes.
|
|
178
|
-
The local lifecycle requires Git and the repository-local registry/lock only;
|
|
179
|
-
it does not require Mottainai, GitHub, `gh`, network access, an LLM, or a
|
|
180
|
-
coding-agent runtime.
|
|
181
|
-
|
|
182
|
-
## Package state/contract API
|
|
183
|
-
|
|
184
|
-
The CLI/JSON surface above remains the primary integration boundary. For a
|
|
185
|
-
Node caller that wants public lifecycle observation/snapshot,
|
|
186
|
-
transition-decision data, or machine-contract discovery without spawning the
|
|
187
|
-
CLI and parsing its output, the package additionally exports two explicit,
|
|
188
|
-
stable entry points:
|
|
48
|
+
`session create` provisions the new worktree under `<repository-parent>/.nawabari/worktrees` by default (discoverable via `status --json` as `managed_worktree_root`). Nawabari creates that managed subdirectory on first default placement. New exact `--worktree` paths must be under the reported root; an absolute path directly under the repository parent remains accepted for compatibility with older callers and persisted sessions.
|
|
189
49
|
|
|
190
|
-
|
|
191
|
-
import { classifyNawabariState, getNawabariSessionStateSnapshot } from "nawabari/state";
|
|
192
|
-
import { nawabariMachineContract } from "nawabari/contract";
|
|
193
|
-
```
|
|
50
|
+
`--all-claimed` is an explicit resource selector. It resolves safely observed Git-changed paths covered by qualifying claims; it does not bypass claim authorization. Use repeated `--resource <path>` when an explicit path list is preferable.
|
|
194
51
|
|
|
195
|
-
|
|
196
|
-
(`NawabariLifecycleState`, `NawabariCommand`), the public observation input
|
|
197
|
-
(`NawabariObservation`), and the public projection produced from it
|
|
198
|
-
(`NawabariStateSnapshot`, `NawabariTransitionDecision`). `classifyNawabariState`
|
|
199
|
-
is a pure, transport-neutral projection function; `getNawabariSessionStateSnapshot`
|
|
200
|
-
observes one real, already-provisioned session through the same
|
|
201
|
-
`SessionRegistry` Git/filesystem/session-registry authority `session inspect`
|
|
202
|
-
uses, without mutating anything. `nawabari/contract` exposes
|
|
203
|
-
`nawabariMachineContract()`, a zero-argument wrapper over the same
|
|
204
|
-
`capabilities --json` contract that defaults to the installed package's own
|
|
205
|
-
version.
|
|
206
|
-
|
|
207
|
-
These are the only supported package entry points beyond the CLI binaries.
|
|
208
|
-
Raw XState machine/actor internals, actor refs, internal state-node ids, and
|
|
209
|
-
private machine context are not exported — `package.json#exports` declares no
|
|
210
|
-
other subpath, so a deep import such as `nawabari/dist/state/session/machine.js`
|
|
211
|
-
is rejected. `classifyNawabariState` only ever projects a caller-supplied observation into
|
|
212
|
-
a decision; it never mutates anything, and no observation or transition
|
|
213
|
-
decision it returns grants mutation authority. Mutating a session
|
|
214
|
-
(close/discard/claim/commit/push/...) still requires the existing CLI or the
|
|
215
|
-
`SessionRegistry` authority directly.
|
|
216
|
-
|
|
217
|
-
## Read-only repository evidence
|
|
218
|
-
|
|
219
|
-
The evidence family is session-addressed and has no task, Issue, semantic, or
|
|
220
|
-
GitHub interpretation. It is the physical repository authority for one owned
|
|
221
|
-
session:
|
|
52
|
+
After reviewing and integrating the session branch:
|
|
222
53
|
|
|
223
54
|
```bash
|
|
224
|
-
git nawabari
|
|
225
|
-
git nawabari
|
|
226
|
-
git nawabari diff --session "$NAWABARI_SESSION_ID" --path src/example.ts \
|
|
227
|
-
--patch --max-bytes 32768 --max-hunks 32 --json
|
|
55
|
+
git nawabari session inspect --session "$session_id" --json
|
|
56
|
+
git nawabari session close --session "$session_id" --json
|
|
228
57
|
```
|
|
229
58
|
|
|
230
|
-
|
|
231
|
-
then reuses checkpoint's exact NUL-safe Git observation for `changed`,
|
|
232
|
-
`staged`, `unstaged`, and `untracked` paths. It also reports canonical per-path
|
|
233
|
-
stats, `clean`, the current `head`, session state, and an `evidence_hash`.
|
|
234
|
-
New sessions persist the exact creation/base revision as `base_revision`;
|
|
235
|
-
legacy records that lack this field report `base_revision: null` and
|
|
236
|
-
`base_revision_proven: false` rather than inferring it from a mutable ref.
|
|
237
|
-
|
|
238
|
-
`session_updated_at` is the UTC timestamp of the last authoritative
|
|
239
|
-
session-state mutation, not a general Git filesystem mtime. A successful
|
|
240
|
-
Nawabari-managed `commit` is such a mutation, so the registry timestamp is
|
|
241
|
-
persisted before the command returns and a subsequent snapshot reports it with
|
|
242
|
-
the resulting `head`. Git changes made outside Nawabari do not advance this
|
|
243
|
-
field; consumers must use the Git-observed fields for those changes.
|
|
244
|
-
|
|
245
|
-
`diff` requires at least one explicit concrete path and never accepts a glob or
|
|
246
|
-
an empty repository-wide selection. Stats are returned by default. Patch text
|
|
247
|
-
requires `--patch` and is bounded to at most 64 paths, 64 KiB, and 128 hunks;
|
|
248
|
-
the caller may request smaller limits. Unrepresentable Git observations fail
|
|
249
|
-
with `GIT_STATE_AMBIGUOUS`; a requested path whose stat is not exposed by Git
|
|
250
|
-
remains in the result with `available: false` and makes snapshot evidence
|
|
251
|
-
`complete: false`, so no path silently disappears. Such paths include a
|
|
252
|
-
bounded `diagnostics` entry; a target directly observed as untracked reports
|
|
253
|
-
`reason: UNTRACKED_TARGET`, while other unavailable-stat causes remain
|
|
254
|
-
`STAT_UNAVAILABLE`. These diagnostics are read-only and do not stage or add
|
|
255
|
-
files.
|
|
256
|
-
|
|
257
|
-
## Session lifecycle
|
|
258
|
-
|
|
259
|
-
Session IDs are generated automatically as UUIDv7 values. They are immutable
|
|
260
|
-
machine identities; labels and branch names are separate display metadata.
|
|
59
|
+
Close is conservative. Unintegrated commits, dirty worktrees, ambiguous Git state, and ownership mismatches remain blocked. For a squash or rebase merge, pass an exact local `--integrated-revision <rev>` so Nawabari can independently re-verify the content.
|
|
261
60
|
|
|
262
|
-
|
|
263
|
-
git nawabari session create --branch feature/example --worktree ../example-worktree --json
|
|
264
|
-
git nawabari session id --json
|
|
265
|
-
git nawabari session show --json
|
|
266
|
-
git nawabari session show <session-id> --json
|
|
267
|
-
git nawabari session list --json
|
|
268
|
-
git nawabari status --json
|
|
269
|
-
git nawabari guard --json
|
|
270
|
-
git nawabari session close --json
|
|
271
|
-
git nawabari session discard --session <session-id> --json
|
|
272
|
-
git nawabari gc --dry-run --json
|
|
273
|
-
git nawabari doctor --json
|
|
274
|
-
```
|
|
61
|
+
## Authority model
|
|
275
62
|
|
|
276
|
-
|
|
277
|
-
`session create` omits `--worktree` and `--worktree-root`. `session create
|
|
278
|
-
--help --json` describes all create options as optional and reports defaults
|
|
279
|
-
for branch, worktree, worktree root, base (`HEAD`), and label.
|
|
280
|
-
|
|
281
|
-
`--worktree-root` selects only the parent directory for a new session
|
|
282
|
-
worktree; Nawabari still derives the final worktree basename from its own
|
|
283
|
-
session-naming contract. It is mutually exclusive with `--worktree`, the
|
|
284
|
-
exact-path override. Every session record's `worktree_root` field reports
|
|
285
|
-
the resolved parent of that session's worktree.
|
|
286
|
-
|
|
287
|
-
`session create` provisions a dedicated worktree and mutable branch atomically
|
|
288
|
-
under the repository-scoped mutation lock. The default/integration worktree
|
|
289
|
-
and its protected branch cannot be session resources. `session id` and the
|
|
290
|
-
other current-session commands resolve ownership from the current worktree;
|
|
291
|
-
callers do not need to repeat the session ID for current-owner operations.
|
|
292
|
-
|
|
293
|
-
Session-scoped commands use one target grammar: the canonical `--session <id>`
|
|
294
|
-
option is accepted everywhere, and `show`, `inspect`, `claim`, `claims`,
|
|
295
|
-
`release`, `update`, `close`, and `discard` also accept one positional
|
|
296
|
-
`<session-id>` immediately after the subcommand. Supplying both forms is
|
|
297
|
-
rejected as ambiguous. `session discard` always requires one explicit target
|
|
298
|
-
and never infers the current worktree owner.
|
|
299
|
-
|
|
300
|
-
Close is conservative. Dirty worktrees, ambiguous ownership, mismatched Git
|
|
301
|
-
state, and commits not proven reachable from the integration branch block
|
|
302
|
-
destructive cleanup. A clean close releases only the owned worktree and
|
|
303
|
-
branch, and repeating close is idempotent. `gc` detects stale or interrupted
|
|
304
|
-
sessions; `--apply` uses the same close safety checks and reports blocked
|
|
305
|
-
sessions instead of guessing. `gc --dry-run` performs the same non-mutating
|
|
306
|
-
cleanup preflight, reports age/physical/lifecycle suspicion separately from
|
|
307
|
-
destructive eligibility, and includes stable blocker codes and
|
|
308
|
-
`recovery_hints` for every eligible candidate that is not safe. Cleanup revalidates the physical worktree,
|
|
309
|
-
branch, and `HEAD` observations immediately before each destructive Git
|
|
310
|
-
operation.
|
|
311
|
-
|
|
312
|
-
`session discard` is the sole explicit destructive abandonment path. It
|
|
313
|
-
revalidates repository identity, the selected session, exact worktree/branch
|
|
314
|
-
ownership, and session/worktree `HEAD` immediately before each Git mutation.
|
|
315
|
-
It may destroy the selected session's unintegrated commits and uncommitted
|
|
316
|
-
worktree contents, removes only that session's worktree/branch, releases only
|
|
317
|
-
its claims, and records `terminal_operation: "discard"` plus the pre-discard
|
|
318
|
-
`HEAD`. It never acts as an implicit fallback for `close`, `gc`, `doctor`, or
|
|
319
|
-
reconciliation; sibling sessions remain untouched. A partial failure leaves a
|
|
320
|
-
retryable closing record and a repeated discard converges or returns an
|
|
321
|
-
explicit terminal idempotent result.
|
|
322
|
-
|
|
323
|
-
Routine `session list` and `status` output excludes `closed` history and is
|
|
324
|
-
limited to 64 records. Use `--all` (or `--history`) for an explicit complete
|
|
325
|
-
history view; closed records remain persisted and are never silently deleted
|
|
326
|
-
by listing or cleanup.
|
|
327
|
-
|
|
328
|
-
`gc` stale eligibility is separate from closed-history retention. Its default
|
|
329
|
-
threshold is 24 hours (`86,400,000` ms), measured from persisted `updated_at`.
|
|
330
|
-
Elapsed age is diagnostic suspicion only: it never authorizes destructive
|
|
331
|
-
cleanup for a physically healthy active session. Records already in `stale` or
|
|
332
|
-
`closing` state are eligible, as is an otherwise live record when Git reports
|
|
333
|
-
its registered worktree as safely prunable and missing. Ambiguous physical
|
|
334
|
-
state remains ineligible and fail-closed. `gc --dry-run` exposes suspicion and
|
|
335
|
-
destructive eligibility/reason separately for each candidate; `gc --apply`
|
|
336
|
-
uses only eligible candidates. Closed records are never stale cleanup
|
|
337
|
-
candidates.
|
|
338
|
-
|
|
339
|
-
`doctor` includes a non-destructive `reconciliation` check. It reports
|
|
340
|
-
registry/Git ownership drift, including missing or prunable worktrees and
|
|
341
|
-
unregistered physical worktrees, without repairing or deleting anything.
|
|
342
|
-
|
|
343
|
-
## Session resource claims
|
|
344
|
-
|
|
345
|
-
Resource claims are versioned, session-scoped ownership records stored in the
|
|
346
|
-
same repository registry and protected by the same mutation lock. They are
|
|
347
|
-
caller declarations; Nawabari does not infer them from task text or source
|
|
348
|
-
code. Claim JSON exposes `schema_version`, `claim_id`, `session_id`, the
|
|
349
|
-
repository/worktree identities, canonical `resource`, `mode`, and timestamps.
|
|
350
|
-
The claim schema version is `2` and supports `read`, `write`, and
|
|
351
|
-
`exclusive-write`. Schema v1 records use different overlap semantics and are
|
|
352
|
-
not interpreted implicitly. If an upgraded repository reports
|
|
353
|
-
`UNSUPPORTED_CLAIM_SCHEMA_VERSION`, run the public migration command:
|
|
63
|
+
Each boundary has one job and one local authority. README summarizes the product contract; executable code and machine-readable projections remain authoritative for exact schemas, transitions, and failure vocabularies.
|
|
354
64
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
65
|
+
| Boundary | What it answers | Typical commands |
|
|
66
|
+
| ---------------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
|
|
67
|
+
| Session lifecycle | Which session owns a worktree/branch and whether it can safely progress or terminate | `session create`, `session inspect`, `session close` |
|
|
68
|
+
| Resource Claims | Which session may access a canonical repository resource and at what mode | `session claim`, `session claims`, `session update`, `session release` |
|
|
69
|
+
| Mutation authorization | Whether a concrete operation has sufficient claims and no conflicting owner | `guard`, `authorize`, `commit`, `push` |
|
|
70
|
+
| Repository evidence | What Git can observe about revisions, paths, changes, ancestry, and bounded diffs | `checkpoint`, `evidence snapshot`, `diff` |
|
|
71
|
+
| Protected execution | Whether a command runs inside the opt-in Linux process/filesystem boundary | `session run`, `session exec`, `session shell`, `doctor` |
|
|
358
72
|
|
|
359
|
-
|
|
360
|
-
rewrites it with an atomic replace. It is idempotent and retry-safe; ambiguous
|
|
361
|
-
or corrupt state is rejected with bounded diagnostics. Do not hand-edit or
|
|
362
|
-
delete the registry. Embedding callers may use the same authority through
|
|
363
|
-
`SessionRegistry.migrate()`.
|
|
73
|
+
Claims are not task labels and do not encode GitHub or agent semantics. `write` permits ordinary path changes; `exclusive-write` is required for finalizing operations such as commit and push. Conflicting or ambiguous claims fail closed.
|
|
364
74
|
|
|
365
|
-
|
|
366
|
-
git nawabari session claim --session "$NAWABARI_SESSION_ID" \
|
|
367
|
-
--resource 'src/**/*.ts' --mode read --json
|
|
368
|
-
git nawabari session claims --session "$NAWABARI_SESSION_ID" --json
|
|
369
|
-
git nawabari session update --session "$NAWABARI_SESSION_ID" \
|
|
370
|
-
--resource 'src/**/*.ts' --mode write --force --json
|
|
371
|
-
git nawabari session release --session "$NAWABARI_SESSION_ID" --all --force --json
|
|
372
|
-
```
|
|
75
|
+
The default governance path does not install hooks and does not prevent direct filesystem writes outside Nawabari. Its guarantee is that Nawabari-routed operations consult authoritative session, Git, and claim state before mutation.
|
|
373
76
|
|
|
374
|
-
|
|
375
|
-
session's _complete_ claim set in one `updateClaims()` transaction, backed by
|
|
376
|
-
the same repository lock as every other mutation. `--resource`/`--mode` are
|
|
377
|
-
repeatable to submit a multi-resource desired set in a single call; each
|
|
378
|
-
`--resource` must be immediately followed by its own `--mode`, so pairing is
|
|
379
|
-
positional adjacency rather than flag order and repeated resources can never
|
|
380
|
-
be associated with the wrong mode:
|
|
77
|
+
## Session and resource lifecycle
|
|
381
78
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
79
|
+
The normal path is:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
session create
|
|
83
|
+
↓
|
|
84
|
+
active session → claim resources → guard/checkpoint → commit or push
|
|
85
|
+
↓ ↓
|
|
86
|
+
inspect readiness integrate the branch
|
|
87
|
+
↓ ↓
|
|
88
|
+
session close ←────────────────────────────────────┘
|
|
387
89
|
```
|
|
388
90
|
|
|
389
|
-
If
|
|
390
|
-
is rejected and the session's prior claim set is left unchanged; no partial
|
|
391
|
-
or empty intermediate claim state is ever observable. Submitting the same
|
|
392
|
-
complete desired set again is idempotent. A successful replacement's JSON
|
|
393
|
-
exposes the resulting `claims` together with machine-readable `added` and
|
|
394
|
-
`released` claims.
|
|
91
|
+
If work is not integrated, `session inspect` reports bounded blockers and safe next actions. Discard is never an implicit fallback for close or garbage collection.
|
|
395
92
|
|
|
396
|
-
The
|
|
93
|
+
The Session lifecycle is backed by the executable XState authority in 0.10.x and exposed through public state, contract, and manifest projections. Consumers use those projections rather than internal machine nodes or actor objects.
|
|
397
94
|
|
|
398
|
-
|
|
399
|
-
session claim/resource claim (additive acquire)
|
|
400
|
-
-> session transition/resource transition (one exact-resource mode change)
|
|
401
|
-
-> session mutate/resource mutate (atomic exact-resource deltas)
|
|
402
|
-
-> session release/resource release (--resource, --claim-id, or explicit --all)
|
|
403
|
-
-> session update/resource update (atomic complete-set replacement)
|
|
404
|
-
```
|
|
95
|
+
### Claims
|
|
405
96
|
|
|
406
|
-
|
|
407
|
-
explicit `--force`. A stale CAS returns `STALE_CLAIM_SET` without changing
|
|
408
|
-
claims or generation. Additive claim is not replacement; selected release
|
|
409
|
-
preserves unrelated claims; `--all` is the unambiguous all-claims selector.
|
|
410
|
-
An exact contradictory additive claim remains rejected with
|
|
411
|
-
`CONTRADICTORY_CLAIM` and may carry the typed `transition-exact-resource`
|
|
412
|
-
recovery action, whose generation is directly usable as the transition CAS.
|
|
413
|
-
|
|
414
|
-
The modes have these normative meanings:
|
|
415
|
-
|
|
416
|
-
- `read`: a non-mutating access declaration. It is not a consistency lease,
|
|
417
|
-
so it may overlap an ordinary `write` claim.
|
|
418
|
-
- `write`: ordinary source-modification authority. It may overlap `read`, but
|
|
419
|
-
not another writer or any `exclusive-write` claim.
|
|
420
|
-
- `exclusive-write`: stronger ownership-sensitive mutation authority. It
|
|
421
|
-
excludes every overlapping claim, including `read`.
|
|
422
|
-
|
|
423
|
-
Overlapping claims use this complete compatibility matrix; non-overlapping
|
|
424
|
-
claims are compatible for every mode:
|
|
425
|
-
|
|
426
|
-
| existing \/ requested | read | write | exclusive-write |
|
|
427
|
-
| --------------------- | ---------- | ---------- | --------------- |
|
|
428
|
-
| read | compatible | compatible | conflict |
|
|
429
|
-
| write | compatible | conflict | conflict |
|
|
430
|
-
| exclusive-write | conflict | conflict | conflict |
|
|
431
|
-
|
|
432
|
-
Claims use canonical repository-relative POSIX paths. Literal path segments,
|
|
433
|
-
`*`/`?` segment wildcards, and a complete `**` segment are supported. Empty,
|
|
434
|
-
`.`/`..`, absolute, drive-relative, backslash, unsupported-glob, and
|
|
435
|
-
symlink-escaping forms are rejected with stable machine-readable codes.
|
|
436
|
-
Equivalent claim acquisition and release retries are idempotent. Closing or
|
|
437
|
-
garbage-collecting a session releases its claims; no separate claim registry
|
|
438
|
-
or claim lock exists. Claims describe ownership state only and do not provide
|
|
439
|
-
OS-level filesystem observation or a filesystem sandbox.
|
|
440
|
-
|
|
441
|
-
For an existing path, canonicalization follows the physical directory entry,
|
|
442
|
-
so a case-insensitive filesystem cannot give `README.md` and `readme.md`
|
|
443
|
-
independent claim identities. This is determined from the filesystem entry
|
|
444
|
-
itself; paths that do not exist yet, and wildcard portions of a claim, retain
|
|
445
|
-
their exact lexical case because their future physical identity is unknown.
|
|
446
|
-
On a case-sensitive filesystem an alternate-case spelling is therefore a
|
|
447
|
-
distinct (possibly future) path, and no global lowercasing is applied.
|
|
448
|
-
|
|
449
|
-
An ordinary source change uses `write` and can proceed while another session
|
|
450
|
-
holds a `read` declaration:
|
|
97
|
+
Claims are canonical repository-relative resource records attached to a session. Supported modes are `read`, `write`, and `exclusive-write`.
|
|
451
98
|
|
|
452
99
|
```bash
|
|
453
|
-
git nawabari session claim --session "$
|
|
454
|
-
|
|
455
|
-
git nawabari
|
|
456
|
-
|
|
100
|
+
git nawabari session claim --session "$session_id" --resource src/example.ts --mode exclusive-write --json
|
|
101
|
+
git nawabari session claims --session "$session_id" --json
|
|
102
|
+
git nawabari session update --session "$session_id" --resource src/example.ts --mode exclusive-write --resource test/example.test.ts --mode write --if-generation 1 --json
|
|
103
|
+
git nawabari session release --session "$session_id" --all --force --json
|
|
457
104
|
```
|
|
458
105
|
|
|
459
|
-
|
|
460
|
-
requires no overlapping claim:
|
|
106
|
+
Resource aliases are discoverable through help. Use `--help --json` rather than copying option metadata into an integration.
|
|
461
107
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
```
|
|
108
|
+
Claim modes are cumulative. The canonical operation requirements are derived from the operation authorization policy and are shown by `session claim --help`:
|
|
109
|
+
|
|
110
|
+
- `read`: no governed operation
|
|
111
|
+
- `write`: `source-write`, `stage`
|
|
112
|
+
- `exclusive-write`: `source-write`, `stage`, `commit`, `branch-mutation`, `push`, `cleanup`
|
|
468
113
|
|
|
469
|
-
|
|
114
|
+
The policy requires `exclusive-write` for operations that finalize or remove shared state. This mapping is documentation of the executable authority, not a second claim policy; integrations should discover the current values from help or the machine contract.
|
|
470
115
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
operations. An optional `--session` asserts the caller's session identity.
|
|
116
|
+
### Inspect, close, discard, and garbage collection
|
|
117
|
+
|
|
118
|
+
`session inspect` is read-only and uses the same close/cleanup evidence as `session close`.
|
|
475
119
|
|
|
476
120
|
```bash
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
exit 1
|
|
480
|
-
}
|
|
121
|
+
git nawabari session inspect --session "$session_id" --json
|
|
122
|
+
git nawabari session discard --session "$session_id" --preview --json
|
|
481
123
|
```
|
|
482
124
|
|
|
483
|
-
|
|
484
|
-
decision has `allowed: false`, a stable code such as
|
|
485
|
-
`WORKTREE_OWNED_BY_OTHER_SESSION`, `PROTECTED_WORKTREE`, `DETACHED_HEAD`,
|
|
486
|
-
`WORKTREE_MISMATCH`, or `OWNERSHIP_MISMATCH`, and a non-zero exit status.
|
|
487
|
-
Detached, corrupt, missing, or conflicting state fails closed. The guard does
|
|
488
|
-
not install hooks and does not prevent direct filesystem writes outside
|
|
489
|
-
Nawabari.
|
|
490
|
-
|
|
491
|
-
## Actionable lifecycle rejections
|
|
492
|
-
|
|
493
|
-
Stable codes are necessary but not sufficient for a caller to pick a safe
|
|
494
|
-
next step without a second, separate inspection. For the codes below,
|
|
495
|
-
Nawabari's `details` carry bounded, deterministic evidence and a
|
|
496
|
-
`safeActions`/`safe_actions` list of stable, kebab-case next-action
|
|
497
|
-
identifiers, in addition to the human-readable `message`. JSON and human
|
|
498
|
-
output always render the identical underlying result; only the formatting
|
|
499
|
-
differs.
|
|
500
|
-
|
|
501
|
-
Lifecycle diagnostics additionally expose `next_action` (and the bounded
|
|
502
|
-
`next_actions` list) as typed, non-mutating caller actions. The action schema
|
|
503
|
-
is versioned independently and currently includes `retain-session`,
|
|
504
|
-
`supply-exact-integrated-revision`,
|
|
505
|
-
`retry-close-with-bounded-integration-fetch`, `discard-session`, and
|
|
506
|
-
`reconcile-physical-state`. A discard action always carries explicit intent;
|
|
507
|
-
ambiguous or terminal states never advertise destructive actions. These
|
|
508
|
-
fields are additive to `session-diagnostic.v1`, so existing consumers may
|
|
509
|
-
continue using `safe_actions`.
|
|
510
|
-
|
|
511
|
-
- **`RESOURCE_CLAIM_CONFLICT`** (`session claim`/`session update`,
|
|
512
|
-
`authorize`, `guard --operation`) reports the blocking claim
|
|
513
|
-
(`ownerClaimId`, `ownerResource`, `ownerMode`) and the blocking session's
|
|
514
|
-
canonical identity (`ownerSessionId`, `ownerWorktree`, `ownerBranch`, and
|
|
515
|
-
`ownerLabel` when the session has one) in the same result, so a caller
|
|
516
|
-
never needs a second `session list` scan to find the owner.
|
|
517
|
-
- **`PROTECTED_WORKTREE`**/**`PROTECTED_BRANCH`** raised by a live command
|
|
518
|
-
(not by cleanup) add `phase: "execution"` and distinguish the current
|
|
519
|
-
(protected) execution context from the referenced `--session` target:
|
|
520
|
-
`requestedSessionId`, `targetWorktree`, `targetBranch`, and `targetState`
|
|
521
|
-
when that session exists. `safeActions` names the deterministic fix
|
|
522
|
-
(`run-from-managed-session-worktree`, `select-target-session-explicitly`)
|
|
523
|
-
instead of the unrelated cleanup-time hint.
|
|
524
|
-
- **`INVALID_SESSION_ID`** stays machine-ID based: an invalid `--session`
|
|
525
|
-
value is never silently reinterpreted as a label. When it exactly and
|
|
526
|
-
unambiguously matches one active session's label, the result adds
|
|
527
|
-
`session_id_hint` (the canonical session ID) and
|
|
528
|
-
`session_label_match: "unique"` as a non-authoritative hint. An ambiguous
|
|
529
|
-
or absent label match never guesses: `session_label_match` reports
|
|
530
|
-
`"ambiguous"` (with `session_label_match_count`) or `"none"` instead.
|
|
531
|
-
- **`RECOVERABLE_COMMITS`** raised by `session close` carries the same
|
|
532
|
-
`close_readiness`/`result_state` classification `session inspect` reports
|
|
533
|
-
for the identical state — `external_evidence_required` when ancestry alone
|
|
534
|
-
could not prove the branch safe and a `--integrated-revision` proof might
|
|
535
|
-
resolve it (e.g. after a squash/rebase merge), versus `blocked` when
|
|
536
|
-
supplied evidence failed to prove equivalence, versus `ambiguous` when Git
|
|
537
|
-
observation itself was inconclusive. For supplied evidence, bounded
|
|
538
|
-
`proofFailure` details distinguish an unauthoritative revision from a
|
|
539
|
-
tree-equivalence failure. The bounded evidence also includes
|
|
540
|
-
`currentSessionHead`, `suppliedIntegratedRevision`, `resolvedIntegrationSha`,
|
|
541
|
-
`lineageProof`/`authorityProof`, and `contentProof`. `safe_actions` includes
|
|
542
|
-
`discard-session` only as an explicit user choice; it does not authorize an
|
|
543
|
-
implicit cleanup fallback. Both surfaces reuse one authority, so a raw close
|
|
544
|
-
rejection and `session inspect` never drift apart.
|
|
545
|
-
|
|
546
|
-
None of the above weakens fail-closed behavior, changes an error code's
|
|
547
|
-
meaning, or performs any mutation while producing the rejection.
|
|
548
|
-
|
|
549
|
-
## Orchestrator integration
|
|
550
|
-
|
|
551
|
-
An external orchestrator can create a session, capture the returned
|
|
552
|
-
`session_id`, launch its worker with the returned `worktree` as `cwd`, and
|
|
553
|
-
check the guard before each Nawabari-governed mutation:
|
|
125
|
+
`session discard` requires an explicit session ID and may destroy unintegrated commits and uncommitted work in that session's worktree. Preview reports bounded destructive scope without mutation. Actual discard revalidates repository, worktree, branch, `HEAD`, and registry ownership before destructive steps.
|
|
554
126
|
|
|
555
|
-
|
|
556
|
-
created=$(git nawabari session create --branch feature/task --json)
|
|
557
|
-
session_id=$(printf '%s' "$created" | jq -r .session_id)
|
|
558
|
-
worktree=$(printf '%s' "$created" | jq -r .worktree)
|
|
127
|
+
`gc --dry-run` reports stale candidates and blockers. `gc --apply` only cleans candidates passing the same safety checks; elapsed age alone is not destructive authority. `doctor` reports prerequisite and reconciliation state without silently repairing ownership.
|
|
559
128
|
|
|
560
|
-
|
|
561
|
-
# run the worker in "$worktree"
|
|
562
|
-
git nawabari session close --session "$session_id" --json
|
|
563
|
-
```
|
|
129
|
+
## Governed Git work
|
|
564
130
|
|
|
565
|
-
|
|
566
|
-
the managed launcher instead of starting the worker directly:
|
|
131
|
+
`guard` and `authorize` are separate read-only boundaries:
|
|
567
132
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
133
|
+
- `guard` without an operation verifies the current physical worktree, branch, and session ownership/context. It does not evaluate resource claims.
|
|
134
|
+
- `authorize` evaluates a named operation against concrete resources, using the canonical operation policy and active claims. It does not grant or persist claims.
|
|
135
|
+
- `guard --operation <name> --resource <path>` remains a compatibility convenience for the combined claim-aware check. Use `authorize` when the operation decision itself is the intended boundary.
|
|
571
136
|
|
|
572
|
-
The
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
The orchestrator owns scheduling, prompts, and worker lifetime; Nawabari owns
|
|
577
|
-
only local session identity, worktree/branch ownership, and safe cleanup. No
|
|
578
|
-
Mottainai, GitHub, `gh`, network, or agent-runtime dependency is required.
|
|
579
|
-
|
|
580
|
-
Mottainai is one optional caller of this contract, not a runtime dependency.
|
|
581
|
-
It may retain task semantics, scheduling, validation policy, Issue/PR
|
|
582
|
-
governance, and worker lifetime. It must pass concrete local declarations to
|
|
583
|
-
Nawabari and retain the returned JSON identities. Nawabari does not import or
|
|
584
|
-
execute Mottainai/GitHub workflow code, infer claims from task text, or create
|
|
585
|
-
a second registry/database.
|
|
586
|
-
|
|
587
|
-
## Claim-aware operation authorization
|
|
588
|
-
|
|
589
|
-
`authorize` is the single decision surface for a governed local operation. Its
|
|
590
|
-
versioned vocabulary and required claim access are:
|
|
591
|
-
|
|
592
|
-
| operation | required access |
|
|
593
|
-
| ----------------- | ----------------- |
|
|
594
|
-
| `source-write` | `write` |
|
|
595
|
-
| `stage` | `write` |
|
|
596
|
-
| `commit` | `exclusive-write` |
|
|
597
|
-
| `branch-mutation` | `exclusive-write` |
|
|
598
|
-
| `push` | `exclusive-write` |
|
|
599
|
-
| `cleanup` | `exclusive-write` |
|
|
600
|
-
|
|
601
|
-
The request contains a session identity, an operation, and concrete
|
|
602
|
-
repository-relative resources. Nawabari independently verifies the current
|
|
603
|
-
repository, owned worktree, branch, active session, and persisted claims;
|
|
604
|
-
caller-supplied labels do not weaken that decision. The JSON result is the
|
|
605
|
-
automation contract and reports stable allow/deny codes such as
|
|
606
|
-
`MISSING_RESOURCE_CLAIM`, `INSUFFICIENT_CLAIM_MODE`, `RESOURCE_CLAIM_CONFLICT`,
|
|
607
|
-
`INVALID_RESOURCE`, and
|
|
608
|
-
the existing ownership/physical-observation codes.
|
|
609
|
-
|
|
610
|
-
`INSUFFICIENT_CLAIM_MODE` means a matching claim exists but its granted mode
|
|
611
|
-
is weaker than the operation requires. Its bounded details identify the
|
|
612
|
-
resource, required access, and matching granted mode names;
|
|
613
|
-
`MISSING_RESOURCE_CLAIM` remains reserved for an absent matching claim.
|
|
614
|
-
|
|
615
|
-
**`authorize` returns an authorization decision only; it does NOT execute the
|
|
616
|
-
operation itself.** Governed commit and push execution use this same decision
|
|
617
|
-
path before invoking bounded Git subprocesses.
|
|
137
|
+
The operation vocabulary is discoverable from the CLI and includes `source-write`, `stage`, `commit`, `branch-mutation`, `push`, and `cleanup`.
|
|
138
|
+
|
|
139
|
+
`checkpoint` and `evidence snapshot` describe Git-observable facts only. They do not infer task meaning, Issue ownership, or review status. `diff` requires explicit concrete paths and bounds optional patch output.
|
|
618
140
|
|
|
619
141
|
```bash
|
|
620
|
-
git nawabari
|
|
621
|
-
|
|
142
|
+
git nawabari commit --session "$session_id" --message "Update example" --resource src/example.ts --json
|
|
143
|
+
git nawabari commit --session "$session_id" --message "Update example" --all-claimed --json
|
|
144
|
+
git nawabari push --session "$session_id" --remote origin --branch feature/example --all-claimed --json
|
|
622
145
|
```
|
|
623
146
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
explicit list. JSON includes the resulting `commit_sha`.
|
|
628
|
-
|
|
629
|
-
Commit evidence distinguishes three sets: the caller's **declared/authorized**
|
|
630
|
-
resources (the explicit, claim-covered list a caller passed in), the
|
|
631
|
-
**staged** set Git reports as staged immediately before the commit runs, and
|
|
632
|
-
the **actual committed** set — read back from the resulting commit itself via
|
|
633
|
-
a bounded, NUL-safe `git diff-tree` observation, not inferred from staging
|
|
634
|
-
intent. The `resources` field in a successful `commit --json` result is
|
|
635
|
-
always the actual committed set, proven equal to or a subset of the
|
|
636
|
-
authorized resources; if Git staging/index drift between staging and the
|
|
637
|
-
commit (a hook, a concurrent process) causes the actual commit to contain a
|
|
638
|
-
path outside the authorized set, the result is not reported as an ordinary
|
|
639
|
-
successful commit — it fails with `COMMIT_RESULT_DIVERGED`, which retains the
|
|
640
|
-
resulting `commitSha` (the Git commit already happened) alongside the
|
|
641
|
-
authorized, actual, and divergent path sets for recovery/reconciliation.
|
|
642
|
-
|
|
643
|
-
If Git reports a bounded transport failure (timeout, output limit, or spawn
|
|
644
|
-
failure) after the commit invocation, Nawabari re-reads the local `HEAD` and
|
|
645
|
-
that commit's bounded changed-path set before classifying the outcome. A
|
|
646
|
-
failure whose `HEAD` is unchanged is reported with `outcome: "proven-absent"`
|
|
647
|
-
and `retrySafe: true`; a matching new commit is returned as a successful
|
|
648
|
-
result with `reconciliation.outcome: "proven-committed"` and its resulting
|
|
649
|
-
SHA; if either observation is unavailable or does not match the authorized
|
|
650
|
-
paths, the failure carries `outcome: "unresolved"` and `retrySafe: false`.
|
|
651
|
-
Unresolved outcomes never authorize a blind retry.
|
|
147
|
+
## Optional protected execution
|
|
148
|
+
|
|
149
|
+
Protected execution is an opt-in Linux-only mode beneath the existing Nawabari session and claim authority. It does not create a second session identity and does not turn ordinary `session create` work into a sandbox.
|
|
652
150
|
|
|
653
151
|
```bash
|
|
654
|
-
git nawabari
|
|
655
|
-
|
|
152
|
+
git nawabari session run --session "$session_id" --runtime-policy strict -- node worker.js
|
|
153
|
+
git nawabari session exec --session "$session_id" -- npm test
|
|
154
|
+
git nawabari session shell --session "$session_id" --runtime-policy compatibility
|
|
656
155
|
```
|
|
657
156
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
check runs only when a caller explicitly supplies a pattern, and a mismatch
|
|
662
|
-
fails with `INVALID_COMMIT_MESSAGE` before anything is staged. The pattern is
|
|
663
|
-
bounded to 512 characters and is evaluated before the repository lock is
|
|
664
|
-
acquired, so a pathological caller-supplied pattern cannot stall other
|
|
665
|
-
sessions' governed operations. A repository's own `commit-msg` Git hook (if
|
|
666
|
-
any) still runs normally, since governed commit invokes real `git commit`.
|
|
157
|
+
The `--` terminator is mandatory. The command is passed as argv and is not interpreted by a shell. The canonical profile gives the child a private root, `/tmp`, `/proc`, HOME, and cache state, mounts only the owned worktree read-write, and does not expose sibling worktrees or Nawabari control paths. Network mode is explicitly `inherited`, not isolated. Required Linux capabilities fail closed when unavailable; optional Landlock and cgroups v2 provide defense in depth when available.
|
|
158
|
+
|
|
159
|
+
Protected execution defaults to the strict `development` runtime profile. Only declared Node, Git, and pnpm material is projected through `/nawabari/bin`; `/usr`, `/bin`, `/nix/store`, the host home, and local user-tool directories are not implicitly visible. Compatibility is available only through the explicit `--runtime-policy compatibility` option.
|
|
667
160
|
|
|
668
161
|
```bash
|
|
669
|
-
git nawabari
|
|
670
|
-
--message 'feat: record the local change' --resource src/example.ts \
|
|
671
|
-
--message-pattern '^(feat|fix|docs|refactor|test|chore): .+$' --json
|
|
162
|
+
git nawabari doctor --json
|
|
672
163
|
```
|
|
673
164
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
pushes use the same exact-generation lease, while force authorization remains
|
|
680
|
-
separate. A new remote branch uses an empty lease, requiring the target ref to
|
|
681
|
-
remain absent. Nawabari fetches only the explicit remote branch into a
|
|
682
|
-
disposable ref when local ancestry is missing; it does not update tracking
|
|
683
|
-
refs or fetch unrelated branches/tags.
|
|
684
|
-
The JSON result includes the immutable `source_sha`, explicit `target_ref`,
|
|
685
|
-
observed `observed_remote_sha`, and relation. If a bounded transport failure
|
|
686
|
-
may have happened after the remote mutation, Nawabari re-observes only that
|
|
687
|
-
exact remote ref. It reports `reconciliation.outcome` as `proven-pushed`,
|
|
688
|
-
`proven-absent`, or `unresolved`, with the exact precondition and post-failure
|
|
689
|
-
generation evidence. Only a proven-absent outcome is retry-safe; unresolved
|
|
690
|
-
outcomes never authorize a blind retry.
|
|
165
|
+
See [Standalone Linux compatibility](docs/standalone-linux-compatibility.md) for platform-specific details.
|
|
166
|
+
|
|
167
|
+
## CLI and machine-readable discovery
|
|
168
|
+
|
|
169
|
+
The installed CLI is the primary integration surface. Discover its contract rather than hard-coding presentation output:
|
|
691
170
|
|
|
692
171
|
```bash
|
|
693
|
-
|
|
694
|
-
|
|
172
|
+
nawabari capabilities --json
|
|
173
|
+
nawabari --version --json
|
|
174
|
+
nawabari session create --help --json
|
|
175
|
+
nawabari commit --help --json
|
|
695
176
|
```
|
|
696
177
|
|
|
697
|
-
`
|
|
698
|
-
`unstaged`, and `untracked` path sets, canonicalizes them through the same
|
|
699
|
-
resource model, and reports `in_claim` and `out_of_claim` paths. Checkpoint
|
|
700
|
-
evidence is limited to the state Git exposes at that instant. Direct
|
|
701
|
-
filesystem activity that is reverted, ignored, or otherwise not observable in
|
|
702
|
-
the Git checkpoint is outside Nawabari's guarantee; this feature is not an
|
|
703
|
-
OS-level filesystem monitor.
|
|
704
|
-
|
|
705
|
-
Checkpoint canonicalization fails closed: a Git-reported path that cannot be
|
|
706
|
-
represented as a canonical repository resource (traversal, symlink escape, or
|
|
707
|
-
syntax reserved for the claim/glob model) never disappears from evidence.
|
|
708
|
-
Checkpoint fails the whole observation with `GIT_STATE_AMBIGUOUS` instead of
|
|
709
|
-
silently omitting the path, so a caller can never mistake an unrepresentable
|
|
710
|
-
observation for a clean one. This mirrors the strictness governed mutation
|
|
711
|
-
already applies to the same Git-observed paths, so checkpoint evidence is
|
|
712
|
-
never weaker than mutation authorization.
|
|
713
|
-
|
|
714
|
-
## Physical execution context
|
|
715
|
-
|
|
716
|
-
Nawabari treats Git and the canonical filesystem as the authority for every
|
|
717
|
-
governed session context. It independently observes the repository common
|
|
718
|
-
directory, worktree path, current branch, and current `HEAD`, then compares
|
|
719
|
-
those observations with the session registry. Caller-supplied paths and branch
|
|
720
|
-
labels are expectations only; they are never used to replace an observation
|
|
721
|
-
Git can make.
|
|
722
|
-
|
|
723
|
-
The shared verifier fails closed with stable registry reasons for detached
|
|
724
|
-
`HEAD`, missing or prunable worktrees, repository/worktree/branch mismatches,
|
|
725
|
-
stale or conflicting registry ownership, ambiguous Git state, and unavailable
|
|
726
|
-
physical observations. Git process failures remain distinct and bounded:
|
|
727
|
-
spawn failure, timeout, output-limit, and non-zero/unexpected exit.
|
|
728
|
-
|
|
729
|
-
Provisioning canonicalizes the managed root and every existing path segment
|
|
730
|
-
before invoking Git. Traversal, symlink/intermediate-segment escapes, existing
|
|
731
|
-
worktree paths, and existing local branches are rejected deterministically;
|
|
732
|
-
the repository lock serializes Nawabari provisioning and Git's own ref checks
|
|
733
|
-
remain the final collision authority.
|
|
734
|
-
|
|
735
|
-
An explicit `--base` ref that is empty, malformed, or does not resolve to a
|
|
736
|
-
commit fails with `INVALID_BASE_REF`. The bounded JSON details retain the
|
|
737
|
-
rejected ref, identify `HEAD` as the default recovery base, and include the
|
|
738
|
-
retry hint to omit `--base`; Nawabari does not enumerate or fuzzy-search refs.
|
|
739
|
-
|
|
740
|
-
## Repository state and concurrency
|
|
741
|
-
|
|
742
|
-
The authoritative registry is stored in the repository-common Git directory at
|
|
743
|
-
`.git/nawabari/session-registry.json`; linked worktrees therefore share one
|
|
744
|
-
registry. It records the schema version, repository identity, immutable session
|
|
745
|
-
ID, canonical worktree and branch identities, lifecycle state, and timestamps.
|
|
746
|
-
|
|
747
|
-
Ownership-changing writes use an exclusive repository-local lock and a synced
|
|
748
|
-
temporary file followed by atomic replacement. Concurrent creation cannot
|
|
749
|
-
silently duplicate an active worktree or branch. Lock recovery is conservative
|
|
750
|
-
and platform-qualified: stale-lock reclamation is supported only on Linux,
|
|
751
|
-
where the lock records a random token, PID, host, and the exact process-start
|
|
752
|
-
token from `/proc/<pid>/stat`. An owner is reclaimed only when the same host
|
|
753
|
-
proves that exact process identity is dead; elapsed age and PID liveness alone
|
|
754
|
-
are never reclaim authority. On non-Linux platforms, Node can run ordinary
|
|
755
|
-
Nawabari operations but does not provide a safe process-generation identity,
|
|
756
|
-
so stale local locks remain `LOCK_STALE` and require deliberate operator
|
|
757
|
-
remediation. Invalid, remote, or otherwise unverifiable lock metadata is never
|
|
758
|
-
stolen and fails closed. The same limitation is machine-readable under
|
|
759
|
-
`capabilities --json` at the `session-lifecycle.registry_lock_recovery`
|
|
760
|
-
contract.
|
|
761
|
-
|
|
762
|
-
### Conformance and extraction boundary
|
|
763
|
-
|
|
764
|
-
The packed-package suite exercises the complete standalone sequence, including
|
|
765
|
-
cross-process claim conflicts, governed commit/push, reconciliation, retryable
|
|
766
|
-
cleanup, and prunable worktree recovery. Native tests additionally cover
|
|
767
|
-
process interruption/atomic-write recovery, partial staging or commit failure,
|
|
768
|
-
stale physical state, cleanup races, bounded subprocess failures, and
|
|
769
|
-
idempotency (`src/registry/store.test.ts`, `src/git-mutation.test.ts`,
|
|
770
|
-
`src/cleanup-authority.test.ts`, `src/session-lifecycle.test.ts`, and
|
|
771
|
-
`scripts/smoke-test.mjs`).
|
|
772
|
-
|
|
773
|
-
The relevant Mottainai #28 execution cases are mapped as follows:
|
|
774
|
-
|
|
775
|
-
- repository/worktree identity, provisioning path safety, branch collision,
|
|
776
|
-
symlink escape, local staging/commit/push safety, cleanup revalidation, and
|
|
777
|
-
reconciliation are Nawabari-native authority and tests;
|
|
778
|
-
- task semantics, prompts, validation evidence policy, Conventional Commit and
|
|
779
|
-
PR/Issue governance, GitHub operations, and agent hooks remain optional
|
|
780
|
-
orchestrator-only semantics and must not move into Nawabari.
|
|
781
|
-
|
|
782
|
-
Run `pnpm run test:package` to validate the exact packed tarball and its
|
|
783
|
-
installed CLI, or `pnpm run verify` for the complete local conformance gate.
|
|
784
|
-
|
|
785
|
-
## Exact packed standalone protected-execution evidence
|
|
786
|
-
|
|
787
|
-
`pnpm run test:package:protected` is the package/evidence gate for the
|
|
788
|
-
standalone protected product. It creates one exact `pnpm pack` archive, records its
|
|
789
|
-
package/version, filename, byte size, SHA-256, source revision, and host
|
|
790
|
-
identity in `test-artifacts/packed-standalone-protected-execution.json`,
|
|
791
|
-
validates the archive contents, and installs that archive into a fresh
|
|
792
|
-
temporary consumer with `npm install --offline`. The default evidence report
|
|
793
|
-
is ignored by Git; pass `--evidence-output <path>` to retain it elsewhere and
|
|
794
|
-
`--keep-tarball` to retain the exact archive for inspection.
|
|
795
|
-
|
|
796
|
-
The smoke test invokes only the installed `nawabari` bin. Its package allowlist
|
|
797
|
-
contains `dist` runtime artifacts, `README.md`, `LICENSE`, and `package.json`;
|
|
798
|
-
source, test, and script modules are rejected, and the installed manifest must
|
|
799
|
-
not declare runtime dependencies. The lifecycle proof goes through the
|
|
800
|
-
installed public CLI for `capabilities --json`, `doctor --json`, session
|
|
801
|
-
creation/resolution, `session run`, resource claims, checkpoint, commit,
|
|
802
|
-
local-bare-remote push, and close. The gate requires the protected doctor
|
|
803
|
-
report to be ready; unavailable protected execution is a failure, not a skip
|
|
804
|
-
or an ambient fallback. The fixture uses only a temporary local repository and
|
|
805
|
-
local bare remote and has no Mottainai, GitHub, `gh`, LLM, or network
|
|
806
|
-
dependency.
|
|
807
|
-
|
|
808
|
-
The ordinary `pnpm run test:package` command runs the package/install smoke
|
|
809
|
-
without requiring a real protected host, so it retains the existing
|
|
810
|
-
compatibility CI job; it still verifies fail-closed rejection when protection
|
|
811
|
-
is unavailable. The `pnpm run test:package:protected` command is the #149
|
|
812
|
-
evidence command and must be run on a supported Linux host. It requires a
|
|
813
|
-
ready protected profile and fails when that prerequisite is unavailable.
|
|
814
|
-
|
|
815
|
-
The evidence supports these boundaries only:
|
|
816
|
-
|
|
817
|
-
- Process: on Linux with the required capabilities, the canonical launcher
|
|
818
|
-
establishes bubblewrap user, mount, PID, IPC, and UTS namespaces, applies
|
|
819
|
-
the versioned seccomp profile, and drops ambient capabilities. This is not a
|
|
820
|
-
VM or a claim about every host process.
|
|
821
|
-
- Filesystem: the protected child receives the authoritative session worktree
|
|
822
|
-
read-write, private session HOME/cache/`/tmp`/`/proc`, repository-owned
|
|
823
|
-
shared HOME state, and the fixed read-only runtime/tool inputs selected by
|
|
824
|
-
the profile. Sibling worktrees and unselected host HOME paths are not part
|
|
825
|
-
of the selected topology.
|
|
826
|
-
- HOME/cache: the child sees `/home/nawabari`; private state is per session,
|
|
827
|
-
while only the repository's selected shared-home subtree is shared. Selected
|
|
828
|
-
host tool directories are read-only inputs, not the host HOME.
|
|
829
|
-
- Network: `network_mode` is `inherited`; this evidence does not prove egress
|
|
830
|
-
isolation.
|
|
831
|
-
- Linux prerequisites: use `nawabari doctor --json` on a supported Linux host.
|
|
832
|
-
The package's supported Node.js engine, Git, and required bubblewrap,
|
|
833
|
-
namespace, seccomp, and capability support must be available and ready;
|
|
834
|
-
cgroups v2 and Landlock remain profile-reported optional defenses.
|
|
835
|
-
- Failure behavior: protected resolution uses `enforce: true`; missing
|
|
836
|
-
required capability, unsupported topology, or launch failure returns a
|
|
837
|
-
bounded failure and never retries through ambient execution.
|
|
838
|
-
|
|
839
|
-
## Packed Mottainai preselected-UID handoff evidence
|
|
840
|
-
|
|
841
|
-
`pnpm run test:package:mottainai` is the required-CI external-handoff gate for
|
|
842
|
-
Issue #150. `scripts/run-mottainai-uid-handoff-gate.mjs` runs the #149
|
|
843
|
-
protected package gate exactly once, retains that exact tarball and its
|
|
844
|
-
`nawabari.packed-standalone-protected-execution.v1` evidence, and passes only
|
|
845
|
-
those exact paths into `scripts/run-mottainai-uid-handoff.mjs`, which installs
|
|
846
|
-
that same tarball into a disposable consumer. `run-mottainai-uid-handoff.mjs`
|
|
847
|
-
itself has no self-pack path: it always requires an already-produced
|
|
848
|
-
`--tarball`/`--artifact-evidence` pair, so #150 can never hide a stale or
|
|
849
|
-
mismatched artifact behind a second pack. The fixture invokes the installed
|
|
850
|
-
`session run` contract under two distinct preselected unprivileged UIDs
|
|
851
|
-
(23001 and 23002 by default) and records bounded
|
|
852
|
-
artifact/fixture/UID/session/worktree/resource/Git evidence in
|
|
853
|
-
`test-artifacts/mottainai-packed-uid-handoff.json`. This gate runs in required
|
|
854
|
-
CI on a Linux host with bubblewrap (`mottainai-uid-handoff` job).
|
|
855
|
-
|
|
856
|
-
The checked-in `scripts/test-fixtures/mottainai-preselected-uid-runner.sh` is a
|
|
857
|
-
UID-only execution adapter. A real Mottainai Runtime may supply another
|
|
858
|
-
executable with the same `--uid`, `--root`, `--cwd`, `--` argv contract:
|
|
178
|
+
`capabilities --json` works without a Git repository. The top-level contract is `nawabari.standalone-execution.v1`, schema version `1`; Resource Claim meaning is separately versioned as `nawabari.resource-claims.v2`. Package version alone is not a compatibility decision.
|
|
859
179
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
180
|
+
JSON mode emits one bounded document on stdout. Consumers should use machine-readable fields and stable codes rather than parse human-oriented text.
|
|
181
|
+
|
|
182
|
+
The command surface includes Session lifecycle, Resource Claims, authorization/evidence, governed Git commit/push, reconciliation/discovery, and protected execution. Use `--help --json` and `capabilities --json` for the authoritative inventory.
|
|
183
|
+
|
|
184
|
+
## Stable package exports
|
|
185
|
+
|
|
186
|
+
Node consumers can use public projections without spawning the CLI:
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
import {
|
|
190
|
+
availableNawabariCommands,
|
|
191
|
+
classifyNawabariState,
|
|
192
|
+
getNawabariSessionStateSnapshot,
|
|
193
|
+
nawabariTransitionDecision,
|
|
194
|
+
} from "nawabari/state";
|
|
195
|
+
|
|
196
|
+
import { nawabariMachineContract } from "nawabari/contract";
|
|
197
|
+
|
|
198
|
+
import { generateNawabariProductStateManifest, serializeNawabariProductStateManifest } from "nawabari/manifest";
|
|
867
199
|
```
|
|
868
200
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
201
|
+
`nawabari/state` provides transport-neutral lifecycle projection and read-only observation of an existing session. `nawabari/contract` provides the installed machine-contract projection. `nawabari/manifest` provides the deterministic Product State Manifest projection.
|
|
202
|
+
|
|
203
|
+
These exports do not grant mutation authority and do not expose raw XState machines, actor references, internal state-node IDs, private context, or `dist/` deep imports. Mutations still go through authoritative runtime paths. See [XState state architecture](docs/architecture/xstate-state-architecture.md).
|
|
204
|
+
|
|
205
|
+
## Further reading
|
|
206
|
+
|
|
207
|
+
- [XState state architecture](docs/architecture/xstate-state-architecture.md): lifecycle authority, public projections, and integration boundaries.
|
|
208
|
+
- [Standalone Linux compatibility](docs/standalone-linux-compatibility.md): protected-execution compatibility and conformance details.
|
|
209
|
+
- [Release notes](docs/releases/): version-specific changes and migration context.
|
|
210
|
+
- [Contributing](CONTRIBUTING.md): development workflow and repository conventions.
|
|
211
|
+
- [Security policy](SECURITY.md): vulnerability reporting.
|
|
876
212
|
|
|
877
213
|
## Development
|
|
878
214
|
|
|
879
215
|
```bash
|
|
880
216
|
pnpm install --frozen-lockfile
|
|
881
|
-
pnpm run
|
|
217
|
+
pnpm run format:check
|
|
218
|
+
pnpm run lint
|
|
219
|
+
pnpm run typecheck
|
|
220
|
+
pnpm test
|
|
882
221
|
```
|
|
883
222
|
|
|
884
|
-
|
|
223
|
+
`pnpm run verify` runs the complete repository validation, including package and workflow checks.
|