nawabari 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/README.md +98 -0
  2. package/dist/cli-command-registry.d.ts +1116 -2
  3. package/dist/cli-command-registry.js +207 -6
  4. package/dist/cli-command-registry.js.map +1 -1
  5. package/dist/cli.d.ts +32 -11
  6. package/dist/cli.js +598 -159
  7. package/dist/cli.js.map +1 -1
  8. package/dist/contract.d.ts +6 -0
  9. package/dist/contract.js +212 -5
  10. package/dist/contract.js.map +1 -1
  11. package/dist/control-repositories.d.ts +43 -0
  12. package/dist/control-repositories.js +151 -0
  13. package/dist/control-repositories.js.map +1 -0
  14. package/dist/control-server.d.ts +40 -0
  15. package/dist/control-server.js +357 -0
  16. package/dist/control-server.js.map +1 -0
  17. package/dist/control-web.d.ts +12 -0
  18. package/dist/control-web.js +194 -0
  19. package/dist/control-web.js.map +1 -0
  20. package/dist/coordination-admission.d.ts +1 -0
  21. package/dist/coordination-admission.js +2 -0
  22. package/dist/coordination-admission.js.map +1 -0
  23. package/dist/coordination-preview.d.ts +107 -0
  24. package/dist/coordination-preview.js +401 -0
  25. package/dist/coordination-preview.js.map +1 -0
  26. package/dist/coordination-transactions.d.ts +131 -0
  27. package/dist/coordination-transactions.js +538 -0
  28. package/dist/coordination-transactions.js.map +1 -0
  29. package/dist/domain/auxiliary-state-policy.d.ts +98 -0
  30. package/dist/domain/auxiliary-state-policy.js +545 -0
  31. package/dist/domain/auxiliary-state-policy.js.map +1 -0
  32. package/dist/domain/cgroups-v2.d.ts +40 -2
  33. package/dist/domain/cgroups-v2.js +128 -22
  34. package/dist/domain/cgroups-v2.js.map +1 -1
  35. package/dist/domain/doctor.d.ts +10 -1
  36. package/dist/domain/doctor.js +12 -3
  37. package/dist/domain/doctor.js.map +1 -1
  38. package/dist/domain/errors.d.ts +2 -2
  39. package/dist/domain/errors.js +1 -0
  40. package/dist/domain/errors.js.map +1 -1
  41. package/dist/domain/fhs-development-runtime.d.ts +2 -1
  42. package/dist/domain/fhs-development-runtime.js +10 -2
  43. package/dist/domain/fhs-development-runtime.js.map +1 -1
  44. package/dist/domain/filesystem-enforcement-integration.d.ts +23 -0
  45. package/dist/domain/filesystem-enforcement-integration.js +34 -0
  46. package/dist/domain/filesystem-enforcement-integration.js.map +1 -0
  47. package/dist/domain/filesystem-policy-decision.d.ts +66 -0
  48. package/dist/domain/filesystem-policy-decision.js +203 -0
  49. package/dist/domain/filesystem-policy-decision.js.map +1 -0
  50. package/dist/domain/filesystem-policy-enforcement.d.ts +52 -0
  51. package/dist/domain/filesystem-policy-enforcement.js +340 -0
  52. package/dist/domain/filesystem-policy-enforcement.js.map +1 -0
  53. package/dist/domain/filesystem-policy-evidence.d.ts +128 -0
  54. package/dist/domain/filesystem-policy-evidence.js +791 -0
  55. package/dist/domain/filesystem-policy-evidence.js.map +1 -0
  56. package/dist/domain/filesystem-policy-materialization.d.ts +132 -0
  57. package/dist/domain/filesystem-policy-materialization.js +704 -0
  58. package/dist/domain/filesystem-policy-materialization.js.map +1 -0
  59. package/dist/domain/filesystem-policy-revision.d.ts +58 -0
  60. package/dist/domain/filesystem-policy-revision.js +199 -0
  61. package/dist/domain/filesystem-policy-revision.js.map +1 -0
  62. package/dist/domain/filesystem-policy.d.ts +146 -0
  63. package/dist/domain/filesystem-policy.js +942 -0
  64. package/dist/domain/filesystem-policy.js.map +1 -0
  65. package/dist/domain/landlock.d.ts +1 -0
  66. package/dist/domain/landlock.js +1 -1
  67. package/dist/domain/landlock.js.map +1 -1
  68. package/dist/domain/runtime-provider-declared.d.ts +98 -0
  69. package/dist/domain/runtime-provider-declared.js +416 -0
  70. package/dist/domain/runtime-provider-declared.js.map +1 -0
  71. package/dist/domain/runtime-resolution.d.ts +4 -0
  72. package/dist/domain/runtime-resolution.js +91 -1
  73. package/dist/domain/runtime-resolution.js.map +1 -1
  74. package/dist/domain/sandbox-launcher.d.ts +15 -2
  75. package/dist/domain/sandbox-launcher.js +359 -103
  76. package/dist/domain/sandbox-launcher.js.map +1 -1
  77. package/dist/domain/sandbox.d.ts +9 -1
  78. package/dist/domain/sandbox.js +1 -1
  79. package/dist/domain/sandbox.js.map +1 -1
  80. package/dist/domain/session-admission-decision.d.ts +67 -0
  81. package/dist/domain/session-admission-decision.js +200 -0
  82. package/dist/domain/session-admission-decision.js.map +1 -0
  83. package/dist/domain/session-backend.d.ts +47 -4
  84. package/dist/domain/session-backend.js +561 -36
  85. package/dist/domain/session-backend.js.map +1 -1
  86. package/dist/domain/session-bootstrap.d.ts +11 -0
  87. package/dist/domain/session-bootstrap.js +292 -0
  88. package/dist/domain/session-bootstrap.js.map +1 -0
  89. package/dist/domain/session-console.d.ts +120 -0
  90. package/dist/domain/session-console.js +610 -0
  91. package/dist/domain/session-console.js.map +1 -0
  92. package/dist/domain/session-environment.d.ts +114 -0
  93. package/dist/domain/session-environment.js +563 -0
  94. package/dist/domain/session-environment.js.map +1 -0
  95. package/dist/domain/session-execution-control.d.ts +114 -0
  96. package/dist/domain/session-execution-control.js +517 -0
  97. package/dist/domain/session-execution-control.js.map +1 -0
  98. package/dist/domain/session-execution-record.d.ts +163 -0
  99. package/dist/domain/session-execution-record.js +524 -0
  100. package/dist/domain/session-execution-record.js.map +1 -0
  101. package/dist/domain/session-git-hooks.d.ts +145 -0
  102. package/dist/domain/session-git-hooks.js +789 -0
  103. package/dist/domain/session-git-hooks.js.map +1 -0
  104. package/dist/domain/session-launch-supervisor-worker.d.ts +19 -0
  105. package/dist/domain/session-launch-supervisor-worker.js +261 -0
  106. package/dist/domain/session-launch-supervisor-worker.js.map +1 -0
  107. package/dist/domain/session-launch-supervisor.d.ts +142 -0
  108. package/dist/domain/session-launch-supervisor.js +591 -0
  109. package/dist/domain/session-launch-supervisor.js.map +1 -0
  110. package/dist/domain/session-process-observation.d.ts +84 -0
  111. package/dist/domain/session-process-observation.js +196 -0
  112. package/dist/domain/session-process-observation.js.map +1 -0
  113. package/dist/domain/session-protected-launch.d.ts +68 -0
  114. package/dist/domain/session-protected-launch.js +335 -0
  115. package/dist/domain/session-protected-launch.js.map +1 -0
  116. package/dist/domain/session-resource-accounting.d.ts +39 -0
  117. package/dist/domain/session-resource-accounting.js +183 -0
  118. package/dist/domain/session-resource-accounting.js.map +1 -0
  119. package/dist/domain/session.d.ts +87 -0
  120. package/dist/domain/session.js.map +1 -1
  121. package/dist/domain/shell-runtime.d.ts +22 -0
  122. package/dist/domain/shell-runtime.js +38 -0
  123. package/dist/domain/shell-runtime.js.map +1 -0
  124. package/dist/domain/worktree-file-operation-helper.d.ts +10 -0
  125. package/dist/domain/worktree-file-operation-helper.js +255 -0
  126. package/dist/domain/worktree-file-operation-helper.js.map +1 -0
  127. package/dist/domain/worktree-file-operation.d.ts +116 -0
  128. package/dist/domain/worktree-file-operation.js +529 -0
  129. package/dist/domain/worktree-file-operation.js.map +1 -0
  130. package/dist/domain/worktree-profile-builtins.d.ts +41 -0
  131. package/dist/domain/worktree-profile-builtins.js +239 -0
  132. package/dist/domain/worktree-profile-builtins.js.map +1 -0
  133. package/dist/domain/worktree-profile-catalog.d.ts +21 -0
  134. package/dist/domain/worktree-profile-catalog.js +163 -0
  135. package/dist/domain/worktree-profile-catalog.js.map +1 -0
  136. package/dist/domain/worktree-profile-inspection.d.ts +77 -0
  137. package/dist/domain/worktree-profile-inspection.js +114 -0
  138. package/dist/domain/worktree-profile-inspection.js.map +1 -0
  139. package/dist/domain/worktree-profile-overrides.d.ts +67 -0
  140. package/dist/domain/worktree-profile-overrides.js +685 -0
  141. package/dist/domain/worktree-profile-overrides.js.map +1 -0
  142. package/dist/domain/worktree-profile-pinning.d.ts +47 -0
  143. package/dist/domain/worktree-profile-pinning.js +96 -0
  144. package/dist/domain/worktree-profile-pinning.js.map +1 -0
  145. package/dist/domain/worktree-profile-runtime.d.ts +72 -0
  146. package/dist/domain/worktree-profile-runtime.js +221 -0
  147. package/dist/domain/worktree-profile-runtime.js.map +1 -0
  148. package/dist/domain/worktree-profile-scope.d.ts +54 -0
  149. package/dist/domain/worktree-profile-scope.js +285 -0
  150. package/dist/domain/worktree-profile-scope.js.map +1 -0
  151. package/dist/domain/worktree-runtime-profile.d.ts +99 -0
  152. package/dist/domain/worktree-runtime-profile.js +505 -0
  153. package/dist/domain/worktree-runtime-profile.js.map +1 -0
  154. package/dist/errors.d.ts +1 -1
  155. package/dist/errors.js.map +1 -1
  156. package/dist/failure-code-vocabulary.d.ts +4 -1
  157. package/dist/failure-code-vocabulary.js +53 -1
  158. package/dist/failure-code-vocabulary.js.map +1 -1
  159. package/dist/git.d.ts +2 -0
  160. package/dist/git.js +18 -0
  161. package/dist/git.js.map +1 -1
  162. package/dist/public-state.d.ts +21 -0
  163. package/dist/public-state.js +25 -0
  164. package/dist/public-state.js.map +1 -1
  165. package/dist/registry/file-operation-record.d.ts +169 -0
  166. package/dist/registry/file-operation-record.js +634 -0
  167. package/dist/registry/file-operation-record.js.map +1 -0
  168. package/dist/registry/runtime-records.d.ts +59 -0
  169. package/dist/registry/runtime-records.js +426 -0
  170. package/dist/registry/runtime-records.js.map +1 -0
  171. package/dist/repository-runtime-observations.d.ts +56 -0
  172. package/dist/repository-runtime-observations.js +388 -0
  173. package/dist/repository-runtime-observations.js.map +1 -0
  174. package/dist/repository-runtime-snapshot.d.ts +52 -0
  175. package/dist/repository-runtime-snapshot.js +170 -0
  176. package/dist/repository-runtime-snapshot.js.map +1 -0
  177. package/dist/resource-claims.d.ts +31 -7
  178. package/dist/resource-claims.js +68 -15
  179. package/dist/resource-claims.js.map +1 -1
  180. package/dist/resource-coordination-cli.d.ts +9 -0
  181. package/dist/resource-coordination-cli.js +199 -0
  182. package/dist/resource-coordination-cli.js.map +1 -0
  183. package/dist/resource-coordination-evidence.d.ts +185 -0
  184. package/dist/resource-coordination-evidence.js +750 -0
  185. package/dist/resource-coordination-evidence.js.map +1 -0
  186. package/dist/resource-coordination-snapshot.d.ts +181 -0
  187. package/dist/resource-coordination-snapshot.js +433 -0
  188. package/dist/resource-coordination-snapshot.js.map +1 -0
  189. package/dist/resource-coordination-view.d.ts +60 -0
  190. package/dist/resource-coordination-view.js +342 -0
  191. package/dist/resource-coordination-view.js.map +1 -0
  192. package/dist/resource-coordination.d.ts +125 -0
  193. package/dist/resource-coordination.js +482 -0
  194. package/dist/resource-coordination.js.map +1 -0
  195. package/dist/resource-handoff-execution.d.ts +14 -0
  196. package/dist/resource-handoff-execution.js +111 -0
  197. package/dist/resource-handoff-execution.js.map +1 -0
  198. package/dist/resource-handoff.d.ts +172 -0
  199. package/dist/resource-handoff.js +576 -0
  200. package/dist/resource-handoff.js.map +1 -0
  201. package/dist/resource-merge-decision.d.ts +54 -0
  202. package/dist/resource-merge-decision.js +287 -0
  203. package/dist/resource-merge-decision.js.map +1 -0
  204. package/dist/resource-text-merge.d.ts +63 -0
  205. package/dist/resource-text-merge.js +254 -0
  206. package/dist/resource-text-merge.js.map +1 -0
  207. package/dist/session-attention.d.ts +41 -0
  208. package/dist/session-attention.js +226 -0
  209. package/dist/session-attention.js.map +1 -0
  210. package/dist/session-console-cli.d.ts +38 -0
  211. package/dist/session-console-cli.js +132 -0
  212. package/dist/session-console-cli.js.map +1 -0
  213. package/dist/session-parking.d.ts +54 -0
  214. package/dist/session-parking.js +348 -0
  215. package/dist/session-parking.js.map +1 -0
  216. package/dist/session-registry.d.ts +233 -18
  217. package/dist/session-registry.js +1991 -83
  218. package/dist/session-registry.js.map +1 -1
  219. package/dist/session-retention.d.ts +211 -0
  220. package/dist/session-retention.js +428 -0
  221. package/dist/session-retention.js.map +1 -0
  222. package/dist/session-runtime-history.d.ts +26 -0
  223. package/dist/session-runtime-history.js +48 -0
  224. package/dist/session-runtime-history.js.map +1 -0
  225. package/dist/session-runtime-lifecycle.d.ts +142 -0
  226. package/dist/session-runtime-lifecycle.js +188 -0
  227. package/dist/session-runtime-lifecycle.js.map +1 -0
  228. package/dist/session-runtime-reconciliation.d.ts +22 -0
  229. package/dist/session-runtime-reconciliation.js +159 -0
  230. package/dist/session-runtime-reconciliation.js.map +1 -0
  231. package/dist/ui/repository-screen.d.ts +59 -0
  232. package/dist/ui/repository-screen.js +323 -0
  233. package/dist/ui/repository-screen.js.map +1 -0
  234. package/dist/ui/repository-terminal.d.ts +42 -0
  235. package/dist/ui/repository-terminal.js +414 -0
  236. package/dist/ui/repository-terminal.js.map +1 -0
  237. package/dist/ui/session-actions.d.ts +77 -0
  238. package/dist/ui/session-actions.js +711 -0
  239. package/dist/ui/session-actions.js.map +1 -0
  240. package/dist/verification-executor.d.ts +6 -1
  241. package/dist/verification-executor.js +7 -1
  242. package/dist/verification-executor.js.map +1 -1
  243. package/dist/worktree-file-operation-cli.d.ts +68 -0
  244. package/dist/worktree-file-operation-cli.js +470 -0
  245. package/dist/worktree-file-operation-cli.js.map +1 -0
  246. package/dist/worktree-profile-cli.d.ts +137 -0
  247. package/dist/worktree-profile-cli.js +426 -0
  248. package/dist/worktree-profile-cli.js.map +1 -0
  249. package/package.json +1 -1
package/README.md CHANGED
@@ -1,3 +1,14 @@
1
+ <p align="center">
2
+ <img src="./docs/assets/readme/nawabari-hero.webp" alt="Nawabari — Git Worktree Isolation." width="100%">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://github.com/yohn-jp/nawabari/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/yohn-jp/nawabari/actions/workflows/ci.yml/badge.svg"></a>
7
+ <a href="https://www.npmjs.com/package/nawabari"><img alt="npm" src="https://img.shields.io/npm/v/nawabari"></a>
8
+ <a href="https://www.npmjs.com/package/nawabari"><img alt="Node" src="https://img.shields.io/node/v/nawabari"></a>
9
+ <a href="./LICENSE"><img alt="License" src="https://img.shields.io/npm/l/nawabari"></a>
10
+ </p>
11
+
1
12
  # Nawabari
2
13
 
3
14
  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.
@@ -69,6 +80,77 @@ worktree=$(printf '%s' "$created" | jq -r .worktree)
69
80
 
70
81
  The initial-claim grammar is `--resource <path-or-glob> --mode <read|write|exclusive-write>` and the pair may be repeated. Each resource is paired with its own mode. The parser also permits zero pairs for backward compatibility, but the canonical routine path declares at least one initial claim. Initial claims are committed atomically with the new session, worktree, and branch. A conflict returns a machine-readable failure such as `RESOURCE_CLAIM_CONFLICT` and does not leave a partially established session or claim set.
