@stonepandastudio/cairn 0.2.0 → 0.2.1

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 (2) hide show
  1. package/README.md +44 -37
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,11 +1,10 @@
1
1
  # @stonepandastudio/cairn
2
2
 
3
- Shared AI workflow scaffolding for Stone Panda repos.
3
+ Shared AI workflow scaffolding, kept in sync across several repos.
4
4
 
5
- Five repos `glossr-api`, `glossr-cli`, `glossr-frontend`, `snap-proof/backend`,
6
- `snap-proof/frontend`each carry an `ai/` folder and a `.claude/commands/` folder
7
- holding the same workflow: brief description plan execute → review → QA, with
8
- the steps mirrored into Jira. They were copied between repos by hand and drifted.
5
+ Each repo carries an `ai/` folder and a `.claude/commands/` folder holding the same
6
+ workflowbrief description plan execute review → QA, with the steps
7
+ mirrored into an issue tracker. Copied between repos by hand, they drift.
9
8
 
10
9
  A cairn is a stack of stones left to mark a trail. That is what this does: it leaves
11
10
  markers — a manifest of what it generated, and a report of where the copies stopped
@@ -13,21 +12,21 @@ agreeing.
13
12
 
14
13
  ```bash
15
14
  npm i -D @stonepandastudio/cairn
16
- npx cairn init --stack backend --tracker jira-server --project-key PROOF --story-type Task
15
+ npx cairn init --stack backend --tracker jira-server --project-key MYPROJ --story-type Task
17
16
  ```
18
17
 
19
18
  ## What v1 does
20
19
 
21
20
  | Command | |
22
21
  |---|---|
23
- | `cairn tracker <cmd>` | Issue tracker client. Replaces the four copied `ai/scripts/jira.js` files |
22
+ | `cairn tracker <cmd>` | Issue tracker client. Replaces the copied `ai/scripts/jira.js` files |
24
23
  | `cairn doctor` | Cross-repo drift report, plus per-repo generated-file state |
25
24
  | `cairn init` | Makes a repo cairn-managed: writes `cairn.config.json`, `_cairn/`, and the shim |
26
25
 
27
26
  Template rendering — generating the command stubs, `WORKFLOW.md` and the agent role
28
27
  contracts from one workflow declaration — is v2, and deliberately not in this release.
29
- v1 swaps the Jira client under five repos; bundling prompt changes into the same
30
- release would make any regression impossible to attribute.
28
+ v1 swaps the tracker client under the consuming repos; bundling prompt changes into
29
+ the same release would make any regression impossible to attribute.
31
30
 
32
31
  ## The two folders
33
32
 
@@ -37,7 +36,7 @@ repo/
37
36
  _cairn/ cairn writes this. nobody hand-edits it.
38
37
  manifest.json what was generated, from which template, at which hash
39
38
  scripts/jira.js vendored shim
40
- ai/ project-owned. cairn seeds it at init and never touches it again.
39
+ ai/ project-owned. cairn never touches it.
41
40
  contexts/ progress/ tasks/ infrastructure/
42
41
  ```
43
42
 
@@ -51,27 +50,27 @@ Generated files are **committed**, not gitignored. Claude Code discovers
51
50
  ## Tracker
52
51
 
53
52
  ```bash
54
- cairn tracker list-statuses PROOF
55
- cairn tracker create-task "Protected image fetch API"
56
- cairn tracker create-subtask PROOF-217 "Step 1: signed URL issuing"
57
- cairn tracker set-status PROOF-218 "In Progress"
58
- cairn tracker append-description PROOF-217 ./ai/tasks/PROOF-217/brief-step-1.md --markup
59
- cairn tracker close-story GLO-42 # cascades through subtasks first
53
+ cairn tracker list-statuses MYPROJ
54
+ cairn tracker create-task "Some task title"
55
+ cairn tracker create-subtask MYPROJ-101 "Step 1: first slice"
56
+ cairn tracker set-status MYPROJ-102 "In Progress"
57
+ cairn tracker append-description MYPROJ-101 ./ai/tasks/MYPROJ-101/brief-step-1.md --markup
58
+ cairn tracker close-story MYPROJ-42 # cascades through subtasks first
60
59
  ```
61
60
 
62
- Providers are `jira-server` and `none`. `none` is a real provider, not an error case:
63
- `glossr-cli` has no tracker, and the workflow steps become no-ops rather than every
64
- command stub needing an "if this repo has Jira" branch written in prose.
61
+ Providers are `jira-server` and `none`. `none` is a real provider, not an error
62
+ case: a repo with no tracker makes the workflow steps no-ops rather than every
63
+ command stub needing an "if this repo has a tracker" branch written in prose.
65
64
 
66
- Three things the four copied scripts did that this does not:
65
+ Three things the copied scripts did that this does not:
67
66
 
68
67
  - **`process.exit` from library code.** Failures throw `TrackerError`; the CLI layer
69
68
  chooses the exit code. That is what makes the client callable from a workflow runner.
70
69
  - **Fail on a re-run.** Transitioning to a status the issue already holds is a
71
70
  successful no-op. `NoTransitionError` exits 0 — re-running a step must be safe.
72
71
  - **Ask an agent to convert markup by hand.** `ai/JIRA_MARKUP.md` was a prose document
73
- in three variants explaining markdown → Jira wiki conversion. It is `toMarkup()` now,
74
- under test, reachable via `--markup`.
72
+ explaining markdown → Jira wiki conversion. It is `toMarkup()` now, under test,
73
+ reachable via `--markup`.
75
74
 
76
75
  Credentials come from the repo's `.env` (`JIRA_BASE_URL`, `JIRA_USER`, `JIRA_PASSWORD`).
77
76
  Jira Server 8.5.1 predates PAT support, so auth is Basic. Anything already in the
@@ -80,9 +79,9 @@ environment wins over the file.
80
79
  ### Legacy command names
81
80
 
82
81
  `create-task`, `create-story`, `close-story` and friends are all still accepted, and
83
- output formats are byte-for-byte what the old scripts printed. Roughly forty prose
84
- references across five repos name these strings, and the agents parse the output.
85
- They get renamed in the v2 pass that regenerates those documents.
82
+ output formats are byte-for-byte what the old scripts printed. Existing prose
83
+ references name these strings and the agents parse the output, so they are kept
84
+ until the v2 pass regenerates those documents.
86
85
 
87
86
  ## Doctor
88
87
 
@@ -93,13 +92,15 @@ cairn doctor --json
93
92
  cairn doctor --strict # exit 1 on drift or a hand-edited generated file
94
93
  ```
95
94
 
95
+ Run it from the directory holding `repos.json`, or pass `--config <file>`.
96
+
96
97
  It reports two independent axes, and keeping them apart is the point:
97
98
 
98
99
  **Drift** — cross-repo. Do the copies still agree? Raw comparison is noise, so each
99
- file is normalized first: BOM and CRLF stripped, repo paths and names folded,
100
- `GLO-18`/`PROOF-210` folded to `{{ISSUE}}`, and declared vars folded to
101
- `{{placeholder}}`. What survives is drift no template variable explains. Files are
102
- then clustered by normalized content; the largest cluster becomes the reference.
100
+ file is normalized first: BOM and CRLF stripped, repo paths and names folded, issue
101
+ keys folded to `{{ISSUE}}`, and declared vars folded to `{{placeholder}}`. What
102
+ survives is drift no template variable explains. Files are then clustered by
103
+ normalized content; the largest cluster becomes the reference.
103
104
 
104
105
  | Status | Meaning |
105
106
  |---|---|
@@ -116,8 +117,11 @@ match what is on disk?
116
117
  |---|---|
117
118
  | `MANAGED` | on-disk hash matches what cairn wrote |
118
119
  | `MODIFIED` | someone hand-edited a generated file |
119
- | `OUTDATED` | cairn has newer content for it |
120
- | `DELETED` | it is gone; `sync` will restore it |
120
+ | `OUTDATED` | cairn has newer content for it — needs template hashes, wired in v2 |
121
+ | `DELETED` | it is gone; a future `cairn sync` will restore it |
122
+
123
+ v1 reports `MANAGED`, `MODIFIED` and `DELETED`. `OUTDATED` and the `sync` that acts
124
+ on these states arrive with the v2 renderer.
121
125
 
122
126
  A file can be perfectly in sync across repos while being hand-edited away from its
123
127
  template, and vice versa. `MODIFIED` outranks `OUTDATED` in the report because
@@ -128,17 +132,20 @@ overwriting a hand edit is the destructive outcome.
128
132
  - `repos[]` — name, path, stack. Per-repo settings live in each repo's own
129
133
  `cairn.config.json`; the inline `vars` blocks are a fallback used only until a repo
130
134
  has been through `cairn init`, so migration can happen one repo at a time.
131
- - `pathAliases` — local → canonical. `glossr-cli` calls its stubs `execute-tests.md`
132
- and `review-code.md`; aliasing folds them onto the cohort's names instead of
133
- reporting one `MISSING` and one `STRANDED` for what is the same file.
135
+ - `pathAliases` — local → canonical. When one repo names a stub `execute-tests.md`
136
+ where the others use `execute-test-plan.md`, aliasing folds them onto the cohort's
137
+ names instead of reporting one `MISSING` and one `STRANDED` for the same file.
134
138
  - `shared[]` — glob rules. `cohort: "all"` compares every repo; `cohort: "stack"`
135
139
  compares backend-with-backend. `requires: { tracker: true }` skips repos with no
136
140
  tracker. A repo with no config has an *unknown* tracker, not an absent one, and is
137
141
  never skipped on that basis.
138
142
  - Anything not matched by a rule — `ai/contexts/`, `ai/progress/`, `ai/tasks/`,
139
143
  `DATABASE_SCHEMA.md` — is per-project by design and never inspected.
140
- `ai/INITIAL_PROMPT.md` is explicitly excluded: four variants at 0% shared content
141
- make it a per-project document, not a drifted template.
144
+ `ai/INITIAL_PROMPT.md` is explicitly excluded: variants at ~0% shared content make
145
+ it a per-project document, not a drifted template.
146
+
147
+ v2 splits this flat file into a per-project `workspace.json` plus an opt-in hub that
148
+ references the projects for cross-project comparison. See `DESIGN.md`.
142
149
 
143
150
  ## Layout
144
151
 
@@ -155,4 +162,4 @@ schema.json JSON Schema for cairn.config.json
155
162
  test/run.js dependency-free test runner
156
163
  ```
157
164
 
158
- No runtime dependencies. Node >= 18. `npm test` runs 34 tests.
165
+ No runtime dependencies. Node >= 18. `npm test` runs 35 tests.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonepandastudio/cairn",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Shared AI workflow scaffolding for Stone Panda repos — issue tracker client and drift doctor.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {