cinna-cli 0.2.3__tar.gz → 0.2.4__tar.gz

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 (86) hide show
  1. cinna_cli-0.2.4/.claude/commands/cinna-cli.feature.doc.md +174 -0
  2. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/PKG-INFO +13 -4
  3. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/README.md +12 -3
  4. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/docs/README.md +164 -6
  5. cinna_cli-0.2.4/docs/features/account_workspace/account_workspace.md +207 -0
  6. cinna_cli-0.2.4/docs/features/account_workspace/account_workspace_acceptance.md +287 -0
  7. cinna_cli-0.2.4/docs/features/account_workspace/account_workspace_tech.md +255 -0
  8. cinna_cli-0.2.4/docs/features/agent_api/agent_api.md +185 -0
  9. cinna_cli-0.2.4/docs/features/agent_api/agent_api_acceptance.md +224 -0
  10. cinna_cli-0.2.4/docs/features/agent_api/agent_api_tech.md +162 -0
  11. cinna_cli-0.2.4/docs/features/agent_management/agent_management.md +149 -0
  12. cinna_cli-0.2.4/docs/features/agent_management/agent_management_acceptance.md +232 -0
  13. cinna_cli-0.2.4/docs/features/agent_management/agent_management_tech.md +160 -0
  14. cinna_cli-0.2.4/docs/features/agent_schedules/agent_schedules.md +155 -0
  15. cinna_cli-0.2.4/docs/features/agent_schedules/agent_schedules_acceptance.md +218 -0
  16. cinna_cli-0.2.4/docs/features/agent_schedules/agent_schedules_tech.md +136 -0
  17. cinna_cli-0.2.4/docs/features/bootstrap_onboarding/bootstrap_onboarding.md +192 -0
  18. cinna_cli-0.2.4/docs/features/bootstrap_onboarding/bootstrap_onboarding_acceptance.md +239 -0
  19. cinna_cli-0.2.4/docs/features/bootstrap_onboarding/bootstrap_onboarding_tech.md +188 -0
  20. cinna_cli-0.2.4/docs/features/doctor/doctor.md +162 -0
  21. cinna_cli-0.2.4/docs/features/doctor/doctor_acceptance.md +263 -0
  22. cinna_cli-0.2.4/docs/features/doctor/doctor_tech.md +154 -0
  23. cinna_cli-0.2.4/docs/features/git_versioning/git_versioning.md +170 -0
  24. cinna_cli-0.2.4/docs/features/git_versioning/git_versioning_acceptance.md +264 -0
  25. cinna_cli-0.2.4/docs/features/git_versioning/git_versioning_tech.md +137 -0
  26. cinna_cli-0.2.4/docs/features/live_sync/live_sync.md +153 -0
  27. cinna_cli-0.2.4/docs/features/live_sync/live_sync_acceptance.md +234 -0
  28. cinna_cli-0.2.4/docs/features/live_sync/live_sync_tech.md +199 -0
  29. cinna_cli-0.2.4/docs/features/mcp_integration/mcp_integration.md +166 -0
  30. cinna_cli-0.2.4/docs/features/mcp_integration/mcp_integration_acceptance.md +192 -0
  31. cinna_cli-0.2.4/docs/features/mcp_integration/mcp_integration_tech.md +145 -0
  32. cinna_cli-0.2.4/docs/features/remote_chat/remote_chat.md +152 -0
  33. cinna_cli-0.2.4/docs/features/remote_chat/remote_chat_acceptance.md +221 -0
  34. cinna_cli-0.2.4/docs/features/remote_chat/remote_chat_tech.md +159 -0
  35. cinna_cli-0.2.4/docs/features/remote_exec/remote_exec.md +124 -0
  36. cinna_cli-0.2.4/docs/features/remote_exec/remote_exec_acceptance.md +183 -0
  37. cinna_cli-0.2.4/docs/features/remote_exec/remote_exec_tech.md +106 -0
  38. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/pyproject.toml +1 -1
  39. cinna_cli-0.2.4/scripts/check_docs_references.py +242 -0
  40. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/account.py +141 -23
  41. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/bootstrap.py +160 -17
  42. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/client.py +21 -0
  43. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/config.py +122 -2
  44. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/context.py +40 -0
  45. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/doctor.py +195 -23
  46. cinna_cli-0.2.4/src/cinna/git_versioning.py +584 -0
  47. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/main.py +285 -11
  48. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/templates/CLAUDE.md.template +2 -0
  49. cinna_cli-0.2.4/src/cinna/templates/GIT_VERSIONING.md +110 -0
  50. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_account.py +46 -6
  51. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_config.py +21 -0
  52. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_context.py +44 -0
  53. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_doctor.py +143 -8
  54. cinna_cli-0.2.4/tests/test_git_versioning.py +539 -0
  55. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_main.py +33 -0
  56. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/uv.lock +1 -1
  57. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/.github/workflows/publish.yml +0 -0
  58. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/.gitignore +0 -0
  59. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/LICENSE.md +0 -0
  60. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/docs/interface.md +0 -0
  61. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/docs/mutagen_capabilities.md +0 -0
  62. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/__init__.py +0 -0
  63. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/auth.py +0 -0
  64. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/chat.py +0 -0
  65. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/console.py +0 -0
  66. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/errors.py +0 -0
  67. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/logging.py +0 -0
  68. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/mcp_proxy.py +0 -0
  69. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/mutagen_runtime.py +0 -0
  70. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/sync.py +0 -0
  71. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/sync_session.py +0 -0
  72. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/sync_ssh_shim.py +0 -0
  73. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/sync_tui.py +0 -0
  74. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/templates/ACCOUNT_CLAUDE.md.template +0 -0
  75. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/templates/CHAT_TESTING.md +0 -0
  76. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/src/cinna/templates/__init__.py +0 -0
  77. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/__init__.py +0 -0
  78. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/conftest.py +0 -0
  79. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_auth.py +0 -0
  80. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_bootstrap.py +0 -0
  81. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_chat.py +0 -0
  82. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_client.py +0 -0
  83. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_mutagen_runtime.py +0 -0
  84. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_sync.py +0 -0
  85. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_sync_session.py +0 -0
  86. {cinna_cli-0.2.3 → cinna_cli-0.2.4}/tests/test_sync_ssh_shim.py +0 -0