71
82
 
83
+ Resource-claim enforcement is disabled by default for a new session: `commit`/`push` authorization does not require the session to hold a resource claim for its own session-owned operations. Pass `--enforce-claims` to `session create` to opt that session into the previous claim-authorization behavior, including `MISSING_RESOURCE_CLAIM`/`INSUFFICIENT_CLAIM_MODE` denials and existing claim-mode compatibility rules. Worktree ownership, branch ownership, and `RESOURCE_CLAIM_CONFLICT` protection against another session's active claim remain enforced either way.
84
+
85
+ ### Working-set artifacts
86
+
87
+ For a bounded session, supply **both** `--execution-scope-file` and `--candidate-working-set-file` to `session create`. The JSON below illustrates the versioned fields accepted by the [canonical parsers](./src/working-set.ts). Replace the identity, revision, digest, and paths with values from the implementation authorization and the repository being bootstrapped. `repositoryHost` and `repositoryId` must agree between the two artifacts and the authorization; `repository` is optional in the execution scope and required in the candidate. The candidate `revision` and execution-scope `base.revision` must equal the session's resolved Git base revision (40 or 64 hexadecimal characters). `base.branch` names that base; `base.freshness` and the top-level execution-scope `branch` are optional bounded strings.
88
+
89
+ `execution-scope.json`:
90
+
91
+ ```json
92
+ {
93
+ "version": 1,
94
+ "kind": "implementation-execution-scope",
95
+ "authorization": {
96
+ "version": 1,
97
+ "kind": "implementation-authorization",
98
+ "contractVersion": 1,
99
+ "implementation": {
100
+ "repositoryHost": "github.com",
101
+ "repositoryId": "1329799765",
102
+ "repository": "yohn-jp/nawabari",
103
+ "number": 659
104
+ },
105
+ "governedBodyDigest": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
106
+ },
107
+ "repository": { "repositoryHost": "github.com", "repositoryId": "1329799765", "repository": "yohn-jp/nawabari" },
108
+ "base": { "branch": "main", "revision": "e0e3c4376c9d70c87f24c7211b5ded1f3d58a983" },
109
+ "scope": {
110
+ "readOnly": ["README.md", "src/**"],
111
+ "write": [],
112
+ "create": [],
113
+ "delete": [],
114
+ "deny": []
115
+ }
116
+ }
117
+ ```
118
+
119
+ `candidate-working-set.json`:
120
+
121
+ ```json
122
+ {
123
+ "kind": "candidate-working-set",
124
+ "schemaVersion": 1,
125
+ "workingSetId": "implementation-659-candidate-v1",
126
+ "repository": { "repositoryHost": "github.com", "repositoryId": "1329799765", "repository": "yohn-jp/nawabari" },
127
+ "revision": "e0e3c4376c9d70c87f24c7211b5ded1f3d58a983",
128
+ "entries": [
129
+ {
130
+ "state": "required",
131
+ "target": { "kind": "file", "locator": "README.md" },
132
+ "reason": { "id": "implementation-659", "summary": "Read the public contract" },
133
+ "evidence": [{ "artifact": "implementation-659", "reference": "working-set-bootstrap" }]
134
+ }
135
+ ]
136
+ }
137
+ ```
138
+
139
+ The execution scope is the maximum authority: all five arrays (`readOnly`, `write`, `create`, `delete`, `deny`) are required, contain canonical repository-relative path selectors, and may be empty. The authorization's `implementation.number` is a positive integer and `governedBodyDigest` is a 64-character lowercase hexadecimal digest from the governing authorization. `implementation.repository` is optional. Candidate `entries` may be empty; each entry requires `state` (`required`, `supporting`, `verification`, or `unresolved`), `target` (`kind`: `file`, `symbol`, `test`, or `unresolved`; plus a nonempty `locator`), `reason` (`id` and `summary`), and an `evidence` array of `{ "artifact", "reference" }` objects. An `unresolved` state requires an `unresolved` target kind; concrete states require a concrete target kind. Candidate entries describe need, not permission. Unknown fields are rejected; the parser in `src/working-set.ts` is the contract authority.
140
+
141
+ ```bash
142
+ nawabari session create --base main --execution-scope-file execution-scope.json \
143
+ --candidate-working-set-file candidate-working-set.json --json
144
+ nawabari session show --session "$session_id" --json
145
+ nawabari session scope expand --help --json
146
+ nawabari session scope expand --session "$session_id" --repository 1329799765 \
147
+ --repository-host github.com --revision "$revision" \
148
+ --execution-scope-file execution-scope.json --path src/new-context.ts \
149
+ --operation READONLY --reason 'Needed for current task' --json
150
+ ```
151
+
152
+ Read `working_set.revision` from `session show --json` before expansion. A granted expansion advances that revision and appends `working_set.history`; a stale revision or different execution-scope provenance is rejected without changing the working set. The requested path must be within the original execution-scope maximum and outside its `deny` selectors. READONLY expansion grants no WRITE, CREATE, or DELETE authority. Mutation still follows the existing claim and scope checks. If a resource handoff reports `Destination maximum scope is unavailable`, inspect the destination and explicitly expand its scope first; retry `session handoff` with fresh claim-set generation through the normal handoff command. Handoff never expands destination scope itself.
153
+
72
154
  The packed auxiliary-state declaration above is the bounded `copy` form: a `repository-local` source is copied to a `managed-worktree` target with `durability: durable`. It is an explicit, repeatable, allowlisted capability. It does not discover ignored state, project process-local sockets/PID files/logs, shadow Git-tracked paths, or expose arbitrary host filesystem paths. Auxiliary-state projection is separate from `SessionRuntimeProjection`: the former copies declared repository-local durable state for a managed worktree; the latter describes explicit runtime material and filesystem visibility for protected execution. Auxiliary state does not change the runtime projection.
