nawabari 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +347 -5
- package/dist/cli.js +770 -51
- package/dist/cli.js.map +1 -1
- package/dist/contract.d.ts +9 -0
- package/dist/contract.js +291 -0
- package/dist/contract.js.map +1 -0
- package/dist/domain/doctor.d.ts +1 -1
- package/dist/domain/doctor.js +99 -90
- 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/session-backend.d.ts +15 -3
- package/dist/domain/session-backend.js +348 -7
- package/dist/domain/session-backend.js.map +1 -1
- package/dist/domain/session.d.ts +247 -2
- package/dist/domain/session.js +42 -0
- package/dist/domain/session.js.map +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/git.d.ts +102 -0
- package/dist/git.js +714 -30
- package/dist/git.js.map +1 -1
- package/dist/operation-authorization.d.ts +76 -0
- package/dist/operation-authorization.js +41 -0
- package/dist/operation-authorization.js.map +1 -0
- package/dist/output-budget.d.ts +16 -0
- package/dist/output-budget.js +58 -0
- package/dist/output-budget.js.map +1 -0
- package/dist/presentation.js +76 -22
- package/dist/presentation.js.map +1 -1
- package/dist/repository-evidence.d.ts +74 -0
- package/dist/repository-evidence.js +7 -0
- package/dist/repository-evidence.js.map +1 -0
- package/dist/resource-claims.d.ts +87 -0
- package/dist/resource-claims.js +450 -0
- package/dist/resource-claims.js.map +1 -0
- package/dist/session-registry.d.ts +251 -1
- package/dist/session-registry.js +2094 -257
- package/dist/session-registry.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -24,6 +24,87 @@ git nawabari --help
|
|
|
24
24
|
nawabari --version
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## Standalone machine contract
|
|
28
|
+
|
|
29
|
+
The installed CLI/JSON surface is the integration boundary. An orchestrator
|
|
30
|
+
must discover the contract before using the lifecycle:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
nawabari capabilities --json
|
|
34
|
+
nawabari --version --json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Both discovery commands work without a Git repository. A compatible
|
|
38
|
+
installation reports `contract_id: "nawabari.standalone-execution.v1"` and
|
|
39
|
+
`schema_version: 1`. The capability response lists the exact commands,
|
|
40
|
+
result-schema versions, identity fields, and stable `failure_codes`. The
|
|
41
|
+
package version is release metadata; it is not a substitute for the
|
|
42
|
+
machine-contract identifier.
|
|
43
|
+
|
|
44
|
+
The supported standalone sequence is:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
session create -> session claim(s) -> authorize/checkpoint
|
|
48
|
+
-> commit/push -> doctor (reconciliation) -> session close/gc
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The JSON envelope is one document on stdout. Success has `ok: true`, a
|
|
52
|
+
`command`, and the command's versioned result fields. Failure has `ok: false`,
|
|
53
|
+
the `command`, a stable `code`, a bounded human-readable `message`, and
|
|
54
|
+
optional structured `details`; JSON mode writes no decorative stderr. Exit
|
|
55
|
+
codes are `0` success, `2` usage, `3` rejected/unsafe operation, `4`
|
|
56
|
+
unavailable capability, `5` failed doctor checks, and `70` unexpected internal
|
|
57
|
+
failure. Consumers must use these fields and codes, never human presentation.
|
|
58
|
+
|
|
59
|
+
The result schemas expose the following identities:
|
|
60
|
+
|
|
61
|
+
| Surface | Versioned identities |
|
|
62
|
+
| ---------------------- | -------------------------------------------------------------------------------- |
|
|
63
|
+
| session lifecycle | `session_id`, `repository`, `worktree`, `branch`, `state` |
|
|
64
|
+
| claims | `claim_id`, `session_id`, `resource`, `mode` |
|
|
65
|
+
| authorization | `operation`, `allowed`, `code`, `claim_ids` |
|
|
66
|
+
| checkpoint evidence | `head`, `changed`, `staged`, `unstaged`, `untracked`, `in_claim`, `out_of_claim` |
|
|
67
|
+
| repository evidence | `session_id`, `base_revision`, `head`, `clean`, `paths.stats`, `evidence_hash` |
|
|
68
|
+
| bounded diff | `from_revision`, `to_revision`, `paths`, `stats`, `patch`, `evidence_hash` |
|
|
69
|
+
| commit/push | `commit_sha`, `remote`, `branch`, `target`, `relation` |
|
|
70
|
+
| reconciliation/cleanup | `clean`, `issues`, `candidates`, `cleaned`, `blocked`, `recovery_hints` |
|
|
71
|
+
|
|
72
|
+
Git subprocesses are bounded at 10 seconds and 64 KiB of output; checkpoint
|
|
73
|
+
evidence is bounded to 4,096 paths. `GIT_SPAWN_FAILED`, `GIT_TIMEOUT`,
|
|
74
|
+
`GIT_OUTPUT_LIMIT`, and `GIT_COMMAND_FAILED` remain distinct failure codes.
|
|
75
|
+
The local lifecycle requires Git and the repository-local registry/lock only;
|
|
76
|
+
it does not require Mottainai, GitHub, `gh`, network access, an LLM, or a
|
|
77
|
+
coding-agent runtime.
|
|
78
|
+
|
|
79
|
+
## Read-only repository evidence
|
|
80
|
+
|
|
81
|
+
The evidence family is session-addressed and has no task, Issue, semantic, or
|
|
82
|
+
GitHub interpretation. It is the physical repository authority for one owned
|
|
83
|
+
session:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
git nawabari evidence snapshot --session "$NAWABARI_SESSION_ID" --json
|
|
87
|
+
git nawabari diff --session "$NAWABARI_SESSION_ID" --path src/example.ts --json
|
|
88
|
+
git nawabari diff --session "$NAWABARI_SESSION_ID" --path src/example.ts \
|
|
89
|
+
--patch --max-bytes 32768 --max-hunks 32 --json
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`evidence snapshot` verifies the registry's repository/worktree/branch owner,
|
|
93
|
+
then reuses checkpoint's exact NUL-safe Git observation for `changed`,
|
|
94
|
+
`staged`, `unstaged`, and `untracked` paths. It also reports canonical per-path
|
|
95
|
+
stats, `clean`, the current `head`, session state, and an `evidence_hash`.
|
|
96
|
+
New sessions persist the exact creation/base revision as `base_revision`;
|
|
97
|
+
legacy records that lack this field report `base_revision: null` and
|
|
98
|
+
`base_revision_proven: false` rather than inferring it from a mutable ref.
|
|
99
|
+
|
|
100
|
+
`diff` requires at least one explicit concrete path and never accepts a glob or
|
|
101
|
+
an empty repository-wide selection. Stats are returned by default. Patch text
|
|
102
|
+
requires `--patch` and is bounded to at most 64 paths, 64 KiB, and 128 hunks;
|
|
103
|
+
the caller may request smaller limits. Unrepresentable Git observations fail
|
|
104
|
+
with `GIT_STATE_AMBIGUOUS`; a requested path whose stat is not exposed by Git
|
|
105
|
+
remains in the result with `available: false` and makes snapshot evidence
|
|
106
|
+
`complete: false`, so no path silently disappears.
|
|
107
|
+
|
|
27
108
|
## Session lifecycle
|
|
28
109
|
|
|
29
110
|
Session IDs are generated automatically as UUIDv7 values. They are immutable
|
|
@@ -41,6 +122,11 @@ git nawabari gc --dry-run --json
|
|
|
41
122
|
git nawabari doctor --json
|
|
42
123
|
```
|
|
43
124
|
|
|
125
|
+
`status --json` reports the resolved `managed_worktree_root` used when
|
|
126
|
+
`session create` omits `--worktree`. `session create --help --json` describes
|
|
127
|
+
all four create options as optional and reports defaults for branch, worktree,
|
|
128
|
+
base (`HEAD`), and label.
|
|
129
|
+
|
|
44
130
|
`session create` provisions a dedicated worktree and mutable branch atomically
|
|
45
131
|
under the repository-scoped mutation lock. The default/integration worktree
|
|
46
132
|
and its protected branch cannot be session resources. `session id` and the
|
|
@@ -52,7 +138,96 @@ state, and commits not proven reachable from the integration branch block
|
|
|
52
138
|
destructive cleanup. A clean close releases only the owned worktree and
|
|
53
139
|
branch, and repeating close is idempotent. `gc` detects stale or interrupted
|
|
54
140
|
sessions; `--apply` uses the same close safety checks and reports blocked
|
|
55
|
-
sessions instead of guessing.
|
|
141
|
+
sessions instead of guessing. `gc --dry-run` performs the same non-mutating
|
|
142
|
+
cleanup preflight and includes stable blocker codes and `recovery_hints` for
|
|
143
|
+
every candidate that is not safe. Cleanup revalidates the physical worktree,
|
|
144
|
+
branch, and `HEAD` observations immediately before each destructive Git
|
|
145
|
+
operation.
|
|
146
|
+
|
|
147
|
+
Routine `session list` and `status` output excludes `closed` history and is
|
|
148
|
+
limited to 64 records. Use `--all` (or `--history`) for an explicit complete
|
|
149
|
+
history view; closed records remain persisted and are never silently deleted
|
|
150
|
+
by listing or cleanup.
|
|
151
|
+
|
|
152
|
+
`gc` stale eligibility is separate from closed-history retention. Its default
|
|
153
|
+
threshold is 24 hours (`86,400,000` ms), measured from persisted `updated_at`;
|
|
154
|
+
records already in `stale` or `closing` state are eligible, and an otherwise
|
|
155
|
+
live record is also eligible when Git reports its registered worktree as
|
|
156
|
+
missing or prunable. Physical Git/worktree state is authoritative for that
|
|
157
|
+
check. `gc --dry-run` and `gc --apply` do not treat a closed record as a stale
|
|
158
|
+
cleanup candidate.
|
|
159
|
+
|
|
160
|
+
`doctor` includes a non-destructive `reconciliation` check. It reports
|
|
161
|
+
registry/Git ownership drift, including missing or prunable worktrees and
|
|
162
|
+
unregistered physical worktrees, without repairing or deleting anything.
|
|
163
|
+
|
|
164
|
+
## Session resource claims
|
|
165
|
+
|
|
166
|
+
Resource claims are versioned, session-scoped ownership records stored in the
|
|
167
|
+
same repository registry and protected by the same mutation lock. They are
|
|
168
|
+
caller declarations; Nawabari does not infer them from task text or source
|
|
169
|
+
code. Claim JSON exposes `schema_version`, `claim_id`, `session_id`, the
|
|
170
|
+
repository/worktree identities, canonical `resource`, `mode`, and timestamps.
|
|
171
|
+
The claim schema version is `2` and supports `read`, `write`, and
|
|
172
|
+
`exclusive-write`. Schema v1 records use different overlap semantics and are
|
|
173
|
+
not interpreted implicitly: an embedding caller must explicitly run
|
|
174
|
+
`SessionRegistry.migrate()` before using them.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
git nawabari session claim --session "$NAWABARI_SESSION_ID" \
|
|
178
|
+
--resource 'src/**/*.ts' --mode read --json
|
|
179
|
+
git nawabari session claims --session "$NAWABARI_SESSION_ID" --json
|
|
180
|
+
git nawabari session update --session "$NAWABARI_SESSION_ID" \
|
|
181
|
+
--resource 'src/**/*.ts' --mode write --json
|
|
182
|
+
git nawabari session release --session "$NAWABARI_SESSION_ID" --json
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The modes have these normative meanings:
|
|
186
|
+
|
|
187
|
+
- `read`: a non-mutating access declaration. It is not a consistency lease,
|
|
188
|
+
so it may overlap an ordinary `write` claim.
|
|
189
|
+
- `write`: ordinary source-modification authority. It may overlap `read`, but
|
|
190
|
+
not another writer or any `exclusive-write` claim.
|
|
191
|
+
- `exclusive-write`: stronger ownership-sensitive mutation authority. It
|
|
192
|
+
excludes every overlapping claim, including `read`.
|
|
193
|
+
|
|
194
|
+
Overlapping claims use this complete compatibility matrix; non-overlapping
|
|
195
|
+
claims are compatible for every mode:
|
|
196
|
+
|
|
197
|
+
| existing \/ requested | read | write | exclusive-write |
|
|
198
|
+
| --------------------- | ---------- | ---------- | --------------- |
|
|
199
|
+
| read | compatible | compatible | conflict |
|
|
200
|
+
| write | compatible | conflict | conflict |
|
|
201
|
+
| exclusive-write | conflict | conflict | conflict |
|
|
202
|
+
|
|
203
|
+
Claims use canonical repository-relative POSIX paths. Literal path segments,
|
|
204
|
+
`*`/`?` segment wildcards, and a complete `**` segment are supported. Empty,
|
|
205
|
+
`.`/`..`, absolute, drive-relative, backslash, unsupported-glob, and
|
|
206
|
+
symlink-escaping forms are rejected with stable machine-readable codes.
|
|
207
|
+
Equivalent claim acquisition and release retries are idempotent. Closing or
|
|
208
|
+
garbage-collecting a session releases its claims; no separate claim registry
|
|
209
|
+
or claim lock exists. Claims describe ownership state only and do not provide
|
|
210
|
+
OS-level filesystem observation or a filesystem sandbox.
|
|
211
|
+
|
|
212
|
+
An ordinary source change uses `write` and can proceed while another session
|
|
213
|
+
holds a `read` declaration:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
git nawabari session claim --session "$NAWABARI_SESSION_ID" \
|
|
217
|
+
--resource src/example.ts --mode write --json
|
|
218
|
+
git nawabari authorize --session "$NAWABARI_SESSION_ID" \
|
|
219
|
+
--operation source-write --resource src/example.ts --json
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
A stronger ownership-sensitive operation uses `exclusive-write` and therefore
|
|
223
|
+
requires no overlapping claim:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
git nawabari session claim --session "$NAWABARI_SESSION_ID" \
|
|
227
|
+
--resource src/example.ts --mode exclusive-write --json
|
|
228
|
+
git nawabari authorize --session "$NAWABARI_SESSION_ID" \
|
|
229
|
+
--operation commit --resource src/example.ts --json
|
|
230
|
+
```
|
|
56
231
|
|
|
57
232
|
## Ownership guard
|
|
58
233
|
|
|
@@ -70,10 +245,11 @@ decision=$(git nawabari guard --session "$NAWABARI_SESSION_ID" --json) || {
|
|
|
70
245
|
|
|
71
246
|
An allowed decision has `allowed: true` and `code: "ALLOWED"`. A denied
|
|
72
247
|
decision has `allowed: false`, a stable code such as
|
|
73
|
-
`WORKTREE_OWNED_BY_OTHER_SESSION`, `PROTECTED_WORKTREE`,
|
|
74
|
-
`OWNERSHIP_MISMATCH`, and a non-zero exit status.
|
|
75
|
-
or conflicting state fails closed. The guard does
|
|
76
|
-
not prevent direct filesystem writes outside
|
|
248
|
+
`WORKTREE_OWNED_BY_OTHER_SESSION`, `PROTECTED_WORKTREE`, `DETACHED_HEAD`,
|
|
249
|
+
`WORKTREE_MISMATCH`, or `OWNERSHIP_MISMATCH`, and a non-zero exit status.
|
|
250
|
+
Detached, corrupt, missing, or conflicting state fails closed. The guard does
|
|
251
|
+
not install hooks and does not prevent direct filesystem writes outside
|
|
252
|
+
Nawabari.
|
|
77
253
|
|
|
78
254
|
## Orchestrator integration
|
|
79
255
|
|
|
@@ -95,6 +271,149 @@ The orchestrator owns scheduling, prompts, and worker lifetime; Nawabari owns
|
|
|
95
271
|
only local session identity, worktree/branch ownership, and safe cleanup. No
|
|
96
272
|
Mottainai, GitHub, `gh`, network, or agent-runtime dependency is required.
|
|
97
273
|
|
|
274
|
+
Mottainai is one optional caller of this contract, not a runtime dependency.
|
|
275
|
+
It may retain task semantics, scheduling, validation policy, Issue/PR
|
|
276
|
+
governance, and worker lifetime. It must pass concrete local declarations to
|
|
277
|
+
Nawabari and retain the returned JSON identities. Nawabari does not import or
|
|
278
|
+
execute Mottainai/GitHub workflow code, infer claims from task text, or create
|
|
279
|
+
a second registry/database.
|
|
280
|
+
|
|
281
|
+
## Claim-aware operation authorization
|
|
282
|
+
|
|
283
|
+
`authorize` is the single decision surface for a governed local operation. Its
|
|
284
|
+
versioned vocabulary and required claim access are:
|
|
285
|
+
|
|
286
|
+
| operation | required access |
|
|
287
|
+
| ----------------- | ----------------- |
|
|
288
|
+
| `source-write` | `write` |
|
|
289
|
+
| `stage` | `write` |
|
|
290
|
+
| `commit` | `exclusive-write` |
|
|
291
|
+
| `branch-mutation` | `exclusive-write` |
|
|
292
|
+
| `push` | `exclusive-write` |
|
|
293
|
+
| `cleanup` | `exclusive-write` |
|
|
294
|
+
|
|
295
|
+
The request contains a session identity, an operation, and concrete
|
|
296
|
+
repository-relative resources. Nawabari independently verifies the current
|
|
297
|
+
repository, owned worktree, branch, active session, and persisted claims;
|
|
298
|
+
caller-supplied labels do not weaken that decision. The JSON result is the
|
|
299
|
+
automation contract and reports stable allow/deny codes such as
|
|
300
|
+
`MISSING_RESOURCE_CLAIM`, `INSUFFICIENT_CLAIM_MODE`, `RESOURCE_CLAIM_CONFLICT`,
|
|
301
|
+
`INVALID_RESOURCE`, and
|
|
302
|
+
the existing ownership/physical-observation codes.
|
|
303
|
+
|
|
304
|
+
`INSUFFICIENT_CLAIM_MODE` means a matching claim exists but its granted mode
|
|
305
|
+
is weaker than the operation requires. Its bounded details identify the
|
|
306
|
+
resource, required access, and matching granted mode names;
|
|
307
|
+
`MISSING_RESOURCE_CLAIM` remains reserved for an absent matching claim.
|
|
308
|
+
|
|
309
|
+
**`authorize` returns an authorization decision only; it does NOT execute the
|
|
310
|
+
operation itself.** Governed commit and push execution use this same decision
|
|
311
|
+
path before invoking bounded Git subprocesses.
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
git nawabari authorize --session "$NAWABARI_SESSION_ID" \
|
|
315
|
+
--operation source-write --resource src/example.ts --json
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Governed commit accepts only a caller-decided final message and explicit
|
|
319
|
+
repository-relative resources. Every resource must be covered by an active
|
|
320
|
+
`exclusive-write` claim; all Git-visible changed/staged paths must be in the
|
|
321
|
+
explicit list. JSON includes the resulting `commit_sha`.
|
|
322
|
+
|
|
323
|
+
Commit evidence distinguishes three sets: the caller's **declared/authorized**
|
|
324
|
+
resources (the explicit, claim-covered list a caller passed in), the
|
|
325
|
+
**staged** set Git reports as staged immediately before the commit runs, and
|
|
326
|
+
the **actual committed** set — read back from the resulting commit itself via
|
|
327
|
+
a bounded, NUL-safe `git diff-tree` observation, not inferred from staging
|
|
328
|
+
intent. The `resources` field in a successful `commit --json` result is
|
|
329
|
+
always the actual committed set, proven equal to or a subset of the
|
|
330
|
+
authorized resources; if Git staging/index drift between staging and the
|
|
331
|
+
commit (a hook, a concurrent process) causes the actual commit to contain a
|
|
332
|
+
path outside the authorized set, the result is not reported as an ordinary
|
|
333
|
+
successful commit — it fails with `COMMIT_RESULT_DIVERGED`, which retains the
|
|
334
|
+
resulting `commitSha` (the Git commit already happened) alongside the
|
|
335
|
+
authorized, actual, and divergent path sets for recovery/reconciliation.
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
git nawabari commit --session "$NAWABARI_SESSION_ID" \
|
|
339
|
+
--message 'record the local change' --resource src/example.ts --json
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
An optional `--message-pattern <regex>` validates the final message against a
|
|
343
|
+
caller-declared rule before Git is invoked; Nawabari does not own or infer
|
|
344
|
+
commit-message conventions (such as Conventional Commits) itself, so this
|
|
345
|
+
check runs only when a caller explicitly supplies a pattern, and a mismatch
|
|
346
|
+
fails with `INVALID_COMMIT_MESSAGE` before anything is staged. The pattern is
|
|
347
|
+
bounded to 512 characters and is evaluated before the repository lock is
|
|
348
|
+
acquired, so a pathological caller-supplied pattern cannot stall other
|
|
349
|
+
sessions' governed operations. A repository's own `commit-msg` Git hook (if
|
|
350
|
+
any) still runs normally, since governed commit invokes real `git commit`.
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
git nawabari commit --session "$NAWABARI_SESSION_ID" \
|
|
354
|
+
--message 'feat: record the local change' --resource src/example.ts \
|
|
355
|
+
--message-pattern '^(feat|fix|docs|refactor|test|chore): .+$' --json
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Governed push requires explicit claim-covered resources and an explicit
|
|
359
|
+
`--remote`/`--branch` target. Existing upstream and local/remote relation are
|
|
360
|
+
inspected before mutation. A missing upstream requires `--create-upstream`;
|
|
361
|
+
behind or diverged history requires explicit `--force`. Force pushes use an
|
|
362
|
+
exact `--force-with-lease` bound to the observed remote branch SHA; non-force
|
|
363
|
+
pushes rely on `--no-force` without any lease option. Nawabari fetches only
|
|
364
|
+
the explicit remote branch into a disposable ref when local ancestry is
|
|
365
|
+
missing; it does not update tracking refs or fetch unrelated branches/tags.
|
|
366
|
+
The JSON result includes the immutable `source_sha`, explicit `target_ref`,
|
|
367
|
+
observed `observed_remote_sha`, and relation.
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
git nawabari push --session "$NAWABARI_SESSION_ID" \
|
|
371
|
+
--remote origin --branch feature/example --resource src/example.ts --json
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
`checkpoint --json` captures bounded Git-observable `changed`, `staged`,
|
|
375
|
+
`unstaged`, and `untracked` path sets, canonicalizes them through the same
|
|
376
|
+
resource model, and reports `in_claim` and `out_of_claim` paths. Checkpoint
|
|
377
|
+
evidence is limited to the state Git exposes at that instant. Direct
|
|
378
|
+
filesystem activity that is reverted, ignored, or otherwise not observable in
|
|
379
|
+
the Git checkpoint is outside Nawabari's guarantee; this feature is not an
|
|
380
|
+
OS-level filesystem monitor.
|
|
381
|
+
|
|
382
|
+
Checkpoint canonicalization fails closed: a Git-reported path that cannot be
|
|
383
|
+
represented as a canonical repository resource (traversal, symlink escape, or
|
|
384
|
+
syntax reserved for the claim/glob model) never disappears from evidence.
|
|
385
|
+
Checkpoint fails the whole observation with `GIT_STATE_AMBIGUOUS` instead of
|
|
386
|
+
silently omitting the path, so a caller can never mistake an unrepresentable
|
|
387
|
+
observation for a clean one. This mirrors the strictness governed mutation
|
|
388
|
+
already applies to the same Git-observed paths, so checkpoint evidence is
|
|
389
|
+
never weaker than mutation authorization.
|
|
390
|
+
|
|
391
|
+
## Physical execution context
|
|
392
|
+
|
|
393
|
+
Nawabari treats Git and the canonical filesystem as the authority for every
|
|
394
|
+
governed session context. It independently observes the repository common
|
|
395
|
+
directory, worktree path, current branch, and current `HEAD`, then compares
|
|
396
|
+
those observations with the session registry. Caller-supplied paths and branch
|
|
397
|
+
labels are expectations only; they are never used to replace an observation
|
|
398
|
+
Git can make.
|
|
399
|
+
|
|
400
|
+
The shared verifier fails closed with stable registry reasons for detached
|
|
401
|
+
`HEAD`, missing or prunable worktrees, repository/worktree/branch mismatches,
|
|
402
|
+
stale or conflicting registry ownership, ambiguous Git state, and unavailable
|
|
403
|
+
physical observations. Git process failures remain distinct and bounded:
|
|
404
|
+
spawn failure, timeout, output-limit, and non-zero/unexpected exit.
|
|
405
|
+
|
|
406
|
+
Provisioning canonicalizes the managed root and every existing path segment
|
|
407
|
+
before invoking Git. Traversal, symlink/intermediate-segment escapes, existing
|
|
408
|
+
worktree paths, and existing local branches are rejected deterministically;
|
|
409
|
+
the repository lock serializes Nawabari provisioning and Git's own ref checks
|
|
410
|
+
remain the final collision authority.
|
|
411
|
+
|
|
412
|
+
An explicit `--base` ref that is empty, malformed, or does not resolve to a
|
|
413
|
+
commit fails with `INVALID_BASE_REF`. The bounded JSON details retain the
|
|
414
|
+
rejected ref, identify `HEAD` as the default recovery base, and include the
|
|
415
|
+
retry hint to omit `--base`; Nawabari does not enumerate or fuzzy-search refs.
|
|
416
|
+
|
|
98
417
|
## Repository state and concurrency
|
|
99
418
|
|
|
100
419
|
The authoritative registry is stored in the repository-common Git directory at
|
|
@@ -110,6 +429,29 @@ owner is reclaimed only when the same host proves that exact process identity
|
|
|
110
429
|
is dead. Invalid, remote, or otherwise unverifiable lock metadata is never
|
|
111
430
|
stolen and fails closed so an operator can inspect or remove it deliberately.
|
|
112
431
|
|
|
432
|
+
### Conformance and extraction boundary
|
|
433
|
+
|
|
434
|
+
The packed-package suite exercises the complete standalone sequence, including
|
|
435
|
+
cross-process claim conflicts, governed commit/push, reconciliation, retryable
|
|
436
|
+
cleanup, and prunable worktree recovery. Native tests additionally cover
|
|
437
|
+
process interruption/atomic-write recovery, partial staging or commit failure,
|
|
438
|
+
stale physical state, cleanup races, bounded subprocess failures, and
|
|
439
|
+
idempotency (`src/registry/store.test.ts`, `src/git-mutation.test.ts`,
|
|
440
|
+
`src/cleanup-authority.test.ts`, `src/session-lifecycle.test.ts`, and
|
|
441
|
+
`scripts/smoke-test.mjs`).
|
|
442
|
+
|
|
443
|
+
The relevant Mottainai #28 execution cases are mapped as follows:
|
|
444
|
+
|
|
445
|
+
- repository/worktree identity, provisioning path safety, branch collision,
|
|
446
|
+
symlink escape, local staging/commit/push safety, cleanup revalidation, and
|
|
447
|
+
reconciliation are Nawabari-native authority and tests;
|
|
448
|
+
- task semantics, prompts, validation evidence policy, Conventional Commit and
|
|
449
|
+
PR/Issue governance, GitHub operations, and agent hooks remain optional
|
|
450
|
+
orchestrator-only semantics and must not move into Nawabari.
|
|
451
|
+
|
|
452
|
+
Run `pnpm run test:package` to validate the exact packed tarball and its
|
|
453
|
+
installed CLI, or `pnpm run verify` for the complete local conformance gate.
|
|
454
|
+
|
|
113
455
|
## Development
|
|
114
456
|
|
|
115
457
|
```bash
|