@@ -0,0 +1,174 @@
1
+ ---
2
+ description: Create or update cinna-cli feature documentation (business / tech / acceptance).
3
+ ---
4
+
5
+ ## User Input
6
+
7
+ ```text
8
+ $ARGUMENTS
9
+ ```
10
+
11
+ Feature name, description, or existing doc path to create/refactor.
12
+
13
+ ## Task
14
+
15
+ Create or refactor feature documentation under `docs/features/` following the
16
+ layered structure below. cinna-cli is a **Python CLI** (source in `src/cinna/`,
17
+ tests in `tests/`) that drives local agent development against a remote platform
18
+ API — there is no frontend/backend split to document. Keep that in mind: file
19
+ references point into `src/cinna/…` and `tests/…`, not `backend/`/`frontend/`.
20
+
21
+ **If given an existing doc path** — refactor it into the correct structure (split
22
+ into business / tech / acceptance files as needed, move under
23
+ `docs/features/{feature}/`).
24
+ **If given a feature name** — create new documentation by exploring the codebase
25
+ first (`src/cinna/`, the `cinna <group>` command surface in `src/cinna/main.py`,
26
+ relevant tests).
27
+
28
+ ## Documentation Architecture
29
+
30
+ ### Layer 1 — Project index (`docs/README.md`)
31
+
32
+ The single concise entry point: project purpose, glossary, architecture, command
33
+ surface, and a **Feature Registry** linking each documented feature to its folder.
34
+ When you create/update a feature doc, add/update its row in the registry.
35
+
36
+ ### Layer 2 — Feature folders (`docs/features/{feature}/`)
37
+
38
+ ```
39
+ docs/
40
+ ├── README.md # Layer 1 — project index + feature registry
41
+ └── features/
42
+ └── {feature}/ # one folder per feature (snake_case)
43
+ ├── {feature}.md # Layer 3a — business logic / reasoning (required)
44
+ ├── {feature}_tech.md # Layer 3b — implementation, file refs (optional)
45
+ └── {feature}_acceptance.md # Layer 3c — real-usage e2e scenarios (optional)
46
+ ```
47
+
48
+ Feature-folder naming: snake_case, descriptive (`git_versioning`, `live_sync`,
49
+ `remote_exec`, `account_workspace`, `remote_chat`).
50
+
51
+ ### Layer 3 — Feature documentation files
52
+
53
+ #### 3a. Business logic: `{feature}.md`
54
+
55
+ Explains **WHAT** the feature does and **WHY**, from a product/user perspective.
56
+ A reader should understand purpose, flows, and rules without reading code.
57
+
58
+ Required sections:
59
+ 1. **Purpose** — 1–2 sentences: what it does for the user.
60
+ 2. **Mental model / core concepts** — key terms and the model the user must hold
61
+ (for cinna-cli, almost always: how local files, the remote container, and any
62
+ external system relate; what is local vs remote vs on-demand).
63
+ 3. **User flows** — numbered steps for the main ways users interact (commands run,
64
+ what happens, what they see).
65
+ 4. **Business rules** — constraints, state/lifecycle rules, guardrails, failure
66
+ semantics (what is *fail-loud*, what is auto vs manual, direction guards…).
67
+ 5. **Architecture overview** — a simple text diagram of the component flow, e.g.
68
+ `cinna git <verb> → git_versioning.py → real git → remote`.
69
+ 6. **Integration points** — how it connects to other features (link their docs).
70
+
71
+ Style: concise bullets, no code blocks, focus on behavior and reasoning.
72
+
73
+ #### 3b. Technical details: `{feature}_tech.md`
74
+
75
+ Deep-dive for developers: **HOW** it's implemented, with file references.
76
+
77
+ Required sections:
78
+ 1. **File locations** — every `src/cinna/…` module + the tests that cover it.
79
+ 2. **Command surface** — `cinna <group> <verb>` → the function in
80
+ `src/cinna/main.py` that implements it, one line each.
81
+ 3. **Key functions & flow** — module path + function names with a brief purpose
82
+ (e.g. `src/cinna/git_versioning.py:link()` — the link sequence).
83
+ 4. **Config & registry** — fields written to `.cinna/config.json` and
84
+ `~/.cinna/agents.json` (the latter referenced as a path, it's runtime state).
85
+ 5. **External contracts** — platform API endpoints consumed, and any external
86
+ tool invoked (git, mutagen) with the exact invariants relied on.
87
+ 6. **Edge cases & guardrails** — the non-obvious behaviors a maintainer must
88
+ preserve, each tied to the code that enforces it.
89
+
90
+ Style: heavy use of `src/cinna/file.py:function()` references. <!-- nocheck --> **No
91
+ code blocks** — only file/function references.
92
+
93
+ #### 3c. Acceptance scenarios: `{feature}_acceptance.md` — **the e2e test catalog**
94
+
95
+ The catalog of **real-usage scenarios** a testing agent executes against a *live*
96
+ environment (a real backend + real container + real external systems) — **not**
97
+ unit tests. This is what catches the bugs unit tests miss: conflicting pushes,
98
+ multi-agent layout collisions, registry drift across commands, tarball/commit
99
+ divergence, stale state across command sequences.
100
+
101
+ Write it so an autonomous agent can pick it up and run each scenario end-to-end.
102
+
103
+ Required sections:
104
+ 1. **Preconditions** — what the agent needs: a live platform URL, an account
105
+ workspace or setup token, at least one (ideally two) agents configured for the
106
+ feature, any external accounts/credentials, and the editable install
107
+ (`which cinna` → repo `src/cinna`).
108
+ 2. **Scenario catalog** — a numbered list. Each scenario has:
109
+ - **Goal** — the real user intent being exercised.
110
+ - **Setup** — starting state.
111
+ - **Steps** — the exact `cinna …` (and supporting `git`/`cinna exec`) commands.
112
+ - **Expected** — observable outcome (output text, file/remote/registry/env
113
+ state). Be specific enough to assert.
114
+ - **Watch for** — the failure modes / regressions this scenario is designed to
115
+ surface (the "why this scenario exists").
116
+ 3. **Cross-cutting invariants** — properties that must hold across *all* scenarios
117
+ (e.g. credentials never committed; a command that re-writes the registry must
118
+ not drop another command's state; fail-loud, never silent-clobber).
119
+ 4. **Cleanup** — how to leave the live environment tidy afterward.
120
+
121
+ Style: imperative, runnable. Real commands in fenced blocks are encouraged here
122
+ (unlike the other layers). Prefer scenarios grounded in actual runs — when a real
123
+ test discovers a defect, **add the scenario that reproduces it** so it becomes a
124
+ permanent regression check.
125
+
126
+ ### Minimal documentation
127
+
128
+ Not every feature needs all three files. Start with `{feature}.md`. Add `_tech.md`
129
+ when implementation detail would clutter the business doc or spans many modules.
130
+ Add `_acceptance.md` when the feature has **real-environment behavior worth
131
+ exercising e2e** (anything touching sync, git, the container, schedules, or
132
+ multi-agent/multi-command state — i.e. most non-trivial cinna-cli features).
133
+
134
+ ## Style rules
135
+
136
+ **DO**
137
+ - Use file refs: `src/cinna/git_versioning.py:link()`, `tests/test_git_versioning.py`
138
+ - Use command refs: `cinna git push` — push the agent branch (ff-only)
139
+ - Use endpoint refs: `GET /api/v1/cli/git-coordinates`
140
+ - Link related docs: `See [Live Sync](../live_sync/live_sync.md)` <!-- nocheck -->
141
+ - Concise bullets; simple text architecture diagrams
142
+ - In `_acceptance.md`, write real runnable commands
143
+
144
+ **DON'T**
145
+ - Put code snippets in `{feature}.md` / `{feature}_tech.md`
146
+ - Duplicate content between the business and tech files
147
+ - Reference container/home paths (`/app/workspace/…`, `~/.cinna/…`) as if repo
148
+ files — they are illustrative; the checker skips them, but be intentional
149
+
150
+ ## Process
151
+
152
+ 1. **Scope** — new feature doc or refactor of an existing one?
153
+ 2. **Folder** — map to `docs/features/{feature}/`.
154
+ 3. **Explore** — read the relevant `src/cinna/` modules, the `cinna` command
155
+ surface, and the covering tests.
156
+ 4. **Write** — always `{feature}.md`; add `_tech.md` / `_acceptance.md` per the
157
+ rules above.
158
+ 5. **Update `docs/README.md`** — add/refresh the Feature Registry entry.
159
+ 6. **Validate references** — run the checker on the files you touched:
160
+ ```
161
+ python3 scripts/check_docs_references.py --files docs/features/{feature}/{feature}.md docs/features/{feature}/{feature}_tech.md docs/features/{feature}/{feature}_acceptance.md
162
+ ```
163
+ Fix every broken reference before finishing. For *illustrative* paths that are
164
+ not real repo files (container/home/convention paths), append `<!-- nocheck -->`
165
+ to that line.
166
+ 7. **Run the test suite** — `pytest -q` must stay green (the docs describe shipped
167
+ behavior; if a doc claims behavior the tests don't cover, add or point to the
168
+ test).
169
+
170
+ ## Output
171
+
172
+ Write to `docs/features/{feature}/`. Report what was created/updated, any old
173
+ files replaced (don't delete automatically — report them), the reference-check
174
+ result, and the test-suite status.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cinna-cli
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Local development CLI for Cinna Core agents
5
5
  Project-URL: Homepage, https://github.com/opencinna/cinna-cli
6
6
  Project-URL: Repository, https://github.com/opencinna/cinna-cli
@@ -344,16 +344,25 @@ It detects and fixes:
344
344
  - **Halted sessions** — sessions stopped on `halted-on-root-deletion` (the local `workspace/` root was deleted) while the agent dir is otherwise intact. Terminated; `cinna dev` recreates a clean one.
345
345
  - **Dead-remote sessions** — sessions stuck retrying a remote env that no longer exists (`connecting-beta` / beta polling error). Mutagen has **no** "give up after N failures" option — a session retries forever until paused or terminated — so `doctor` is the cleanup path for these. Terminated.
346
346
  - **Orphaned sessions** — `cinna-*` sessions with no registry entry at all. Terminated.
347
+ - **Active sessions** — the healthy, still-watching sessions left over from past `cinna dev` runs. They are not broken, but they keep the shared Mutagen daemon busy and are recreated on demand, so doctor offers to clear them as a separate step.
347
348
  - **Expired tokens** — for **account-managed** workspaces (those under an account root), the CLI token is re-minted automatically through the parent account token, no pasting required. **Standalone** workspaces (set up via `cinna setup`) can only be refreshed with a pasted setup token, so they are reported with a `cinna set-token` hint rather than changed.
348
349
  - **Expired account token** — a sub-agent token can only be re-minted while the **account** token that mints it is still valid. When the account token has itself expired, doctor probes it once and surfaces a single _"renew the account token — run `cinna login`"_ finding (listing the blocked sub-agents) instead of a pile of re-mints that would all fail with 401. Run `cinna login`, then re-run `cinna doctor` to re-mint the dependents.
349
350
 
350
351
  ```bash
351
- cinna doctor # diagnose, then apply all fixes behind one confirmation
352
+ cinna doctor # diagnose, then walk the repair steps (each defaults to Yes)
352
353
  cinna doctor --dry-run # report problems only; change nothing
353
- cinna doctor --yes # apply every fix non-interactively
354
+ cinna doctor --yes # accept every step non-interactively
354
355
  ```
355
356
 
356
- The diagnosis is split into two tables: **Will fix** (everything doctor can repair — deleted-workspace cleanup, halted/dead/orphaned session termination, account token re-mints) and **No automatic fix — manual action needed** (standalone expired tokens, which need a pasted setup token and are never touched). Everything actionable is applied together behind a single `Apply N fix(es)?` confirmation, so the count always matches the "Will fix" table.
357
+ `doctor` first prints the live `cinna-*` session inventory — each session tagged with the **agent** and **folder** it serves — so you can see what's running before deciding anything. Findings it can't fix itself (standalone expired tokens) are listed under **No automatic fix — manual action needed** and never touched.
358
+
359
+ The repair then runs as three ordered, independently-confirmed steps, each defaulting to **Yes**:
360
+
361
+ 1. **Delete stalled sessions** — deleted-workspace cleanup plus halted / dead / orphaned session termination.
362
+ 2. **Terminate active sessions** — clear the healthy leftovers from the inventory above (recreated on the next `cinna dev`).
363
+ 3. **Refresh tokens** — re-mint expired account-managed tokens.
364
+
365
+ `--yes` accepts all three; `--dry-run` shows the tables and changes nothing.
357
366
 
358
367
  ### `cinna disconnect`
359
368
 
@@ -307,16 +307,25 @@ It detects and fixes:
307
307
  - **Halted sessions** — sessions stopped on `halted-on-root-deletion` (the local `workspace/` root was deleted) while the agent dir is otherwise intact. Terminated; `cinna dev` recreates a clean one.
308
308
  - **Dead-remote sessions** — sessions stuck retrying a remote env that no longer exists (`connecting-beta` / beta polling error). Mutagen has **no** "give up after N failures" option — a session retries forever until paused or terminated — so `doctor` is the cleanup path for these. Terminated.
309
309
  - **Orphaned sessions** — `cinna-*` sessions with no registry entry at all. Terminated.
310
+ - **Active sessions** — the healthy, still-watching sessions left over from past `cinna dev` runs. They are not broken, but they keep the shared Mutagen daemon busy and are recreated on demand, so doctor offers to clear them as a separate step.
310
311
  - **Expired tokens** — for **account-managed** workspaces (those under an account root), the CLI token is re-minted automatically through the parent account token, no pasting required. **Standalone** workspaces (set up via `cinna setup`) can only be refreshed with a pasted setup token, so they are reported with a `cinna set-token` hint rather than changed.
311
312
  - **Expired account token** — a sub-agent token can only be re-minted while the **account** token that mints it is still valid. When the account token has itself expired, doctor probes it once and surfaces a single _"renew the account token — run `cinna login`"_ finding (listing the blocked sub-agents) instead of a pile of re-mints that would all fail with 401. Run `cinna login`, then re-run `cinna doctor` to re-mint the dependents.
312
313
 
313
314
  ```bash
314
- cinna doctor # diagnose, then apply all fixes behind one confirmation
315
+ cinna doctor # diagnose, then walk the repair steps (each defaults to Yes)
315
316
  cinna doctor --dry-run # report problems only; change nothing
316
- cinna doctor --yes # apply every fix non-interactively
317
+ cinna doctor --yes # accept every step non-interactively
317
318
  ```
318
319
 
319
- The diagnosis is split into two tables: **Will fix** (everything doctor can repair — deleted-workspace cleanup, halted/dead/orphaned session termination, account token re-mints) and **No automatic fix — manual action needed** (standalone expired tokens, which need a pasted setup token and are never touched). Everything actionable is applied together behind a single `Apply N fix(es)?` confirmation, so the count always matches the "Will fix" table.
320
+ `doctor` first prints the live `cinna-*` session inventory — each session tagged with the **agent** and **folder** it serves — so you can see what's running before deciding anything. Findings it can't fix itself (standalone expired tokens) are listed under **No automatic fix — manual action needed** and never touched.
321
+
322
+ The repair then runs as three ordered, independently-confirmed steps, each defaulting to **Yes**:
323
+
324
+ 1. **Delete stalled sessions** — deleted-workspace cleanup plus halted / dead / orphaned session termination.
325
+ 2. **Terminate active sessions** — clear the healthy leftovers from the inventory above (recreated on the next `cinna dev`).
326
+ 3. **Refresh tokens** — re-mint expired account-managed tokens.
327
+
328
+ `--yes` accepts all three; `--dry-run` shows the tables and changes nothing.
320
329
 
321
330
  ### `cinna disconnect`
322
331
 
@@ -198,7 +198,7 @@ main.py (CLI commands — Click)
198
198
  │
199
199
  ├── bootstrap.py — setup orchestration
200
200
  ├── account.py — account workspace; `cinna login` (device auth), `cinna account`, `cinna agent`
201
- ├── doctor.py — `cinna doctor`: reconcile registry ↔ Mutagen, repair stale state, refresh tokens
201
+ ├── doctor.py — `cinna doctor`: reconcile registry ↔ Mutagen, delete stalled / terminate active sessions, refresh tokens
202
202
  ├── chat.py — `cinna chat`: session-backed conversation testing (poll + NDJSON) over the api-proxy
203
203
  ├── config.py — .cinna/config.json: load/save/find
204
204
  ├── auth.py — JWT storage, Authorization headers
@@ -217,12 +217,21 @@ main.py (CLI commands — Click)
217
217
 
218
218
  ### Local Directory Layout
219
219
 
220
- After `cinna setup` (agent name normalized, e.g. "HR Manager Agent" → `hr-manager-agent/`):
220
+ After `cinna setup` (agent name normalized, e.g. "HR Manager Agent" → `hr-manager-agent`),
221
+ every new checkout uses the **Model-A nested layout** (`config.compute_agent_layout`):
222
+ a clone-root dir holds the agent at `<subdir>/`, so the folder is already shaped like
223
+ the agent's git repo whether or not Git Versioning is enabled (see "Git Versioning"
224
+ below). `<subdir>` defaults to the agent slug. If the clone-root dir `<slug>/` is
225
+ already taken by a **different** agent (two names normalizing to the same slug), the
226
+ clone root falls back to `<slug>-<shorthash>/` (the agent id's short hash) so the two
227
+ don't collide; re-running setup for the *same* agent still reports "already set up".
221
228
 
222
229
  ```
223
- hr-manager-agent/ (workspace root)
230
+ hr-manager-agent/ (clone root — becomes the git working tree once linked)
231
+ └── hr-manager-agent/ (workspace root == the repo's <subdir>/ node)
224
232
  .cinna/
225
- config.json (agent config, CLI token, mutagen_version pin)
233
+ config.json (agent config, CLI token, mutagen_version pin, git{} layout)
234
+ cinna.agent.json (backend-owned manifest; present once git-versioned)
226
235
  workspace/ (continuously synced with remote /app/workspace)
227
236
  scripts/ (bundle-owned — shipped in published revisions)
228
237
  docs/ (bundle-owned)
@@ -250,13 +259,146 @@ Per-user global state (one copy, shared across every agent workspace):
250
259
 
251
260
  ```
252
261
  ~/.cinna/
253
- agents.json (agent_id → {platform_url, cli_token, workspace_path}; 0600)
262
+ agents.json (agent_id → {platform_url, cli_token, workspace_path,
263
+ git?:{clone_path, subdir, repo_url, ref, …}}; 0600)
254
264
  mutagen-ssh/
255
265
  ssh (bash wrapper — execs cinna-sync-ssh; 0755)
256
266
  ```
257
267
 
258
268
  ---
259
269
 
270
+ ## Feature Registry
271
+
272
+ Each feature is documented under `docs/features/{feature}/` as a layered set:
273
+ `{feature}.md` (business logic / reasoning), `{feature}_tech.md` (implementation +
274
+ file refs), and `{feature}_acceptance.md` (live e2e scenarios). See
275
+ [cinna-cli.feature.doc](../.claude/commands/cinna-cli.feature.doc.md) for the
276
+ authoring convention.
277
+
278
+ | Feature | Command surface | Docs |
279
+ |---|---|---|
280
+ | **Bootstrap & onboarding** | `cinna setup` / `set-token` / `login` / `list` / `status` / `disconnect[-all]` / `completion` / `dev` / `redev` | [business](features/bootstrap_onboarding/bootstrap_onboarding.md) · [tech](features/bootstrap_onboarding/bootstrap_onboarding_tech.md) · [acceptance](features/bootstrap_onboarding/bootstrap_onboarding_acceptance.md) |
281
+ | **Account workspace** | `cinna account` (setup, agents, status, refresh-context, user-workspace, credentials) | [business](features/account_workspace/account_workspace.md) · [tech](features/account_workspace/account_workspace_tech.md) · [acceptance](features/account_workspace/account_workspace_acceptance.md) |
282
+ | **Agent management** | `cinna agent` (sync, unsync, create, restart-env, show, status) | [business](features/agent_management/agent_management.md) · [tech](features/agent_management/agent_management_tech.md) · [acceptance](features/agent_management/agent_management_acceptance.md) |
283
+ | **Agent schedules** | `cinna agent schedule` (list, generate, create, update, run, logs, delete) | [business](features/agent_schedules/agent_schedules.md) · [tech](features/agent_schedules/agent_schedules_tech.md) · [acceptance](features/agent_schedules/agent_schedules_acceptance.md) |
284
+ | **Live sync** | `cinna sync` (status, conflicts, push, pull, resolve) + Mutagen transport | [business](features/live_sync/live_sync.md) · [tech](features/live_sync/live_sync_tech.md) · [acceptance](features/live_sync/live_sync_acceptance.md) |
285
+ | **Remote exec** | `cinna exec` | [business](features/remote_exec/remote_exec.md) · [tech](features/remote_exec/remote_exec_tech.md) · [acceptance](features/remote_exec/remote_exec_acceptance.md) |
286
+ | **Remote chat** | `cinna chat` | [business](features/remote_chat/remote_chat.md) · [tech](features/remote_chat/remote_chat_tech.md) · [acceptance](features/remote_chat/remote_chat_acceptance.md) |
287
+ | **Agent API** | `cinna agent-api` (enable, refresh, spec, call) · `cinna api` · `cinna connect agent-api` | [business](features/agent_api/agent_api.md) · [tech](features/agent_api/agent_api_tech.md) · [acceptance](features/agent_api/agent_api_acceptance.md) |
288
+ | **MCP integration** | `cinna connect mcp` · `cinna mcp-proxy` (knowledge stdio server) | [business](features/mcp_integration/mcp_integration.md) · [tech](features/mcp_integration/mcp_integration_tech.md) · [acceptance](features/mcp_integration/mcp_integration_acceptance.md) |
289
+ | **Git versioning** | `cinna git` (link, status, commit, push, pull, log, checkout, unlink) | [business](features/git_versioning/git_versioning.md) · [tech](features/git_versioning/git_versioning_tech.md) · [acceptance](features/git_versioning/git_versioning_acceptance.md) |
290
+
291
+ The sections below (Git Versioning, Sync Transport, Remote Exec, Remote Chat,
292
+ Bootstrap Flow) remain as in-README quick references and backend contracts; the
293
+ feature folders above are the authoritative deep dives.
294
+
295
+ ---
296
+
297
+ ## Git Versioning
298
+
299
+ > Full feature docs: [git_versioning](features/git_versioning/git_versioning.md)
300
+ > (business logic), [_tech](features/git_versioning/git_versioning_tech.md)
301
+ > (implementation), [_acceptance](features/git_versioning/git_versioning_acceptance.md)
302
+ > (live e2e scenarios). This section is the quick reference + backend contract.
303
+
304
+ A git-versioned agent has **two independent sync layers** on the same folder:
305
+ **Mutagen** keeps `workspace/` mirrored to the running container in near-real-time
306
+ (it ignores `.git`), and **git** durably versions the same files against the agent's
307
+ external remote. They meet only at the remote. All git ops are local and run with the
308
+ developer's **own** git/SSH credentials — the platform's deploy key never reaches the
309
+ CLI. (The agent-facing version of this guidance is shipped into each checkout as the
310
+ on-demand `GIT_VERSIONING.md`, referenced conditionally from `CLAUDE.md`.)
311
+
312
+ Because new checkouts already use the Model-A nested layout, enabling Git Versioning
313
+ later needs no re-download or file move — just a link:
314
+
315
+ ```
316
+ cinna git status # is this agent git-versioned? linked? working-tree status
317
+ cinna git link # init the clone, sparse-checkout <subdir>, fetch + reset --mixed
318
+ cinna git commit -m "…" [--push] # stage the subdir + commit (honors .gitignore)
319
+ cinna git push # fast-forward only; rejected pushes tell you to pull --rebase
320
+ cinna git pull # rebase the remote in; Mutagen mirrors it into the running env
321
+ cinna git log # recent commits touching this agent's subdir
322
+ cinna git checkout <ref> [--reload] # restore a past version's workspace/ files into
323
+ # the tree (uncommitted) + flush to the running env via Mutagen
324
+ # — debug/rollback without committing
325
+ cinna git unlink # stop offering git helpers (keeps .git + history)
326
+ ```
327
+
328
+ `cinna setup` / `cinna agent sync` auto-run `git link` when the agent is already
329
+ git-versioned, so the developer gets a working tree from the first checkout.
330
+ `--agent <ref>` targets a synced child from the account root (like `cinna sync`).
331
+
332
+ Key behaviors: `link` uses `git reset --mixed` (never `--hard`) so the backend's
333
+ in-flight changes survive as ordinary uncommitted edits; pushes are fast-forward-only
334
+ and never auto-forced; a `sync_direction=pull` agent refuses local pushes; and a legacy
335
+ *flat* workspace that becomes git-versioned is **not** auto-converted (link prints a
336
+ disconnect + re-sync instruction).
337
+
338
+ ### Backend contract (cinna-core)
339
+
340
+ The CLI consumes one discovery endpoint; the agent is derived from the per-agent
341
+ token, so the path has **no `{agent_id}`**:
342
+
343
+ ```
344
+ GET /api/v1/cli/git-coordinates (Auth: per-agent CLI JWT)
345
+ ```
346
+
347
+ Response (`CliGitCoordinates` — `client.get_git_coordinates`, modelled by
348
+ `git_versioning.GitCoordinates`). `vcs_enabled=false` ⇒ all other fields null; a 404
349
+ (older backend) is treated as `vcs_enabled=false`:
350
+
351
+ ```jsonc
352
+ {
353
+ "vcs_enabled": true, // false ⇒ agent has no git source
354
+ "repo_url": "git@github.com:acme/agents.git",
355
+ "subdir": "hr-bot", // null ⇒ agent lives at the repo root
356
+ "ref": "main",
357
+ "sync_direction": "bidirectional", // "pull" | "push" | "bidirectional"
358
+ "last_synced_commit": "a1b2c3…", // SHA the backend last imported/pushed; may be null
359
+ "auth_hint": "ssh" // "ssh" | "https" — which local cred the DEV needs
360
+ }
361
+ ```
362
+
363
+ The remote repo stores each agent as the `schema_version`-2 bundle snapshot — this is
364
+ the layout `link` reconciles against (`reset --mixed` brings the manifest + `.gitignore`
365
+ from the ref; `workspace/**` stays the live copy):
366
+
367
+ ```
368
+ <repo-root>/<subdir>/
369
+ ├── cinna.agent.json # backend-owned manifest (prompts, SDK config, schedules,
370
+ │ # plugin specs, required_credential_specs, content_hash…)
371
+ ├── workspace/ # the editable agent files (scripts/, docs/, …)
372
+ └── .gitignore # auto-generated; excludes credentials/, app-data/, logs/,
373
+ # databases/, uploads/, plugins-derived, __pycache__, *.pyc…
374
+ ```
375
+
376
+ Contract rules the CLI honors:
377
+
378
+ - **Two-writer, fast-forward-only.** Backend (deploy key) and developer (own creds)
379
+ push the same ref; both ff-only, no auto-merge. A rejected dev push ⇒ surface
380
+ `git pull --rebase`, never force.
381
+ - **Backend-owned manifest.** `cinna.agent.json` is regenerated by the backend from
382
+ the DB on every backend push/connect — the CLI commits it as-is and never invents
383
+ values (it lacks the DB/env inputs). Editing prompt **files** under
384
+ `workspace/docs/` flows back into the DB via the platform's prompt-sync.
385
+ - **Never committable** (the committed `.gitignore` + a local `.git/info/exclude`
386
+ enforce it; the CLI never `git add -f`): `credentials/`, `app-data/`, logs,
387
+ databases, `uploads/`, plugins-derived files, `__pycache__/`, `*.pyc`, plus the
388
+ CLI's own `.cinna/` (holds the token) and generated guides.
389
+ - **Deploy key is host-side only** and never leaves the backend; `git-coordinates`
390
+ deliberately omits all key material — the dev authenticates with their own
391
+ git/SSH (`auth_hint` only advises which).
392
+ - **Backend adoption of dev pushes.** After a dev push the backend is behind; it
393
+ adopts the change when the user clicks **Pull** on the agent's Git Versioning card
394
+ or via the configured GitOps webhook — the CLI cannot trigger it.
395
+
396
+ The backend half lives in cinna-core — see its `docs/agents/agent_git_versioning/` <!-- nocheck: cross-repo (cinna-core) path -->
397
+ plus `backend/app/api/routes/cli.py` (`CliGitCoordinates` / `_git_auth_hint`),
398
+ `GitSourceService`, and `SSHKeyService`; that repo owns the authoritative spec.
399
+
400
+ ---
401
+
260
402
  ## Sync Transport
261
403
 
262
404
  ### Wire path
@@ -430,7 +572,7 @@ When a CLI token expires (or is revoked) the normal remedy is `cinna set-token <
430
572
 
431
573
  **Account tokens** refresh without a paste. `cinna login` (run inside an account workspace) drives the platform's RFC 8628 device-authorization flow: `POST /account/login/start` returns a short code + verification URL, the user clicks **Authorize** in the browser (already signed in), and the CLI polls `POST /account/login/poll` until it receives the fresh token, which it writes back into `.cinna/account.json` in place. The poll endpoint always returns HTTP 200 with a `status` field (`authorization_pending` / `slow_down` / `authorized` / `access_denied` / `expired_token`) — a deliberate divergence from RFC 8628's 400+`error` shape. Run from a fresh folder, the same command bootstraps a new account workspace instead of resuming one.
432
574
 
433
- **Bulk repair** is `cinna doctor`. It reconciles the `~/.cinna/agents.json` registry against the Mutagen daemon and heals the state that drifts as agents come and go — registry entries whose workspace was deleted, sessions halted on a deleted local root or stuck retrying a dead remote env, and orphaned sessions (Mutagen has no "stop after N failures" knob, so these retry forever until terminated). Expired **per-agent** tokens under an account workspace are re-minted automatically through the parent account token; when the **account** token has itself expired, doctor groups the blocked agents into a single "run `cinna login`" finding instead of attempting re-mints that would 401. Standalone agents are reported for a manual `cinna set-token`.
575
+ **Bulk repair** is `cinna doctor`. It reconciles the `~/.cinna/agents.json` registry against the Mutagen daemon and heals the state that drifts as agents come and go — registry entries whose workspace was deleted, sessions halted on a deleted local root or stuck retrying a dead remote env, and orphaned sessions (Mutagen has no "stop after N failures" knob, so these retry forever until terminated). It prints the live `cinna-*` session inventory up front — each tagged with the agent and folder it serves — then walks three ordered, separately-confirmed steps (each defaulting to Yes): **delete stalled sessions**, **terminate active sessions** (the healthy leftovers, recreated on the next `cinna dev`), and **refresh tokens**. Expired **per-agent** tokens under an account workspace are re-minted automatically through the parent account token; when the **account** token has itself expired, doctor groups the blocked agents into a single "run `cinna login`" finding instead of attempting re-mints that would 401. Standalone agents are reported for a manual `cinna set-token`.
434
576
 
435
577
  ### Authorization
436
578
 
@@ -460,6 +602,7 @@ When a CLI token expires (or is revoked) the normal remedy is `cinna set-token <
460
602
  | GET | `/api/v1/cli/agents/{id}/building-context` | CLI JWT | Assembled building prompt |
461
603
  | POST | `/api/v1/cli/agents/{id}/knowledge/search` | CLI JWT | Knowledge base search (via MCP proxy) |
462
604
  | GET | `/api/v1/cli/agents/{id}/sync-runtime` | CLI JWT | Required Mutagen version + hash (also used by `cinna list` / `cinna status` as a cheap token-validity probe) |
605
+ | GET | `/api/v1/cli/git-coordinates` | CLI JWT | Agent's git-versioning coordinates — **no `{id}`**, derived from the token (see "Git Versioning"). 404 on older backends ⇒ treated as not-versioned |
463
606
  | POST | `/api/v1/cli/agents/{id}/exec` | CLI JWT | Streaming SSE command execution |
464
607
  | WSS | `/api/v1/cli/agents/{id}/sync-stream` | CLI JWT | Mutagen transport tunnel |
465
608
  | POST | `/api/v1/cli/account/login/start` | None | Begin a `cinna login` device-authorization request |
@@ -558,6 +701,21 @@ git push origin main && git push origin v0.1.5
558
701
 
559
702
  ---
560
703
 
704
+ ## Feature Documentation
705
+
706
+ Per-feature docs live under `docs/features/{feature}/` in up to three layers:
707
+ `{feature}.md` (business logic / reasoning), `{feature}_tech.md` (implementation +
708
+ file refs), `{feature}_acceptance.md` (live e2e scenarios a testing agent runs
709
+ against a real environment). Author new ones with the `/cinna-cli.feature.doc`
710
+ command (`.claude/commands/cinna-cli.feature.doc.md`) and validate references with
711
+ `scripts/check_docs_references.py`.
712
+
713
+ | Feature | Docs | Summary |
714
+ |---------|------|---------|
715
+ | Git Versioning (`cinna git`) | [business](features/git_versioning/git_versioning.md) · [tech](features/git_versioning/git_versioning_tech.md) · [acceptance](features/git_versioning/git_versioning_acceptance.md) | Version an agent's workspace with git against its external remote (commit/push/pull/rollback) alongside live Mutagen sync. |
716
+
717
+ ---
718
+
561
719
  ## Related Projects
562
720
 
563
721
  - **cinna-core** — the platform backend. Hosts the API routes this CLI calls, the agent runtime, env core, building mode, and the web UI. Source plan for this CLI feature: `cinna-core/docs/drafts/cinna-cli-live-sync_plan.md`.