73
155
 
74
156
  The create operation is atomic, but a caller must treat an uncertain result carefully. If JSON reports `REGISTRY_DURABILITY_UNCERTAIN`, re-read the reported session and claims before retrying. If the exact original declaration is already present, follow `bootstrap_retry.next_action: inspect-established-session` and inspect that `session_id`; if another declaration owns the worktree or branch, follow `bootstrap_retry.next_action: inspect-blocking-session`. Nawabari never silently adopts an existing owner. A retry is appropriate only after the authoritative state proves that the requested bootstrap was not established.
@@ -247,6 +329,22 @@ JSON mode emits one bounded document on stdout. Consumers should use machine-rea
247
329
 
248
330
  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. Human-readable guidance and agent integrations use these same command and action identifiers; there is no separate human or agent workflow.
249
331
 
332
+ `src/cli-command-registry.ts` is the single canonical authority for that surface: every command/option name is a `CommandId`/`OptionId` literal type derived directly from the registry data (not hand-typed), and `--help`, `capabilities`, and the executable dispatcher's own accepted-flag parsing all read that same data. There is no second command or option table to keep in sync.
333
+
334
+ ### Optional machine-local Control Server
335
+
336
+ ```bash
337
+ nawabari server [--port <port>]
338
+ ```
339
+
340
+ `nawabari server` runs one foreground Control Server and built-in Web UI at `http://127.0.0.1:47471/` (default port `47471`; `--port` selects another; an occupied port fails instead of choosing another endpoint). The listener binds IPv4 loopback `127.0.0.1` only and the bind address is not configurable. Stop it with Ctrl-C or `SIGTERM`.
341
+
342
+ One listener serves every locally known Nawabari repository. Repository discovery uses a machine-local locator catalog (`$XDG_STATE_HOME/nawabari/control-repositories.json`, default `~/.local/state/nawabari/`) that holds only repository identity (common Git directory) and worktree path; `session create` and `server` record the current repository when it already has a Nawabari registry. The catalog is discovery metadata, not authority: each request reopens that repository's own backend, and each repository's registry, lifecycle, claims, runtime and filesystem authority stay independent.
343
+
344
+ The HTTP v1 API is `GET /api/v1/health`, `GET /api/v1/repositories`, `GET /api/v1/repositories/:repositoryKey/snapshot`, `GET /api/v1/repositories/:repositoryKey/sessions/:sessionId`, and `POST /api/v1/repositories/:repositoryKey/sessions/:sessionId/actions`. Reads re-project the canonical `RepositoryRuntimeSnapshot`; actions accept only the typed `session action` contract (`action_id`, `token`, `confirmation`) and delegate to the repository's `SessionActionDispatcher`, so stale evidence fails closed (HTTP 409) and `discard-session` still needs the authoritative preview plus explicit confirmation. No route executes command text.
345
+
346
+ Every API request needs the `x-nawabari-control-token` header. The token is random per start, bootstrapped only into the same-origin root document, and never printed, logged, persisted, or put in URLs. Requests with an unexpected `Host` or a foreign `Origin` are rejected, no CORS headers are sent, and actions accept bounded `application/json` bodies only. The Web UI polls every 3 seconds and has a manual refresh; it offers only the actions listed by the current canonical diagnostic. The server is optional: every other command, including `nawabari ui`, keeps calling the backend directly.
347
+
250
348
  ## Stable package exports
251
349
 
252
350
  Node consumers can use public projections without spawning the CLI: