arcane-cli 0.26.0 → 0.26.2

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 CHANGED
@@ -30,7 +30,7 @@ npm install -g arcane-cli # then: spell init
30
30
 
31
31
  <div align="center">
32
32
 
33
- **🔁 opinionated lifecycle** &nbsp;·&nbsp; **📜 36 spells** &nbsp;·&nbsp; **🤖 12 agents** &nbsp;·&nbsp; **⚖️ 23 governance standards** &nbsp;·&nbsp; **📝 markdown-native** &nbsp;·&nbsp; **🔌 any AI client / tracker**
33
+ **🔁 opinionated lifecycle** &nbsp;·&nbsp; **📜 38 spells** &nbsp;·&nbsp; **🤖 12 agents** &nbsp;·&nbsp; **⚖️ 23 governance standards** &nbsp;·&nbsp; **📝 markdown-native** &nbsp;·&nbsp; **🔌 any AI client / tracker**
34
34
 
35
35
  </div>
36
36
 
@@ -113,22 +113,27 @@ Arcane isn't a prompt snippet — it's a full framework. Everything installs int
113
113
 
114
114
  | Layer | What you get |
115
115
  | --- | --- |
116
- | 📜 **Spells** | **34** prompt-driven workflows spanning the entire lifecycle — planning, architecture, implementation, testing, review, shipping, session management, and ops. |
117
- | ⚖️ **Governance** | **19** battle-tested standards as drop-in templates: git conventions, testing standards, CI/CD, threat model, ADR format, naming, security hardening, and more. |
116
+ | 📜 **Spells** | **38** prompt-driven workflows spanning the entire lifecycle — planning, architecture, implementation, testing, review, shipping, session management, and ops. |
117
+ | ⚖️ **Governance** | **23** battle-tested standards as drop-in templates: git conventions, testing standards, CI/CD, threat model, ADR format, naming, security hardening, and more. |
118
118
  | 🤖 **Agents** | **12** ready-made agent personas with roles, clusters, and a gamified autonomy model — assign work and power levels per repo. |
119
119
  | 🛠️ **CLI** | `spell init / add / update / status / uninstall` — install by profile or à la carte, and keep everything in sync as new versions ship. |
120
120
 
121
+ <!-- arcane:start -->
121
122
  <details>
122
- <summary><b>📜 The full spell catalogue (34)</b></summary>
123
-
124
- **Core Spell Loop** — `plan` · `enchant` · `scope` · `architect` · `implement` · `test` · `review` · `ship`
125
- **Session** — `open-session` · `close-session` · `status`
126
- **Operational & Git** — `commit-work` · `todo` · `check-drift` · `bug` · `create-pull-request` · `address-review` · `bump`
127
- **Specialized** — `full-cycle` · `review-batch` · `security-review` · `dotnet-expert` · `product-review` · `suggest-feature`
128
- **Knowledge & Docs** — `document` · `explain-concept` · `feedback` · `save-idea` · `manifest`
129
- **Business & Admin** — `summon-venture` · `brainstorm` · `generate-bot-icons` · `present-arcane` · `arcane-version`
123
+ <summary><b>📜 The full spell catalogue (38)</b></summary>
124
+
125
+ **Session** — `open-session` · `close-session` · `commit-work` · `status` · `arcane-version`
126
+ **Capture** — `save-idea` · `todo` · `feedback` · `suggest-feature` · `document` · `brainstorm` · `explain-concept`
127
+ **Delivery** — `create-pull-request` · `sync-pull-request` · `address-review`
128
+ **Review** — `review` · `review-batch`
129
+ **Planning** — `plan` · `architect` · `scope` · `product-review`
130
+ **Build** — `implement` · `test` · `full-cycle` · `bug` · `bump` · `dotnet-expert` · `security-review` · `ship` · `enchant` · `generate-bot-icons` · `make-discoverable` · `scry`
131
+ **Docs** — `adopt-docs`
132
+ **Venture** — `summon-venture` · `manifest`
133
+ **Meta** — `present-arcane` · `check-drift`
130
134
 
131
135
  </details>
136
+ <!-- arcane:end -->
132
137
 
133
138
  <details>
134
139
  <summary><b>⚖️ The governance standards (23)</b></summary>
@@ -478,6 +478,17 @@ git branch -d <branch> # delete local branch (skip if branch
478
478
  git push origin --delete <branch> # delete remote branch (safety net — --delete-source-branch true usually handles this; ignore 'does not exist' errors)
479
479
  ```
480
480
 
481
+ **MCP fail-fast / fallback rule:** one abnormal MCP tool failure — a hang, an idle-timeout abort, a
482
+ transport error, or an empty response where data is clearly expected — marks that MCP server **down
483
+ for the rest of the session**. Do not retry it blindly. All subsequent operations that would have used
484
+ it fall back to the documented CLI (`az repos pr` / `gh` / a direct REST call), and the downgrade is
485
+ reported in output so a human sees it happened. The known-issues rows below (`MCP vote_pull_request`,
486
+ `MCP create_pull_request`) are concrete instances of this general rule, not special cases of their own.
487
+ **Consumer hardening:** set a per-server `"timeout"` (milliseconds) in `.mcp.json` so a hang aborts on a
488
+ predictable schedule instead of running to the client's own default idle limit (as long as 30 minutes).
489
+ Origin: a real ops session lost roughly an hour to two consecutive 30-minute MCP hangs before the
490
+ documented `az` fallback was used (2026-08-14).
491
+
481
492
  **Known issues:**
482
493
 
483
494
  | Issue | Symptom | Fix |
@@ -54,6 +54,12 @@ Paste this entire file into any AI client (Claude web, ChatGPT, etc.) to give it
54
54
  - **Project/domain documents:** use explicit descriptive paths such as `docs/`, `security/`, `infrastructure/`, or a configured business root. These add project context alongside framework standards.
55
55
  - **Overrides are not yet supported:** editing a managed `.arcane/governance/` standard can be replaced by `arcane update`. Additive project documents are safe; overriding a shipped standard requires the open customization/override model.
56
56
 
57
+ ## Research Reports
58
+
59
+ Research findings (competitive analysis, technical spikes, feasibility studies — the output of the Research & Backlog Analyst role) live at `docs/research/<topic-slug>.md`, one file per report. No dedicated spell produces these: `spell-document` already proposes a target path from project structure and matches its destination directory's existing conventions — point it at `docs/research/` for investigative content, the same way it already proposes `docs/` or `.arcane/governance/` for other document types. The directory is created on first real report, not pre-seeded on `spell init`.
60
+
61
+ Use this repo's standard frontmatter (below) plus one addition: `sources` — a list of what was consulted. Every claim in the body traces back to one of these or is explicitly marked speculative. Structure the body summary-first: a short **Summary** with the key findings, then **Findings** with full detail and inline citations, then an optional **Follow-ups** for anything that should become a TODO item — route those via `spell-todo`, which cross-references the report path. Throughout, distinguish **verified facts**, **reasonable inferences**, and **speculation** explicitly; don't let an inference read as a checked fact.
62
+
57
63
  ## Documentation Format
58
64
 
59
65
  Every doc uses YAML frontmatter: `title`, `audience` (human/ai/both), `last_updated`, `status` (draft/active/deprecated), `tags`. Use wiki-links (`[[filename]]`) for cross-references.
@@ -81,6 +81,13 @@ When completing a PR via `az repos pr update`, do **not** pass `--squash true`.
81
81
  az repos pr update --id <PR_ID> --org https://dev.azure.com/<org> --status completed --delete-source-branch true
82
82
  ```
83
83
 
84
+ ## MCP Fail-Fast / Fallback
85
+
86
+ One abnormal MCP tool failure (hang, idle-timeout abort, transport error, empty response where data is
87
+ expected) marks that server down for the rest of the session — fall back to the documented CLI (`az
88
+ repos pr` / `gh` / REST), no blind retries, and report the downgrade in output. Full rule and origin
89
+ incident: `.arcane/governance/git-conventions.md` → Known issues.
90
+
84
91
  ## Branch Naming (Interactive Sessions)
85
92
 
86
93
  Interactive tool session branches use:
@@ -31,7 +31,7 @@ Workflow:
31
31
  - Decisions made (even implicit ones like naming choices, tool preferences, or workflow patterns).
32
32
  - Problems encountered and how they were resolved (troubleshooting).
33
33
  - Lessons learned (anything that cost time, surprised the user, or should prevent future mistakes).
34
- - **Capture tie-in tip:** If this session produced durable analysis worth formalizing (a design, an investigation, a reusable explanation), suggest running `spell-document` before closing so it lands in the right doc. For quick ideas worth keeping but not yet actionable, suggest `spell-save-idea`.
34
+ - **Capture tie-in tip:** If this session produced durable analysis worth formalizing (a design, an investigation, a research finding, a reusable explanation), suggest running `spell-document` before closing so it lands in the right doc — a research finding defaults to `docs/research/<topic-slug>.md` per `portable-bootstrap.md`'s Research Reports convention. For quick ideas worth keeping but not yet actionable, suggest `spell-save-idea`.
35
35
 
36
36
  1b. **Verify in-flight async work before writing any output artifact (EF-21). Enforcement: structured spell gate (ARC-023) — this workflow requires the observable state of every dispatched item before proceeding to step 2.** "I started it" is not "it worked." Before the journal, TODO.md, or the handoff are written, enumerate every piece of asynchronous work dispatched during this session that could still be running or could have failed after being kicked off — CI/CD runs, deployments, package publishes, long-running background tasks, PR checks. For each, **actively check** its current status through whatever means is available (CI provider API/CLI, deployment dashboard, `gh run view`, `az pipelines runs show`, etc.) — attempt the check before reaching for `unverifiable`; that state exists for genuine access limits (no CLI/API access, no credentials, provider outage), not for skipping a check that was merely inconvenient to run. Then classify into exactly one state:
37
37
 
@@ -152,6 +152,8 @@ Workflow:
152
152
 
153
153
  a. Run `git push origin <branch>`.
154
154
 
155
+ a1. **MCP fail-fast / fallback.** If an MCP tool used anywhere in this step (e.g. `create_pull_request`) fails abnormally once — a hang, an idle-timeout abort, a transport error, or an empty response where data is clearly expected — treat that server as down for the rest of this session. Do not retry it blindly; fall back to the raw CLI paths below (`gh pr create` / `az repos pr create`) and report the downgrade. Full rule: `.arcane/governance/git-conventions.md` → Known issues.
156
+
155
157
  b. **🛑 Mandatory pre-PR rebase (governance guard, applies to every path below).** Before invoking any PR-creation command — whether via `spell-create-pull-request`, raw `gh pr create`, raw `az repos pr create`, or an MCP `create_pull_request` tool — you MUST:
156
158
 
157
159
  ```bash
@@ -25,8 +25,8 @@ The user's input describes what to capture and where. If no argument was provide
25
25
  Identify:
26
26
 
27
27
  - **Topics** — what conversation insights to extract (e.g., "naming analysis", "architecture comparison").
28
- - **Target paths** — where to write (e.g., `docs/...`, `.arcane/governance/...`). If the user gives only topics, propose sensible paths from the project structure.
29
- - **Document type** — reference doc, decision record, analysis report, inventory, or guide.
28
+ - **Target paths** — where to write (e.g., `docs/...`, `.arcane/governance/...`). If the user gives only topics, propose sensible paths from the project structure. For a research report specifically (cited investigation, competitive analysis, feasibility study), default to `docs/research/<topic-slug>.md` per `portable-bootstrap.md`'s Research Reports convention.
29
+ - **Document type** — reference doc, decision record, analysis report, research report, inventory, or guide.
30
30
 
31
31
  ## Step 2 — Extract from Conversation
32
32
 
@@ -118,6 +118,7 @@ Determine the target file(s) for each item:
118
118
  | Speculative idea or future-facing concept | `TODO.md` under `## Product Ideas` or the best matching section |
119
119
  | ADR candidate | `DECISIONS.md` — flag it as pending, do not write the full ADR yet |
120
120
  | Journal-worthy context | `journal/` — propose a filename with today's date slug, do not create the file yet |
121
+ | Finding sourced from a research report | `TODO.md` under the matching section — cross-reference the report path (e.g., `— see docs/research/<slug>.md`) |
121
122
  | Business-specific execution item | Both `TODO.md` AND the relevant `{BUSINESS_ROOT}/<name>/overview.md` reference section |
122
123
 
123
124
  ## Step 4 — Show Proposal
@@ -0,0 +1,10 @@
1
+ {
2
+ "$comment": "Example MCP server config. Replace or remove the example server below with your own. Set a per-server \"timeout\" (milliseconds) so a hung server aborts on a predictable schedule instead of running to the client's own default idle limit (as long as 30 minutes) -- see .arcane/governance/git-conventions.md's MCP fail-fast / fallback rule.",
3
+ "mcpServers": {
4
+ "example-server": {
5
+ "command": "npx",
6
+ "args": ["-y", "@example/mcp-server"],
7
+ "timeout": 30000
8
+ }
9
+ }
10
+ }
package/dist/index.js CHANGED
@@ -428,6 +428,15 @@ var COMPONENTS = [
428
428
  skipExisting: true,
429
429
  initOnly: true
430
430
  },
431
+ // Optional MCP config scaffold (BC-22/I12). skipExisting: a repo's own
432
+ // .mcp.json is user-owned server config Arcane must never overwrite.
433
+ // Not initOnly -- useful to retrofit via `spell add` on an existing repo too.
434
+ {
435
+ name: "mcp-config-template",
436
+ description: "Example .mcp.json with a per-server timeout, companion to the MCP fail-fast rule",
437
+ files: [".mcp.json"],
438
+ skipExisting: true
439
+ },
431
440
  {
432
441
  name: "records-conventions",
433
442
  description: "Supersession, tombstone, and retention conventions for records repositories",
@@ -4067,6 +4076,47 @@ async function checkPushPolicy(targetDir) {
4067
4076
  message: `declared "blocked" but not enforced \u2014 ${missing.join("; ")}. The manifest claims a protection this repository does not have.`
4068
4077
  };
4069
4078
  }
4079
+ async function checkMcpConfig(targetDir) {
4080
+ const name = "MCP config (per-server timeout, I12)";
4081
+ const filePath = join11(targetDir, ".mcp.json");
4082
+ let raw;
4083
+ try {
4084
+ raw = await readFile6(filePath, "utf8");
4085
+ } catch {
4086
+ return { name, passed: true, blocking: false, message: "no .mcp.json \u2014 nothing to check" };
4087
+ }
4088
+ let parsed;
4089
+ try {
4090
+ parsed = JSON.parse(raw);
4091
+ } catch {
4092
+ return {
4093
+ name,
4094
+ passed: false,
4095
+ blocking: false,
4096
+ message: ".mcp.json exists but contains invalid JSON"
4097
+ };
4098
+ }
4099
+ const servers = parsed.mcpServers ?? {};
4100
+ const serverNames = Object.keys(servers);
4101
+ if (serverNames.length === 0) {
4102
+ return { name, passed: true, blocking: false, message: "no MCP servers configured" };
4103
+ }
4104
+ const missingTimeout = serverNames.filter((n) => typeof servers[n]?.timeout !== "number");
4105
+ if (missingTimeout.length > 0) {
4106
+ return {
4107
+ name,
4108
+ passed: false,
4109
+ blocking: false,
4110
+ message: `server(s) missing a "timeout": ${missingTimeout.join(", ")} \u2014 a hang runs to the client's own default idle limit (up to 30 min) instead of a predictable one`
4111
+ };
4112
+ }
4113
+ return {
4114
+ name,
4115
+ passed: true,
4116
+ blocking: false,
4117
+ message: `${serverNames.length} server(s) configured, all with a timeout set`
4118
+ };
4119
+ }
4070
4120
  async function checkDelegations(targetDir) {
4071
4121
  const name = "Standing delegations (T13)";
4072
4122
  const filePath = join11(targetDir, ".arcane", "delegations.json");
@@ -4152,7 +4202,8 @@ async function runDoctor(targetDir, options = {}, assetsDir) {
4152
4202
  checkPullRebase(targetDir),
4153
4203
  checkPushPolicy(targetDir),
4154
4204
  checkPlatformBranchPolicy(targetDir),
4155
- checkDelegations(targetDir)
4205
+ checkDelegations(targetDir),
4206
+ checkMcpConfig(targetDir)
4156
4207
  ]);
4157
4208
  const sessionResults = await checkSessionContinuity(targetDir);
4158
4209
  results.push(...sessionResults);