Test Spec: Status and Detection
What to do with this file
You are a coding agent. Your job is to execute this test spec by running commands in a shell, step by step, from Phase 0 through Phase 6. For each step:
- Run the command shown in the code block.
- Read the output.
- Check every Assert listed for that step.
- Record the result: PASS or FAIL with the actual output.
- When a step says Capture, save the value into the named variable and use it in subsequent steps.
At the end, produce a summary table showing which phases passed and which failed, with the actual vs. expected values for any failures.
If a prerequisite is not met (binary not found, fixture script missing), stop and report that instead of continuing.
What this test is checking
slice status is the canonical inspection command, but it also serves as the
detection mechanism for scripts and agents: "am I in a thinslice workspace,
and if so, where exactly?" That makes its failure modes — not in a git repo
at all, in a git repo that hasn't been slice setup-ed — as important as its
happy path.
This test verifies all six location states a caller can find itself in, both
through the human-readable output and through the --json shape that scripts
consume. Exit codes are tested separately from output because shell callers
branch on them without parsing prose.
The six location states are:
| State | Exit | Notes |
|---|---|---|
| Not in a git repository | 2 | No git ancestor at all |
Git repo, but no +clone+ ancestor | 1 | Slice setup hasn't run |
| Slice workspace root | 0 | At the workspace root (sibling of +clone+/) |
| Slice worktree, unbound | 0 | In a worktree with no state binding |
| Slice worktree, bound, stopped | 0 | Bound but processes not running |
| Slice worktree, bound, running | 0 | Bound and processes up |
Prerequisites
The slice binary and the slice-test-fixture helper must be on $PATH.
Python 3 must be available (for the bound+running test). No external
infrastructure is required.
As a quick smoke test, run:
$ slice --version
If this succeeds, proceed. If it fails, stop and report the error.
Fixture
This test uses two helpers from slice-test-fixture:
init-repo— creates a vanilla git repo (noslice setuprun). Used for the "git-repo-but-not-slice" failure case.workspace— creates a fully-initialized slice workspace. Used for all the happy-path location states.
Both helpers print the absolute path on stdout. destroy <path> cleans up.
Notation
$WS— absolute path to the slice workspace$REPO— absolute path to the vanilla (non-slice) git repo- Lines starting with
$inside code blocks are commands to run
Phase 0: Set up fixtures
We need two starting points: a vanilla git repo (for the "git but not slice" failure case) and a fully-set-up slice workspace (for all happy paths).
0.1 Vanilla git repo
$ slice-test-fixture init-repo
Capture the output as $REPO.
$ git -C $REPO rev-parse --is-inside-work-tree
Assert: Output is true — a real git repo exists.
$ test -d $REPO/+clone+ && echo "found" || echo "missing"
Assert: Output is missing — slice setup has not been run.
0.2 Slice workspace
$ slice-test-fixture workspace
Capture the output as $WS.
$ test -d $WS/+clone+ && echo "found" || echo "missing"
Assert: Output is found — workspace is set up.
Phase 1: Failure mode — not in a git repository
Run from a directory with no git ancestor. The command should report a clear
reason, exit with code 2, and produce valid JSON in --json mode.
1.1 Human output
$ cd / && slice status; echo "exit=$?"
Assert:
- Output is
slice: not in a git repository - Exit code is
2
1.2 JSON output
$ cd / && slice status --json
Assert: Output is valid JSON with:
thinslice_managed: falsereason: "not in a git repository"cwd: "/"- No
git_common_dirfield
$ cd / && slice status --json; echo "exit=$?"
Assert: Exit code is 2 — same as human mode.
Phase 2: Failure mode — git repo, but not slice-managed
Run from $REPO, which is a git repo but has no +clone+ ancestor. The
command should distinguish this from "not a git repo" with a different
reason and a different exit code.
2.1 Human output
$ cd $REPO && slice status; echo "exit=$?"
Assert:
- Output is
slice: git repository found, but no +clone+ directory — runslice setupto convert it - Exit code is
1
2.2 JSON output
$ cd $REPO && slice status --json
Assert: Output is valid JSON with:
thinslice_managed: falsereasonmatches the human message exactlycwdequals$REPOgit_common_diris present and points to$REPO/.git
2.3 Same behavior in a subdirectory
$ mkdir -p $REPO/subdir && cd $REPO/subdir && slice status; echo "exit=$?"
Assert:
- Same reason and exit code as Phase 2.1 — the detection walks up to find the git common dir, so depth inside the repo doesn't matter.
Phase 3: Happy path — workspace root
Run from $WS itself (the workspace root, sibling of +clone+/). The
command should report location: workspace root and list all worktrees.
3.1 Human output
$ cd $WS && slice status; echo "exit=$?"
Assert:
- First line:
location: workspace root ($WS) - Blank line follows
- Each worktree listed with leading two-character marker (
for not-current) mainworktree is listed and showsunboundand—- No worktree is marked with
*(no current worktree at root) - Exit code is
0
3.2 JSON output
$ cd $WS && slice status --json
Assert: Output is valid JSON with:
thinslice_managed: trueworkspace.rootequals$WSworkspace.cloneequals$WS/+clone+workspace.stateequals$WS/+state+current.locationequals"root"current.pathisnullcurrent.relisnullcurrent.namespaceisnullcurrent.bindingisnullworktreesis a list containing at least one entry formain- Every entry has
current: false
Phase 4: Happy path — worktree, unbound
Run from $WS/main. The worktree exists but isn't bound to any state.
4.1 Human output
$ cd $WS/main && slice status; echo "exit=$?"
Assert:
- First line:
location: worktree main - The
mainentry is marked with*(current worktree) - State shown as
unbound, status shown as— - Exit code is
0
4.2 JSON output
$ cd $WS/main && slice status --json
Assert:
current.locationequals"worktree"current.pathequals$WS/maincurrent.relequals"main"current.namespaceequals"main"(the first path segment;mainis its own segment since the worktree path is flat, notlocal/...ortmp/...)current.binding.boundisfalsecurrent.binding.stateisnullcurrent.binding.processesisnull- In
worktrees, the entry formainhascurrent: true
Phase 5: Happy path — worktree, bound and running
Bind a worktree to a state and start processes. slice status should report
the binding, the state name, the running status, and port allocations.
5.1 Set up the binding
$ cd $WS/main && slice state new dev-alpha --from template-clean
$ cd $WS && slice local feature-status
$ cd $WS/local/feature-status && slice use dev-alpha
$ cd $WS/local/feature-status && slice up
Expect: Each step succeeds. Processes start.
5.2 Human output, bound + running
$ cd $WS/local/feature-status && slice status; echo "exit=$?"
Assert:
- First line:
location: worktree local/feature-status - The
local/feature-statusentry is marked with* - State shown as
dev-alpha, status shown asrunning - A port list appears in brackets, e.g.
[httpd:NNNN] - The
mainentry still appears, unmarked, withunboundand— - Exit code is
0
5.3 JSON output, bound + running
$ cd $WS/local/feature-status && slice status --json
Capture the port value shown for httpd as $HTTPD_PORT.
Assert:
current.locationequals"worktree"current.relequals"local/feature-status"current.namespaceequals"local"current.binding.boundistruecurrent.binding.stateequals"dev-alpha"current.binding.processesequals"running"- The
local/feature-statusentry inworktreeshascurrent: true,state: "dev-alpha",status: "running", and a non-nullportsstring
5.4 Stop, then check status again
$ cd $WS/local/feature-status && slice down
$ cd $WS/local/feature-status && slice status; echo "exit=$?"
Assert:
- State still shown as
dev-alpha(binding preserved) - Status now shown as
stopped - Exit code is
0
5.5 JSON output, bound + stopped
$ cd $WS/local/feature-status && slice status --json
Assert:
current.binding.boundistruecurrent.binding.stateequals"dev-alpha"current.binding.processesequals"stopped"
Phase 6: Teardown
$ cd $WS/local/feature-status && slice detach
$ cd $WS && slice rm local/feature-status
$ cd $WS/main && slice state rm dev-alpha
$ slice-test-fixture destroy $WS
$ slice-test-fixture destroy $REPO
Assert:
- Each step succeeds.
$WSand$REPOdirectories no longer exist.
Summary of Key Assertions
| Phase | What is tested | Key assertion |
|---|---|---|
| 0 | Fixtures | Vanilla git repo and slice workspace both available |
| 1 | Not a git repo | Exit 2, reason not in a git repository, JSON shape |
| 2 | Git repo, not slice | Exit 1, reason mentions +clone+, JSON includes git_common_dir |
| 3 | Workspace root | Exit 0, location: workspace root, no current marker |
| 4 | Worktree, unbound | Exit 0, * marks current, binding.bound: false |
| 5 | Worktree, bound + running | Exit 0, port list shown, binding.processes: "running" |
| 6 | Teardown | All fixtures cleaned up |

