arcane-cli 0.29.0 → 0.29.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/dist/assets/.arcane/governance/cicd-standards.md +16 -16
- package/dist/assets/.arcane/governance/compliance-standards.md +12 -28
- package/dist/assets/.arcane/governance/external-verification-standards.md +6 -6
- package/dist/assets/.arcane/governance/git-conventions.md +45 -18
- package/dist/assets/.arcane/governance/mobile-release-standards.md +14 -30
- package/dist/assets/.arcane/governance/new-business-setup.md +2 -1
- package/dist/assets/.arcane/governance/spell-authoring-standards.md +44 -20
- package/dist/assets/.arcane/governance/testing-standards.md +15 -7
- package/dist/assets/.arcane/governance/universal-agent-rules.md +24 -24
- package/dist/assets/.arcane/governance/web-discoverability-standards.md +16 -16
- package/dist/assets/.github/prompts/spell-address-review.prompt.md +1 -1
- package/dist/assets/.github/prompts/spell-commit-work.prompt.md +5 -3
- package/dist/assets/.github/prompts/spell-full-cycle.prompt.md +2 -2
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ Pipeline patterns, branch policies, and deployment gates for all your projects.
|
|
|
12
12
|
|
|
13
13
|
## Executive Summary
|
|
14
14
|
|
|
15
|
-
- Every code repository must have a CI pipeline that runs on PR creation and merge to main.
|
|
15
|
+
- Every code repository must have a CI pipeline that runs on PR creation and merge to main. **Enforcement: explicitly advisory prose (ARC-023) — prescriptive guidance for repos Prospero provisions; Arcane's own tooling does not enumerate an organization's repositories to verify each one has a CI pipeline.**
|
|
16
16
|
- Branch policies enforce PR requirements: build must pass, reviewer required, work item linked.
|
|
17
17
|
- Terraform changes use plan-on-PR / apply-on-merge with manual approval gates.
|
|
18
18
|
- Prospero owns pipeline creation and maintenance across all repos.
|
|
@@ -39,12 +39,12 @@ Applied to all code repositories (not docs-only repos per ADR-048):
|
|
|
39
39
|
|
|
40
40
|
| Policy | Setting | Rationale |
|
|
41
41
|
|--------|---------|-----------|
|
|
42
|
-
| **Require PR** | All branches → main | No direct pushes to main |
|
|
43
|
-
| **Minimum reviewers** | 1 (Lince for code, Merlin for architecture) | Quality gate |
|
|
44
|
-
| **Build validation** | CI pipeline must pass | No merging broken code |
|
|
45
|
-
| **Work item linking** | Required (when ticketing active) | Traceability |
|
|
46
|
-
| **Comment resolution** | All comments must be resolved | No ignored feedback |
|
|
47
|
-
| **Merge type** | Merge (no fast-forward) or Rebase and fast-forward — Squash disallowed | Preserves per-commit attribution trailers (ARC-009 §7); see [[git-conventions#Azure DevOps PR Merge Type]] |
|
|
42
|
+
| **Require PR** | All branches → main | No direct pushes to main. Enforcement: explicitly advisory prose (ARC-023) — prescriptive for consumer Azure DevOps repos; no Arcane check verifies a PR-required policy is configured. |
|
|
43
|
+
| **Minimum reviewers** | 1 (Lince for code, Merlin for architecture) | Quality gate. Enforcement: explicitly advisory prose (ARC-023) — prescriptive for consumer Azure DevOps repos; no Arcane check verifies configured reviewer counts. |
|
|
44
|
+
| **Build validation** | CI pipeline must pass | No merging broken code. Enforcement: explicitly advisory prose (ARC-023) — prescriptive for consumer Azure DevOps repos; no Arcane check verifies a build-validation policy is configured. |
|
|
45
|
+
| **Work item linking** | Required (when ticketing active) | Traceability. Enforcement: explicitly advisory prose (ARC-023) — prescriptive for consumer Azure DevOps repos; no Arcane check verifies it. |
|
|
46
|
+
| **Comment resolution** | All comments must be resolved | No ignored feedback. Enforcement: explicitly advisory prose (ARC-023) — prescriptive for consumer Azure DevOps repos; no Arcane check verifies a comment-resolution policy is configured. |
|
|
47
|
+
| **Merge type** | Merge (no fast-forward) or Rebase and fast-forward — Squash disallowed | Preserves per-commit attribution trailers (ARC-009 §7); see [[git-conventions#Azure DevOps PR Merge Type]]. Enforcement: verified external platform policy (ARC-023) — `spell doctor`'s `checkPlatformBranchPolicy` (src/commands/doctor.ts, backed by src/modules/platform-policy.ts's evaluateGitHubMergePolicy/evaluateAdoMergePolicy) queries live GitHub Rulesets or Azure DevOps branch policy and verifies the effective merge methods match this ladder — a local, on-demand CLI check the operator runs, not a check wired into CI itself. |
|
|
48
48
|
|
|
49
49
|
For docs-only repos (Arcane):
|
|
50
50
|
- PR not required (ADR-048 allows local ff-only merge for docs)
|
|
@@ -64,7 +64,7 @@ glob, and deliberately just one entry: `docs/**`/`journal/**`/`.arcane/governanc
|
|
|
64
64
|
directory-wide excludes would ALSO exclude any non-Markdown file a consumer happens to place in
|
|
65
65
|
those directories (a build script, a manifest, tooling config) — silently violating ARC-022's own
|
|
66
66
|
unconditional requirement that scripts, manifests, lockfiles, migrations, containers, and
|
|
67
|
-
infrastructure always remain triggering inputs, regardless of which directory they live in. Filetype-scoping to
|
|
67
|
+
infrastructure always remain triggering inputs, regardless of which directory they live in. **Enforcement: explicitly advisory prose (ARC-023) — prescriptive for the Azure DevOps template this repo ships to consumers; Arcane has no shipped `azure-pipelines.yml` file of its own to check parity against, and cannot verify a downstream repo kept the filter filetype-scoped.** Filetype-scoping to
|
|
68
68
|
`**/*.md` closes that gap: only actual Markdown files are excluded, anywhere in the tree; anything
|
|
69
69
|
else — including a `.md`-adjacent script — still triggers CI by default.
|
|
70
70
|
|
|
@@ -111,7 +111,7 @@ steps:
|
|
|
111
111
|
Previously had no path filter at all — fail-safe (never misses a code change) but wasteful (a
|
|
112
112
|
pure docs commit still burns a full pipeline run). Fail-safe path filter (ARC-022): the same
|
|
113
113
|
filetype-scoped `**/*.md` **exclude** entry as the .NET template above — never a directory-wide
|
|
114
|
-
exclude, and never an include list.
|
|
114
|
+
exclude, and never an include list. **Enforcement: explicitly advisory prose (ARC-023) — prescriptive for the Azure DevOps template this repo ships to consumers; Arcane has no shipped `azure-pipelines.yml` file of its own to check parity against, and cannot verify a downstream repo kept this filter filetype-scoped.**
|
|
115
115
|
|
|
116
116
|
```yaml
|
|
117
117
|
trigger:
|
|
@@ -149,7 +149,7 @@ steps:
|
|
|
149
149
|
### Terraform Pipeline
|
|
150
150
|
|
|
151
151
|
An **include** filter is correct here, not the ARC-022 anti-pattern — but only if it's a
|
|
152
|
-
**filetype** glob, not a directory-prefix one. An earlier version of this template included only
|
|
152
|
+
**filetype** glob, not a directory-prefix one. **Enforcement: explicitly advisory prose (ARC-023) — prescriptive for the Azure DevOps template this repo ships to consumers; Arcane has no shipped `azure-pipelines.terraform.yml` file of its own to check parity against, and cannot verify a downstream repo kept the include filter filetype-scoped rather than directory-prefixed.** An earlier version of this template included only
|
|
153
153
|
`infrastructure/terraform/**`: a directory-prefix pattern that silently misses any `.tf` file
|
|
154
154
|
added *outside* that one named directory (a new `modules/**` root, a renamed infra folder) —
|
|
155
155
|
exactly the "new code locations fail open" failure ARC-022 rejects, and exactly what EF-22's own
|
|
@@ -244,7 +244,7 @@ steps:
|
|
|
244
244
|
CI skip/run decisions are based **only on changed paths** — never on commit message, author
|
|
245
245
|
identity, or branch name. Do not add a *new* mechanism (a custom `docs(...)`-style commit-prefix
|
|
246
246
|
convention, a bot rule, a pipeline-level check) that lets a commit opt itself out of validation by
|
|
247
|
-
what it *says* rather than what it *changed*.
|
|
247
|
+
what it *says* rather than what it *changed*. **Enforcement: explicitly advisory prose (ARC-023) — prescriptive guidance for Azure DevOps consumer pipelines; this repo's own `.github/workflows/ci.yml` runs unconditionally on every push/PR to `main` with no path filter at all, so it neither implements nor is bound by this pattern, and no Arcane check inspects a downstream repo's CI configuration for compliance.**
|
|
248
248
|
|
|
249
249
|
Commit messages, authorship, and branch names are attacker-controlled metadata — anyone who can
|
|
250
250
|
push a commit controls all three. A CI-skip mechanism keyed on any of them is a bypass primitive:
|
|
@@ -253,7 +253,7 @@ actually touched. Path-based filtering (above) is the only trust signal this rep
|
|
|
253
253
|
recognizes, because the pipeline itself independently observes the changed paths rather than
|
|
254
254
|
trusting a claim embedded in the commit.
|
|
255
255
|
|
|
256
|
-
**Know the platform default, don't assume this rule alone controls it.** Azure Pipelines honors
|
|
256
|
+
**Know the platform default, don't assume this rule alone controls it. Enforcement: explicitly advisory prose (ARC-023) — this paragraph discloses a residual platform-level gap; it is not a mechanism Arcane enforces.** Azure Pipelines honors
|
|
257
257
|
`[skip ci]`, `[ci skip]`, `skip-checks: true`, `[skip azurepipelines]`, `[skip azpipelines]`,
|
|
258
258
|
`[skip azp]`, and `***NO_CI***` in a pushed commit message **by default**, on `trigger:`-driven
|
|
259
259
|
runs — this is platform behavior, not something a consumer opts into, and this governance rule
|
|
@@ -283,7 +283,7 @@ adopted exclude-based YAML triggers), a change to a new top-level code directory
|
|
|
283
283
|
triggers the pipeline (YAML is fail-safe) but does **not** require it to pass before merge (branch
|
|
284
284
|
policy is not) — the build can run, fail, and be ignored, or the PR can merge before it finishes.
|
|
285
285
|
Whenever a pipeline's YAML trigger scope changes, the branch policy's own path filter (if it has
|
|
286
|
-
one) must be reviewed and updated to match or be a strict superset — never left narrower.
|
|
286
|
+
one) must be reviewed and updated to match or be a strict superset — never left narrower. **Enforcement: explicitly advisory prose (ARC-023) — prescriptive for consumer Azure DevOps projects; Arcane has no visibility into a downstream repo's branch-policy path-filter configuration and cannot verify the two stay aligned.**
|
|
287
287
|
|
|
288
288
|
---
|
|
289
289
|
|
|
@@ -291,9 +291,9 @@ one) must be reviewed and updated to match or be a strict superset — never lef
|
|
|
291
291
|
|
|
292
292
|
| Environment | Gate | Who Approves |
|
|
293
293
|
|-------------|------|-------------|
|
|
294
|
-
| **Staging** | CI passes + PR approved | Automatic on merge |
|
|
295
|
-
| **Production** | Staging verified + manual approval | Human (operator) |
|
|
296
|
-
| **Terraform apply** | Plan reviewed + Checkov clean | Human (operator) |
|
|
294
|
+
| **Staging** | CI passes + PR approved | Automatic on merge. Enforcement: explicitly advisory prose (ARC-023) — describes a consumer Azure DevOps pipeline's intended gating; Arcane does not verify a downstream repo's environment configuration. |
|
|
295
|
+
| **Production** | Staging verified + manual approval | Human (operator). Enforcement: explicitly advisory prose (ARC-023) — describes a consumer Azure DevOps environment's approval configuration; Arcane does not verify it is actually configured. |
|
|
296
|
+
| **Terraform apply** | Plan reviewed + Checkov clean | Human (operator). Enforcement: explicitly advisory prose (ARC-023) — describes a consumer Azure DevOps pipeline's manual-apply step; Arcane does not verify it is actually configured. |
|
|
297
297
|
|
|
298
298
|
---
|
|
299
299
|
|
|
@@ -67,8 +67,7 @@ with EU visitors signing up for a free product is a plausible trigger; a company
|
|
|
67
67
|
not, but "zero" needs to be an actual verified fact about the user base, not an assumption based on
|
|
68
68
|
where the company is headquartered.
|
|
69
69
|
|
|
70
|
-
**Rule (CS-01)
|
|
71
|
-
what the processing does, never from the business's own location alone.
|
|
70
|
+
**Rule (CS-01): Determine GDPR applicability from the actual or intended user base's location and what the processing does, never from the business's own location alone. Enforcement: explicitly advisory prose (ARC-023) — GDPR applicability turns on real-world facts about a specific business's actual user base and processing, a legal/business judgment call no Arcane mechanism observes or verifies.**
|
|
72
71
|
|
|
73
72
|
### CS-02: A lawful basis and enforceable data-subject rights
|
|
74
73
|
|
|
@@ -80,8 +79,7 @@ Requests exercising these rights carry a response deadline (commonly one month,
|
|
|
80
79
|
cases) — a rights-request process that has no defined owner or turnaround time is itself a gap, even
|
|
81
80
|
before any request arrives.
|
|
82
81
|
|
|
83
|
-
**Rule (CS-02)
|
|
84
|
-
a defined owner and turnaround time — for handling data-subject rights requests.
|
|
82
|
+
**Rule (CS-02): Document a lawful basis per processing category, and maintain a working process — with a defined owner and turnaround time — for handling data-subject rights requests. Enforcement: explicitly advisory prose (ARC-023) — whether a lawful basis is properly documented and a rights-request process actually functions is a substantive judgment about the downstream product's own operations; `spell-compliance` can only ask and report on it, never verify or gate on it.**
|
|
85
83
|
|
|
86
84
|
### CS-03: 72-hour breach notification
|
|
87
85
|
|
|
@@ -90,8 +88,7 @@ relevant supervisory authority within 72 hours of the organization becoming awar
|
|
|
90
88
|
starts at awareness, not at confirmation of scope — an incident-response process that only begins
|
|
91
89
|
drafting a notification after a full investigation completes risks missing the window entirely.
|
|
92
90
|
|
|
93
|
-
**Rule (CS-03)
|
|
94
|
-
supervisory authority within 72 hours of awareness, even before the full scope of an incident is known.
|
|
91
|
+
**Rule (CS-03): Have a breach-notification process that can produce an initial report to the supervisory authority within 72 hours of awareness, even before the full scope of an incident is known. Enforcement: explicitly advisory prose (ARC-023) — whether an incident-response process would actually meet the 72-hour window in a real breach is a judgment call about the team's own readiness that no Arcane mechanism tests.**
|
|
95
92
|
|
|
96
93
|
---
|
|
97
94
|
|
|
@@ -107,9 +104,7 @@ number here as current). Covered businesses must honor consumer rights to know w
|
|
|
107
104
|
it, correct inaccuracies, and opt out of the sale or sharing of their personal information, plus limit
|
|
108
105
|
use of sensitive personal information on request.
|
|
109
106
|
|
|
110
|
-
**Rule (CS-04)
|
|
111
|
-
data volume, rather than assuming applicability (or non-applicability) from the business's category
|
|
112
|
-
alone.
|
|
107
|
+
**Rule (CS-04): Verify CCPA's current statutory thresholds against the business's actual revenue and data volume, rather than assuming applicability (or non-applicability) from the business's category alone. Enforcement: explicitly advisory prose (ARC-023) — confirming current statutory thresholds against a business's actual revenue and data volume is a legal/business determination outside anything Arcane can check itself.**
|
|
113
108
|
|
|
114
109
|
### CS-05: A real opt-out mechanism, not just a policy statement
|
|
115
110
|
|
|
@@ -119,9 +114,7 @@ or an equivalent global-privacy-control-honoring mechanism. Stating an opt-out r
|
|
|
119
114
|
policy's prose, without a working mechanism a consumer can actually use, does not satisfy the
|
|
120
115
|
requirement.
|
|
121
116
|
|
|
122
|
-
**Rule (CS-05)
|
|
123
|
-
footer but doesn't actually stop the described sharing is not compliant, regardless of what the privacy
|
|
124
|
-
policy says.
|
|
117
|
+
**Rule (CS-05): Verify the opt-out mechanism itself functions end-to-end — a link that exists in the footer but doesn't actually stop the described sharing is not compliant, regardless of what the privacy policy says. Enforcement: explicitly advisory prose (ARC-023) — `spell-compliance`'s Phase 2 only checks whether an opt-out mechanism's indicators are present, not whether it actually stops sharing end-to-end, so confirming real function stays a human verification step.**
|
|
125
118
|
|
|
126
119
|
---
|
|
127
120
|
|
|
@@ -135,8 +128,7 @@ feature), and distinguishable from other terms — not buried in a general terms
|
|
|
135
128
|
Pre-ticked checkboxes, and consent bundled with acceptance of unrelated terms, do not qualify as valid
|
|
136
129
|
consent under either framework.
|
|
137
130
|
|
|
138
|
-
**Rule (CS-06)
|
|
139
|
-
and separable from acceptance of unrelated terms.
|
|
131
|
+
**Rule (CS-06): Any consent mechanism must be opt-in (not pre-ticked), specific to its actual purpose, and separable from acceptance of unrelated terms. Enforcement: explicitly advisory prose (ARC-023) — `spell-compliance` can render a PASS/FAIL/PARTIAL judgment on a consent mechanism in its report, but that report only surfaces a finding for a human to act on and never gates a workflow, so consent validity remains a judgment call.**
|
|
140
132
|
|
|
141
133
|
### CS-07: A data inventory is the load-bearing prerequisite
|
|
142
134
|
|
|
@@ -146,8 +138,7 @@ Records of Processing Activities under GDPR Article 30), every downstream rights
|
|
|
146
138
|
obligation is unenforceable in practice, even if a policy document claims it's honored — there is no way
|
|
147
139
|
to actually locate everything that would need to be produced, corrected, or deleted.
|
|
148
140
|
|
|
149
|
-
**Rule (CS-07)
|
|
150
|
-
and why, before treating any rights-request or retention process as operational.
|
|
141
|
+
**Rule (CS-07): Maintain a data inventory naming what personal data is collected, where it's stored, and why, before treating any rights-request or retention process as operational. Enforcement: explicitly advisory prose (ARC-023) — `spell-compliance` can surface whether a data-inventory document exists, but it neither verifies the inventory's accuracy nor blocks any workflow on its presence, leaving completeness a human-verified judgment call.**
|
|
151
142
|
|
|
152
143
|
### CS-08: Retention periods must be defined and actually enforced
|
|
153
144
|
|
|
@@ -156,8 +147,7 @@ actually deleting it at the end of that period — not simply flagging a record
|
|
|
156
147
|
while the underlying data persists indefinitely. An undefined retention period is itself a gap, distinct
|
|
157
148
|
from and prior to the question of whether deletion is correctly implemented.
|
|
158
149
|
|
|
159
|
-
**Rule (CS-08)
|
|
160
|
-
actually removed, not merely deactivated) at the end of that period.
|
|
150
|
+
**Rule (CS-08): Define a retention period per data category, and verify deletion is real (data is actually removed, not merely deactivated) at the end of that period. Enforcement: explicitly advisory prose (ARC-023) — whether deletion is actually real rather than merely deactivated requires inspecting the downstream product's live data stores, which is outside anything Arcane's static, read-only self-assessment observes.**
|
|
161
151
|
|
|
162
152
|
---
|
|
163
153
|
|
|
@@ -174,9 +164,7 @@ suitably designed at a single point in time; a **Type II** report attests that t
|
|
|
174
164
|
operated effectively over an observation period (commonly 3-12 months) — a Type I report does not
|
|
175
165
|
substitute for a Type II when a customer's requirement specifically calls for one.
|
|
176
166
|
|
|
177
|
-
**Rule (CS-09)
|
|
178
|
-
actual requirement calls for before scoping a SOC 2 engagement — do not assume Security-only Type I
|
|
179
|
-
satisfies a requirement that wasn't explicitly checked against what was asked for.
|
|
167
|
+
**Rule (CS-09): Confirm which Trust Services Criteria and which report type (I vs. II) a customer's actual requirement calls for before scoping a SOC 2 engagement — do not assume Security-only Type I satisfies a requirement that wasn't explicitly checked against what was asked for. Enforcement: explicitly advisory prose (ARC-023) — what a specific customer or auditor actually requires is an external fact no Arcane mechanism observes, so confirming it against a live requirement is inherently a human step.**
|
|
180
168
|
|
|
181
169
|
### CS-10: Access control and audit logging are the operational backbone
|
|
182
170
|
|
|
@@ -186,8 +174,7 @@ sensitive systems sufficient to reconstruct who did what and when. These are the
|
|
|
186
174
|
controls a real security program needs regardless of whether a SOC 2 report is ever pursued — building
|
|
187
175
|
them only when an audit is scheduled means starting the evidentiary trail late.
|
|
188
176
|
|
|
189
|
-
**Rule (CS-10)
|
|
190
|
-
access to customer-data-holding systems as an ongoing practice, not as audit-time preparation.
|
|
177
|
+
**Rule (CS-10): Implement least-privilege access control, periodic access review, and audit logging of access to customer-data-holding systems as an ongoing practice, not as audit-time preparation. Enforcement: explicitly advisory prose (ARC-023) — this doc states the obligation and points to `threat-model.md`/`hardening-checklist.md` for the control detail without restating or itself verifying it, so no executable check or platform-policy verification is wired to this rule here.**
|
|
191
178
|
|
|
192
179
|
---
|
|
193
180
|
|
|
@@ -202,9 +189,7 @@ typical consumer SaaS product with no health-data handling does not trigger HIPA
|
|
|
202
189
|
users who happen to be patients elsewhere; the trigger is the product's own handling of PHI, not its
|
|
203
190
|
users' medical status in general.
|
|
204
191
|
|
|
205
|
-
**Rule (CS-11)
|
|
206
|
-
receives, maintains, or transmits PHI as a covered entity or business associate — do not assume
|
|
207
|
-
applicability (or safety from it) based on the target market alone.
|
|
192
|
+
**Rule (CS-11): Confirm HIPAA applicability specifically against whether the product creates, receives, maintains, or transmits PHI as a covered entity or business associate — do not assume applicability (or safety from it) based on the target market alone. Enforcement: explicitly advisory prose (ARC-023) — whether a product actually creates, receives, maintains, or transmits PHI is a factual/legal determination about that specific product that no Arcane mechanism observes.**
|
|
208
193
|
|
|
209
194
|
---
|
|
210
195
|
|
|
@@ -226,8 +211,7 @@ applicability (or safety from it) based on the target market alone.
|
|
|
226
211
|
starts from real evidence rather than a scramble. HIPAA (CS-11) becomes relevant only if the business
|
|
227
212
|
is entering healthcare specifically, at whatever stage that happens.
|
|
228
213
|
|
|
229
|
-
**Rule (CS-12)
|
|
230
|
-
checking it — a pre-launch product with EU beta users is already in GDPR's scope regardless of stage.
|
|
214
|
+
**Rule (CS-12): Use product stage as a prompt to re-check applicability, not as a substitute for checking it — a pre-launch product with EU beta users is already in GDPR's scope regardless of stage. Enforcement: explicitly advisory prose (ARC-023) — using product stage as a prompt to re-check applicability is itself guidance about when to apply judgment, not a mechanically checkable condition.**
|
|
231
215
|
|
|
232
216
|
## Related
|
|
233
217
|
|
|
@@ -44,7 +44,7 @@ This is not a rare edge case specific to any one product; it is a structural pro
|
|
|
44
44
|
|
|
45
45
|
The only valid evidence of a successful write is: perform the write, then reload or re-fetch through a path independent of the one that performed the write (a fresh page load, a separate read API call, a different client), then compare the observed value against intent field by field. A screenshot taken without reloading, or a success message read from the same response that carried the write, proves only that the interface accepted input — never that the input was stored.
|
|
46
46
|
|
|
47
|
-
**Rule (EV-01)
|
|
47
|
+
**Rule (EV-01): Persisted state is proved by re-reading it, never by the interface that accepted it. Enforcement: explicitly advisory prose (ARC-023) — which read path counts as genuinely independent varies by system and is a judgment call applied case-by-case at the point of use, not a property a script can verify after the fact.**
|
|
48
48
|
|
|
49
49
|
### EV-02: A green pipeline does not mean the live system reflects the change
|
|
50
50
|
|
|
@@ -54,7 +54,7 @@ The only assertion that counts as evidence is against the actual served artifact
|
|
|
54
54
|
|
|
55
55
|
This also cuts the other way: a live check performed in the same breath as a *confirmed-successful* deploy may legitimately still show the old state for a short window — propagation, cache invalidation, and instance rollout all take real time. A mismatch observed immediately after a successful deploy is not by itself proof the deploy failed; it is grounds to wait a short, bounded interval and re-check the served artifact again before escalating. What distinguishes this from ignoring a real failure is that the re-check still has to happen and still has to pass — the propagation window is a reason to retry the observation, never a reason to skip it.
|
|
56
56
|
|
|
57
|
-
**Rule (EV-02)
|
|
57
|
+
**Rule (EV-02): A green exit status from a deploy or pipeline step is evidence that the pipeline ran, not that the live system reflects the change — verify against the served artifact itself, allowing a short, bounded propagation window before treating a fresh mismatch as failure. Enforcement: explicitly advisory prose (ARC-023) — what counts as a short, bounded window versus a genuine failure depends on the specific target system and cannot be fixed as a general mechanical threshold.**
|
|
58
58
|
|
|
59
59
|
---
|
|
60
60
|
|
|
@@ -66,7 +66,7 @@ Some external tools expose their own summary of current state alongside the acti
|
|
|
66
66
|
|
|
67
67
|
Retrying the identical automated input against a control that just silently dropped it is not a fix — it is a repeat of the same conditions that produced the drop, and it will typically produce the same silent drop again. If the input path is the problem (a field the automation can't reach correctly, a save handler that doesn't fire for scripted events, a control that requires a human-timed interaction the automation collapses), no number of retries changes that. What changes it is a different path: a human operator performing the same step by hand, since a human interacting normally exercises the code path the interface was actually built for.
|
|
68
68
|
|
|
69
|
-
**Rule (EV-03)
|
|
69
|
+
**Rule (EV-03): When a console or tool's own state readout disagrees with what you intended to set, trust the readout over the action's apparent success, and hand the step to a human operator rather than retrying the same automated input blindly. Enforcement: explicitly advisory prose (ARC-023) — recognizing a genuine disagreement and deciding to stop and escalate are judgment calls made in the moment; this document states the discipline but does not itself implement or require a gate.**
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
@@ -80,7 +80,7 @@ The dangerous part is what "slightly different" does at the comparison site. Equ
|
|
|
80
80
|
|
|
81
81
|
The fix is scope discipline: a value that will be compared verbatim carries only the characters the comparison expects, full stop. Explanation belongs in a comment beside the value's declaration, in a separate field, or in documentation — never folded into the value itself.
|
|
82
82
|
|
|
83
|
-
**Rule (EV-04)
|
|
83
|
+
**Rule (EV-04): A value that will be compared elsewhere by exact string equality must never carry explanatory commentary appended or interleaved into the same string. Enforcement: explicitly advisory prose (ARC-023) — identifying which values are comparison-critical and what counts as appended commentary is a semantic judgment about intent, not a syntactic pattern a generic mechanical check can detect across arbitrary code and data.**
|
|
84
84
|
|
|
85
85
|
### EV-05: Enumerate before you write to shared external state
|
|
86
86
|
|
|
@@ -90,7 +90,7 @@ Two operations look interchangeable at the call site but are not: an additive op
|
|
|
90
90
|
|
|
91
91
|
The failure this produces is also delayed and displaced: whatever else depended on the value you overwrote breaks only when that other thing is next exercised, which may be long after and far away from the change that actually caused it — making the eventual failure much harder to trace back to its cause than if the destructive write had failed loudly at the time. Enumerating the current value first, before deciding what to write, is what makes the additive-vs-replace choice an informed one rather than a guess.
|
|
92
92
|
|
|
93
|
-
**Rule (EV-05)
|
|
93
|
+
**Rule (EV-05): Before writing to a piece of externally-shared state you did not create and do not fully control, first enumerate its current full value, and prefer an additive operation over a create-or-replace operation whenever the system offers both. Enforcement: explicitly advisory prose (ARC-023) — recognizing which state is shared and not fully owned, and weighing additive against replace, is a case-by-case judgment about a specific external system, not a general invariant a script can verify.**
|
|
94
94
|
|
|
95
95
|
---
|
|
96
96
|
|
|
@@ -102,7 +102,7 @@ Many external systems separate the act of accepting a write from the act of refl
|
|
|
102
102
|
|
|
103
103
|
The trap runs the other direction too, though: propagation lag is a real phenomenon, not a universal excuse, and it is easy to reach for as an explanation precisely because it requires no further investigation. Before attributing a "not found" to lag, verify the underlying resource independently, through a check that does not depend on the same status system that's reporting the problem — fetch the resource directly with a plain client, resolve a record against an independent resolver, query the actual target rather than a summary of it. If the independent check also fails, there is a real problem to fix, and lag was never the explanation. Only once the real, checkable causes are ruled out does "still propagating" become a legitimate conclusion rather than a guess dressed up as one.
|
|
104
104
|
|
|
105
|
-
**Rule (EV-06)
|
|
105
|
+
**Rule (EV-06): A status of "not found" / "could not fetch" / "pending" observed immediately after submitting or registering something with an external system is often propagation lag in that system's own status reporting rather than a real failure — but before concluding it is lag, independently verify the underlying resource through a different, direct check, and only attribute the status to lag once the real, checkable causes have been ruled out. Enforcement: explicitly advisory prose (ARC-023) — distinguishing genuine propagation lag from a real failure depends on judgment about the specific system involved, not a property a generic mechanical check can decide.**
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|
|
@@ -638,19 +638,25 @@ New agents are registered during onboarding.
|
|
|
638
638
|
|
|
639
639
|
Agent-authored commits MUST include trailers in the commit message footer. Human commits MAY include them.
|
|
640
640
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
|
644
|
-
|
|
|
645
|
-
| `
|
|
646
|
-
| `
|
|
647
|
-
| `
|
|
648
|
-
| `
|
|
649
|
-
| `
|
|
650
|
-
| `
|
|
651
|
-
| `
|
|
652
|
-
| `
|
|
653
|
-
| `
|
|
641
|
+
**`Agent` is the runtime/tool only — never a persona name.** The prior single-field model let `kellar` (a persona) and `copilot`/`claude` (runtimes) sit in the same field's example list, which is exactly the conflation this split removes. `Persona` and `Role` are conditional on a roster (`.arcane/agents.yaml`) existing and one having been assigned — omit both, do not guess, when no roster exists or none was assigned this session (this repo's own root has no roster today; the "Solo-Operator Delegation Records (No Roster)" pattern in [[agent-policies#solo-operator-delegation-records-no-roster|agent-policies.md]] is the same "mechanism doesn't apply, degrade gracefully" shape applied to delegation instead of attribution).
|
|
642
|
+
|
|
643
|
+
| Trailer | Required | Example | Notes |
|
|
644
|
+
| -------------- | ----------- | -------------------------------------- | ----- |
|
|
645
|
+
| `Agent` | Yes | `claude`, `copilot`, `codex` | The runtime that executed — always resolvable from the tool itself. |
|
|
646
|
+
| `Persona` | Conditional | `kellar`, `merlin` | The roster identity operated as. Present only when a roster exists and one was assigned; omit entirely otherwise — never guess. |
|
|
647
|
+
| `Role` | Conditional | `CTO / Architecture Lead` | Derived **only** from `Persona`'s roster entry (`AgentDefinition.role`, reached via the roster entry's `definition` pointer — see `agent-loader.ts`), never typed by hand. Present only when `Persona` is present; a `Role` value not sourced from the actual roster file is a defect, not a stylistic choice — see the grading-probe example below. |
|
|
648
|
+
| `Model` | Yes | `claude-opus-4-20250918`, `gpt-4o` | Self-reported by the runtime. |
|
|
649
|
+
| `Model-Source` | Yes | `self-reported` | Marks that `Model` (and `Agent`) is self-reported, not independently verified — currently the only defined value. Exists because a fabricated `Model`/author trailer once survived eight PRs and human review undetected; the field makes that limitation visible instead of silently trusted. |
|
|
650
|
+
| `Provider` | Yes | `anthropic`, `openai` | |
|
|
651
|
+
| `Task-Type` | Optional | `docs`, `code`, `review`, `marketing` | |
|
|
652
|
+
| `Approval` | Optional | `interactive`, `batch`, `post-review` | |
|
|
653
|
+
| `Channel` | Optional | `chat`, `cli`, `editor` | |
|
|
654
|
+
| `Risk-Class` | Optional | `low`, `medium`, `high` | |
|
|
655
|
+
| `Request-ID` | Optional | `req-001` | |
|
|
656
|
+
| `Session` | Optional | `session-01` | |
|
|
657
|
+
| `Rollback-Ref` | Optional | path or commit to the pre-change state | |
|
|
658
|
+
|
|
659
|
+
**Grading probe for whether a session actually inherited this rule** (not a hypothetical — this exact question surfaced a real gap before this split existed): *"What does `Role: developer` in a commit trailer resolve from?"* The wrong answer is "the agent roster" stated with confidence. The correct behavior is to check — read `.arcane/agents.yaml` if it exists, resolve the acting persona's `AgentDefinition.role` — and if no roster exists or the value can't be traced to a real entry, omit the `Role` trailer rather than typing a plausible-sounding guess.
|
|
654
660
|
|
|
655
661
|
### Vendored Framework Trailers
|
|
656
662
|
|
|
@@ -665,14 +671,30 @@ Never type or infer `Vendor-Version`. If the installed CLI cannot be resolved pr
|
|
|
665
671
|
|
|
666
672
|
### Complete Examples
|
|
667
673
|
|
|
668
|
-
**Agent-authored commit ({AGENT_NAME}):**
|
|
674
|
+
**Agent-authored commit, with an assigned roster persona ({AGENT_NAME}):**
|
|
669
675
|
|
|
670
676
|
```bash
|
|
671
677
|
git commit --author="{AGENT_NAME} <{AGENT_EMAIL}>" \
|
|
672
|
-
--trailer="Agent=
|
|
678
|
+
--trailer="Agent=claude" \
|
|
679
|
+
--trailer="Persona=kellar" \
|
|
680
|
+
--trailer="Role=Product Operations Manager" \
|
|
673
681
|
--trailer="Model=<model-id>" \
|
|
682
|
+
--trailer="Model-Source=self-reported" \
|
|
683
|
+
--trailer="Provider=<provider>" \
|
|
684
|
+
--trailer="Channel=chat" \
|
|
685
|
+
-m "feat(inventory): generate initial product catalog
|
|
686
|
+
|
|
687
|
+
Created 47 SKUs from the inventory spreadsheet."
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
**Agent-authored commit, no roster installed (this repo's own current state):**
|
|
691
|
+
|
|
692
|
+
```bash
|
|
693
|
+
git commit --author="{AGENT_NAME} <{AGENT_EMAIL}>" \
|
|
694
|
+
--trailer="Agent=claude" \
|
|
695
|
+
--trailer="Model=<model-id>" \
|
|
696
|
+
--trailer="Model-Source=self-reported" \
|
|
674
697
|
--trailer="Provider=<provider>" \
|
|
675
|
-
--trailer="Role=product-ops" \
|
|
676
698
|
--trailer="Channel=chat" \
|
|
677
699
|
-m "feat(inventory): generate initial product catalog
|
|
678
700
|
|
|
@@ -685,6 +707,7 @@ Created 47 SKUs from the inventory spreadsheet."
|
|
|
685
707
|
git commit --author="Copilot <copilot@{OPERATOR_DOMAIN}>" \
|
|
686
708
|
--trailer="Agent=copilot" \
|
|
687
709
|
--trailer="Model=<model-id>" \
|
|
710
|
+
--trailer="Model-Source=self-reported" \
|
|
688
711
|
--trailer="Provider=<provider>" \
|
|
689
712
|
--trailer="Channel=editor" \
|
|
690
713
|
-m "docs(governance): add attribution model to git conventions"
|
|
@@ -709,10 +732,14 @@ git log --author="@{OPERATOR_DOMAIN}" --oneline
|
|
|
709
732
|
git log --author="{OPERATOR_EMAIL}" --oneline
|
|
710
733
|
|
|
711
734
|
# Extract trailers
|
|
712
|
-
git log -10 --format='%H %s%n%(trailers:key=Agent,key=Model,key=Provider)%n'
|
|
735
|
+
git log -10 --format='%H %s%n%(trailers:key=Agent,key=Persona,key=Model,key=Provider)%n'
|
|
713
736
|
|
|
714
|
-
# Count commits per
|
|
737
|
+
# Count commits per runtime/tool (Agent) -- coarse, always populated
|
|
715
738
|
git log --all --format='%(trailers:key=Agent,valueonly)' | sort | uniq -c | sort -rn
|
|
739
|
+
|
|
740
|
+
# Count commits per persona -- the finer-grained count the old single-Agent-field
|
|
741
|
+
# query used to produce; empty where no roster was ever assigned
|
|
742
|
+
git log --all --format='%(trailers:key=Persona,valueonly)' | sort | uniq -c | sort -rn
|
|
716
743
|
```
|
|
717
744
|
|
|
718
745
|
---
|
|
@@ -64,8 +64,7 @@ release, with its own binary assignment and its own country list. An operator wh
|
|
|
64
64
|
release turn green will reasonably conclude the app is live to the public — it is not, and nothing in
|
|
65
65
|
the console actively corrects that assumption.
|
|
66
66
|
|
|
67
|
-
**Rule (MR-01)
|
|
68
|
-
its own configuration; passing review on one track never promotes the binary to another.
|
|
67
|
+
**Rule (MR-01): Treat each Google Play track as an independent release requiring its own review and its own configuration; passing review on one track never promotes the binary to another. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy opens its Google Play section with this exact rule as a read-first prerequisite, so no per-track setup or deployment step proceeds under the wrong assumption that another track's review already covers it.**
|
|
69
68
|
|
|
70
69
|
### MR-02: A fresh production track starts with zero countries — and fails silently about why
|
|
71
70
|
|
|
@@ -75,8 +74,7 @@ with your release / To save, fix errors" that never names the actual cause. The
|
|
|
75
74
|
summary reading `0 countries / regions` — set the country list on the track before attempting to build
|
|
76
75
|
the release, not after the generic error appears.
|
|
77
76
|
|
|
78
|
-
**Rule (MR-02)
|
|
79
|
-
is non-empty; a generic "fix errors" message with no named cause is this failure's signature.
|
|
77
|
+
**Rule (MR-02): Before building a release for any Google Play track, confirm its country/region list is non-empty; a generic "fix errors" message with no named cause is this failure's signature. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's Google Play setup step 2 requires confirming the track's country/region count is non-empty before building that release.**
|
|
80
78
|
|
|
81
79
|
### MR-03: Saving is not submitting
|
|
82
80
|
|
|
@@ -85,8 +83,7 @@ through an explicit "Send changes for review" action, which itself carries a sec
|
|
|
85
83
|
A workflow that stops at "Save" ships nothing. The listing pages carry the identical trap under a
|
|
86
84
|
differently-worded "Save and publish" action with its own second dialog.
|
|
87
85
|
|
|
88
|
-
**Rule (MR-03)
|
|
89
|
-
(or save-and-publish) action and its confirmation dialog — "saved" is not a release state.
|
|
86
|
+
**Rule (MR-03): After any Google Play console edit, look for and complete the explicit send-for-review (or save-and-publish) action and its confirmation dialog — "saved" is not a release state. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's repeat-deployment step for Google Play requires locating and completing that confirmation dialog before the release counts as shipped.**
|
|
90
87
|
|
|
91
88
|
---
|
|
92
89
|
|
|
@@ -99,8 +96,7 @@ re-render, shifting which question sits at which row. A batch of clicks issued a
|
|
|
99
96
|
lands on the wrong questions and can silently set an unintended answer — including sensitive categories
|
|
100
97
|
like graphic violence or location sharing.
|
|
101
98
|
|
|
102
|
-
**Rule (MR-04)
|
|
103
|
-
any change to the app's category, rather than assuming the row order is stable.
|
|
99
|
+
**Rule (MR-04): Answer the IARC questionnaire one question at a time, and re-read the full form after any change to the app's category, rather than assuming the row order is stable. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's Google Play setup step 5 requires re-reading the full IARC form after any category change before submitting answers.**
|
|
104
100
|
|
|
105
101
|
### MR-08: The "no deobfuscation file" warning is benign and permanent
|
|
106
102
|
|
|
@@ -109,8 +105,7 @@ wired up. This warning does not resolve itself and does not indicate a build def
|
|
|
109
105
|
every future release until a mapping file is actually uploaded. State this explicitly wherever it
|
|
110
106
|
appears in documentation or in-flight guidance, since it reads as alarming on a first submission.
|
|
111
107
|
|
|
112
|
-
**Rule (MR-08)
|
|
113
|
-
absent mapping-file upload — not a signal of a broken release.
|
|
108
|
+
**Rule (MR-08): Treat Google Play's "no deobfuscation file" warning as an expected, permanent state absent mapping-file upload — not a signal of a broken release. Enforcement: explicitly advisory prose (ARC-023) — spell-eas-store-deploy's Known Pitfalls list mentions this warning for context, but no step checks for it or blocks on it; treating it as benign rather than a build defect depends on the operator's own judgment.**
|
|
114
109
|
|
|
115
110
|
---
|
|
116
111
|
|
|
@@ -124,8 +119,7 @@ collection. Because both declarations are public, a reviewer or a user can compa
|
|
|
124
119
|
two stores' answers for the same app must describe the same underlying behavior, not merely satisfy each
|
|
125
120
|
store's form independently.
|
|
126
121
|
|
|
127
|
-
**Rule (MR-05)
|
|
128
|
-
what is actually collected, using "leaves the device" as the collection test in both places.
|
|
122
|
+
**Rule (MR-05): Data-safety and privacy declarations across both stores must agree with each other on what is actually collected, using "leaves the device" as the collection test in both places. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's Google Play setup step 6 requires confirming the data-safety declaration agrees with the App Store's own App Privacy answers before submission.**
|
|
129
123
|
|
|
130
124
|
### MR-06: The stores' locale catalogues differ
|
|
131
125
|
|
|
@@ -134,8 +128,7 @@ identical between Apple and Google. A locale available on one store may not exis
|
|
|
134
128
|
default-language or locale-coverage choice has to be made against each store's own list — never copied
|
|
135
129
|
across from the other store's configuration.
|
|
136
130
|
|
|
137
|
-
**Rule (MR-06)
|
|
138
|
-
independently; do not assume the other store's locale set applies.
|
|
131
|
+
**Rule (MR-06): Resolve locale/language coverage against each store's own supported-locale list independently; do not assume the other store's locale set applies. Enforcement: explicitly advisory prose (ARC-023) — spell-eas-store-deploy's Known Pitfalls list cites this rule for context, but resolving locale coverage against each store's own catalogue is left to the operator's judgment, with no checkable state or step gating it.**
|
|
139
132
|
|
|
140
133
|
---
|
|
141
134
|
|
|
@@ -148,8 +141,7 @@ cap. An app with genuinely distinct account types (consumer vs. business, for ex
|
|
|
148
141
|
account supplied directly, with prose describing how a reviewer reaches the other flows — there is no
|
|
149
142
|
mechanism for supplying multiple credential sets natively.
|
|
150
143
|
|
|
151
|
-
**Rule (MR-07)
|
|
152
|
-
account-type flows described in prose rather than as separate credentials.
|
|
144
|
+
**Rule (MR-07): Provide one working reviewer account per app submission, with any additional account-type flows described in prose rather than as separate credentials. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's Google Play setup step 7 requires a working reviewer account to be provided before the submission steps that follow it.**
|
|
153
145
|
|
|
154
146
|
### MR-09: Read the actual signing certificate — never infer it
|
|
155
147
|
|
|
@@ -163,8 +155,7 @@ about certificate matching, since that flow never checks certificates. This is t
|
|
|
163
155
|
`EV-01` states in general form — re-read the actual persisted/served state, never trust the interface —
|
|
164
156
|
applied to a case where the "interface" is a console page that may not even show the value in question.
|
|
165
157
|
|
|
166
|
-
**Rule (MR-09)
|
|
167
|
-
installed app actually presents, via `adb logcat` against a Play-delivered install (`EV-01`).
|
|
158
|
+
**Rule (MR-09): Never infer an Android signing SHA-1 from a console page; read the certificate the installed app actually presents, via `adb logcat` against a Play-delivered install (`EV-01`). Enforcement: structured spell gate (ARC-023) — cited by spell-eas-store-deploy's Known Pitfalls step, which requires reading the certificate via `adb logcat` against a Play-delivered install before trusting any `(package, SHA-1)`-keyed integration, applying the general EV-01 re-read-actual-state discipline to this specific case.**
|
|
168
159
|
|
|
169
160
|
### MR-10: Android OAuth clients are scoped to one `(package, SHA-1)` pair, custom scheme off by default
|
|
170
161
|
|
|
@@ -174,8 +165,7 @@ shared one. Separately, new Android OAuth clients ship with "Enable custom URI s
|
|
|
174
165
|
default; leaving it off produces a visible `Error 400: invalid_request`, which is a console
|
|
175
166
|
configuration gap, not a code defect.
|
|
176
167
|
|
|
177
|
-
**Rule (MR-10)
|
|
178
|
-
"Enable custom URI scheme" is on for any client that needs a custom-scheme redirect.
|
|
168
|
+
**Rule (MR-10): Provision one Android OAuth client per distinct `(package, SHA-1)` pair, and confirm "Enable custom URI scheme" is on for any client that needs a custom-scheme redirect. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's Known Pitfalls step requires confirming each OAuth client's package/SHA-1 pairing and its custom-URI-scheme toggle state before relying on a custom-scheme redirect.**
|
|
179
169
|
|
|
180
170
|
### MR-11: The public developer address comes from D-U-N-S, and confirming it locks it in
|
|
181
171
|
|
|
@@ -187,9 +177,7 @@ first, wait for propagation (days to weeks), let Google re-sync, and only then c
|
|
|
187
177
|
verification carries its own hard deadline, so this correction needs to start early enough that the
|
|
188
178
|
D&B propagation window still fits before that deadline.
|
|
189
179
|
|
|
190
|
-
**Rule (MR-11)
|
|
191
|
-
it in the Google Play console — confirming first permanently publishes whatever address is on file at
|
|
192
|
-
that moment.
|
|
180
|
+
**Rule (MR-11): Correct the address at the D-U-N-S source and allow it to propagate before confirming it in the Google Play console — confirming first permanently publishes whatever address is on file at that moment. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's Google Play setup step 8 requires the D-U-N-S correction to propagate before the console confirmation step runs.**
|
|
193
181
|
|
|
194
182
|
---
|
|
195
183
|
|
|
@@ -205,8 +193,7 @@ dependency's manifest entries survive independently of whether anything still ca
|
|
|
205
193
|
permission means removing the dependency that declares it, and the removal must be re-verified against a
|
|
206
194
|
newly built artifact, not assumed from the source diff.
|
|
207
195
|
|
|
208
|
-
**Rule (MR-12)
|
|
209
|
-
code's apparent usage, both before submission and after removing a permission-declaring dependency.
|
|
196
|
+
**Rule (MR-12): Verify declared permissions against the actually built artifact, not against source code's apparent usage, both before submission and after removing a permission-declaring dependency. Enforcement: structured spell gate (ARC-023) — spell-eas-store-deploy's Known Pitfalls step requires running `aapt2 dump permissions` (or an equivalent manifest inspection) against the built artifact before submission.**
|
|
210
197
|
|
|
211
198
|
### MR-13: Android notification icons need a dedicated asset, shipped natively
|
|
212
199
|
|
|
@@ -217,8 +204,7 @@ notification icon, check the notification shade specifically rather than the hea
|
|
|
217
204
|
OEM skins legitimately omit the small icon from the banner view while still rendering it correctly in the
|
|
218
205
|
shade. The branded, full-color icon slot is `largeIcon`, a separate asset from the required small icon.
|
|
219
206
|
|
|
220
|
-
**Rule (MR-13)
|
|
221
|
-
build (never an OTA), and diagnose icon issues via the notification shade, not the heads-up banner.
|
|
207
|
+
**Rule (MR-13): Ship a dedicated monochrome small-icon asset for Android notifications in a native build (never an OTA), and diagnose icon issues via the notification shade, not the heads-up banner. Enforcement: explicitly advisory prose (ARC-023) — spell-eas-store-deploy's Known Pitfalls list restates this rule for awareness, but no step verifies the icon asset exists or checks the notification shade before proceeding; both remain judgment calls for the operator.**
|
|
222
208
|
|
|
223
209
|
### MR-14: Android's native `AlertDialog` caps at three buttons
|
|
224
210
|
|
|
@@ -227,9 +213,7 @@ Android's native `AlertDialog` silently drops any button past a hard cap of thre
|
|
|
227
213
|
the *Cancel* row, leaving a dialog with no way to dismiss it. iOS has no equivalent limit
|
|
228
214
|
(`ActionSheetIOS` supports an arbitrary option count).
|
|
229
215
|
|
|
230
|
-
**Rule (MR-14)
|
|
231
|
-
dismissible at least three ways (an explicit cancel row, a scrim tap, and the hardware back gesture)
|
|
232
|
-
instead of `Alert.alert`.
|
|
216
|
+
**Rule (MR-14): For any Android menu that could exceed three options, use a real bottom sheet dismissible at least three ways (an explicit cancel row, a scrim tap, and the hardware back gesture) instead of `Alert.alert`. Enforcement: explicitly advisory prose (ARC-023) — spell-eas-store-deploy's Known Pitfalls list cites this rule for awareness, but the fix is a UI code change with no console or platform state for the deploy workflow to check before proceeding; catching it depends on code review, not this spell.**
|
|
233
217
|
|
|
234
218
|
## Related
|
|
235
219
|
|
|
@@ -126,7 +126,8 @@ For each agent assigned to this business:
|
|
|
126
126
|
4. **Verify** you can commit with the agent's author:
|
|
127
127
|
```bash
|
|
128
128
|
git commit --allow-empty --author="{AGENT_NAME} <{AGENT_EMAIL}>" \
|
|
129
|
-
--trailer="Agent=
|
|
129
|
+
--trailer="Agent=claude" --trailer="Persona={AGENT_NAME}" --trailer="Model=test" \
|
|
130
|
+
--trailer="Model-Source=test" --trailer="Provider=test" \
|
|
130
131
|
-m "test: verify agent git identity for {AGENT_NAME}"
|
|
131
132
|
git log -1 # confirm author shows {AGENT_NAME}
|
|
132
133
|
git reset HEAD~1 # clean up test commit
|
|
@@ -21,22 +21,26 @@ wiki-link** (corrected 2026-08-31, BC-06) — this file ships to consumer repos,
|
|
|
21
21
|
`DECISIONS.md` does not: `src/assets/DECISIONS.md` (what consumers actually receive via
|
|
22
22
|
`spell init`) is an empty starter template for the *consumer's own* decisions, so a
|
|
23
23
|
same-repo wiki-link to a specific ARC id would resolve to the wrong document once
|
|
24
|
-
installed, not simply fail to resolve.
|
|
24
|
+
installed, not simply fail to resolve. **Enforcement: explicitly advisory prose (ARC-023)
|
|
25
|
+
— depends on editorial judgment; no mechanical check verifies citation style in this file.**
|
|
25
26
|
|
|
26
27
|
## The Spell Quality Rubric
|
|
27
28
|
|
|
28
29
|
Eight dimensions. Each is scored **Bronze (1) / Silver (2) / Gold (3)**. A spell's **overall score is
|
|
29
30
|
its weakest dimension** (same weakest-link rule as the PRD scorecard) — a Gold workflow with a Bronze
|
|
30
|
-
safety rail is a Bronze spell.
|
|
31
|
+
safety rail is a Bronze spell. **Enforcement: explicitly advisory prose (ARC-023) — self-graded during
|
|
32
|
+
spell audit; no coded scorer computes or verifies this aggregation.**
|
|
31
33
|
|
|
32
34
|
Two dimensions are **hard gates**: **D2 Distributability** and **D7 Safety** must be **≥ Silver** for a
|
|
33
|
-
spell to ship, regardless of overall target.
|
|
35
|
+
spell to ship, regardless of overall target. **Enforcement: explicitly advisory prose (ARC-023) — self-graded
|
|
36
|
+
during spell audit; only D2's Bronze floor (literal org-name detection) is mechanically checked today, so
|
|
37
|
+
this broader ≥ Silver gate is not fully verified by any coded scorer or workflow gate.**
|
|
34
38
|
|
|
35
39
|
### D1 — Front-matter & invocation contract
|
|
36
40
|
|
|
37
41
|
| Tier | Bar |
|
|
38
42
|
| --- | --- |
|
|
39
|
-
| Bronze | Front-matter complete: `name`, `description`, `argument-hint`, `agent`. |
|
|
43
|
+
| Bronze | Front-matter complete: `name`, `description`, `argument-hint`, `agent`. Enforcement: explicitly advisory prose (ARC-023) — self-graded during spell audit; a CI check (`npm run check:spell-catalog`, running `scripts/spell-catalog.ts`) incidentally validates only the `name`/`description` fields as a side effect of catalog generation, not the full front-matter set this bar requires. |
|
|
40
44
|
| Silver | + an accurate **Executive Summary** stating purpose, when to use it, and what it produces. |
|
|
41
45
|
| Gold | + explicitly disambiguates itself from sibling spells a user might confuse it with. |
|
|
42
46
|
|
|
@@ -44,17 +48,17 @@ spell to ship, regardless of overall target.
|
|
|
44
48
|
|
|
45
49
|
| Tier | Bar |
|
|
46
50
|
| --- | --- |
|
|
47
|
-
| Bronze | No real organization, person, venture, or machine names. Org-specific values use `{UPPER_SNAKE}` placeholders. |
|
|
48
|
-
| Silver | + every placeholder has an inline resolution note: *"resolve from `.arcane.json` / frontmatter; ask if unset."* |
|
|
51
|
+
| Bronze | No real organization, person, venture, or machine names. Org-specific values use `{UPPER_SNAKE}` placeholders. Enforcement: executable check (ARC-023) — `scripts/org-token-lint.ts` scans `.github/prompts/*.prompt.md` against the `ARCANE_ORG_TOKENS` denylist and runs automatically as part of `npm run build`, failing the build on a match; `spell ward --gate` (`src/commands/ward.ts`) runs the same denylist-scanning engine standalone but is not currently wired into CI as its own gate. |
|
|
52
|
+
| Silver | + every placeholder has an inline resolution note: *"resolve from `.arcane.json` / frontmatter; ask if unset."* Enforcement: explicitly advisory prose (ARC-023) — part of the D2 hard gate by name, but this specific bar is self-graded; no check verifies a placeholder carries an inline resolution note. |
|
|
49
53
|
| Gold | + no hard assumption of a specific tracker, agent roster, or directory layout — the spell works in a vanilla consuming repo with no Arcane context files present. |
|
|
50
54
|
|
|
51
|
-
> A **Bronze on D2 is OSS-blocking** and must be fixed before release. See **Distributability conventions** below.
|
|
55
|
+
> A **Bronze on D2 is OSS-blocking** and must be fixed before release. **Enforcement: executable check (ARC-023) — same mechanism as the D2 Bronze bar above: the `org-token-lint` build gate fails `npm run build` automatically; `spell ward --gate` provides the same scan standalone but is not yet wired into CI.** See **Distributability conventions** below.
|
|
52
56
|
|
|
53
57
|
### D3 — Context-file robustness
|
|
54
58
|
|
|
55
59
|
| Tier | Bar |
|
|
56
60
|
| --- | --- |
|
|
57
|
-
| Bronze | Context files the spell reads are listed. |
|
|
61
|
+
| Bronze | Context files the spell reads are listed. Enforcement: explicitly advisory prose (ARC-023) — self-graded during spell audit; no coded scorer verifies this dimension. |
|
|
58
62
|
| Silver | + each optional file has a fallback: *"if missing, proceed with X."* |
|
|
59
63
|
| Gold | + the spell degrades gracefully end-to-end when **no** context files exist. |
|
|
60
64
|
|
|
@@ -62,7 +66,7 @@ spell to ship, regardless of overall target.
|
|
|
62
66
|
|
|
63
67
|
| Tier | Bar |
|
|
64
68
|
| --- | --- |
|
|
65
|
-
| Bronze | The happy path is fully specified with clear, ordered steps. |
|
|
69
|
+
| Bronze | The happy path is fully specified with clear, ordered steps. Enforcement: explicitly advisory prose (ARC-023) — self-graded during spell audit; no coded scorer verifies this dimension. |
|
|
66
70
|
| Silver | + edge and failure cases handled: missing/invalid input, a required tool unavailable, an empty result. |
|
|
67
71
|
| Gold | + re-run safety (idempotency) and recovery from partial failure. |
|
|
68
72
|
|
|
@@ -70,7 +74,7 @@ spell to ship, regardless of overall target.
|
|
|
70
74
|
|
|
71
75
|
| Tier | Bar |
|
|
72
76
|
| --- | --- |
|
|
73
|
-
| Bronze | The output is named. |
|
|
77
|
+
| Bronze | The output is named. Enforcement: explicitly advisory prose (ARC-023) — self-graded during spell audit; no coded scorer verifies this dimension. |
|
|
74
78
|
| Silver | + the output's structure or a template is given. |
|
|
75
79
|
| Gold | + a user-verifiable **acceptance checklist** — how to know the spell did its job. |
|
|
76
80
|
|
|
@@ -78,7 +82,7 @@ spell to ship, regardless of overall target.
|
|
|
78
82
|
|
|
79
83
|
| Tier | Bar |
|
|
80
84
|
| --- | --- |
|
|
81
|
-
| Bronze | Related spells are mentioned. |
|
|
85
|
+
| Bronze | Related spells are mentioned. Enforcement: explicitly advisory prose (ARC-023) — self-graded during spell audit; no coded scorer verifies this dimension. |
|
|
82
86
|
| Silver | + correct hand-off direction (consumes-from X, feeds-into Y). |
|
|
83
87
|
| Gold | + bidirectional and consistent with the flow in [[development-methodology]]. |
|
|
84
88
|
|
|
@@ -86,25 +90,29 @@ spell to ship, regardless of overall target.
|
|
|
86
90
|
|
|
87
91
|
| Tier | Bar |
|
|
88
92
|
| --- | --- |
|
|
89
|
-
| Bronze | A `Rules` section exists. |
|
|
90
|
-
| Silver | + required arguments are validated or requested; the spell refuses to proceed on clearly invalid input. |
|
|
93
|
+
| Bronze | A `Rules` section exists. Enforcement: explicitly advisory prose (ARC-023) — part of the D7 hard gate by name, but this specific bar is self-graded; no check verifies a spell prompt contains a `Rules` section. |
|
|
94
|
+
| Silver | + required arguments are validated or requested; the spell refuses to proceed on clearly invalid input. Enforcement: explicitly advisory prose (ARC-023) — part of the D7 hard gate by name, but this specific bar is self-graded; no check verifies input-validation behavior across spell prompts. |
|
|
91
95
|
| Gold | + every destructive or outward-facing action (delete, force-push, publish, external post) is explicitly gated behind confirmation. |
|
|
92
96
|
|
|
93
97
|
### D8 — Conciseness & non-duplication
|
|
94
98
|
|
|
95
99
|
| Tier | Bar |
|
|
96
100
|
| --- | --- |
|
|
97
|
-
| Bronze | No dead or contradictory text. |
|
|
101
|
+
| Bronze | No dead or contradictory text. Enforcement: explicitly advisory prose (ARC-023) — self-graded during spell audit; no coded scorer verifies this dimension. |
|
|
98
102
|
| Silver | + shared logic is **referenced**, not copy-pasted (e.g. point to a governance doc rather than inlining it). |
|
|
99
103
|
| Gold | + tight and single-responsibility — the spell does one job well. |
|
|
100
104
|
|
|
101
105
|
## Scoring & target
|
|
102
106
|
|
|
103
|
-
- **Overall = lowest dimension score.**
|
|
104
|
-
|
|
107
|
+
- **Overall = lowest dimension score.** Enforcement: explicitly advisory prose (ARC-023) — self-graded
|
|
108
|
+
during spell audit; no coded scorer computes or verifies this aggregation.
|
|
109
|
+
- **Hard gates:** D2 and D7 must each be **≥ Silver**. Enforcement: explicitly advisory prose (ARC-023) —
|
|
110
|
+
self-graded during spell audit; only D2's Bronze floor is mechanically checked today, so this broader
|
|
111
|
+
gate is not fully verified by any coded scorer or workflow gate.
|
|
105
112
|
- **Authoring target:** every shipped spell reaches **Silver overall, Gold on D2.** Gold-everywhere is
|
|
106
113
|
aspirational, not required — chasing it on a mature spell usually adds bloat, not value. A short spell
|
|
107
|
-
that meets every gate at Silver is **done**; do not pad it.
|
|
114
|
+
that meets every gate at Silver is **done**; do not pad it. Enforcement: explicitly advisory prose
|
|
115
|
+
(ARC-023) — self-graded during spell audit; no coded scorer verifies overall attainment.
|
|
108
116
|
|
|
109
117
|
## Distributability conventions (D2)
|
|
110
118
|
|
|
@@ -112,20 +120,33 @@ Arcane spells ship to other repositories and, eventually, open source. Keep them
|
|
|
112
120
|
|
|
113
121
|
- **Never hard-code** an org name, person, venture, product, or machine name. Use a documented
|
|
114
122
|
`{UPPER_SNAKE}` placeholder: `{ADO_ORG}`, `{ADO_PROJECT}`, `{BUSINESS_NAME}`, `{OPERATOR_NAME}`.
|
|
123
|
+
Enforcement: executable check (ARC-023) — same mechanism as D2 Bronze above: the `org-token-lint`
|
|
124
|
+
build gate (`scripts/org-token-lint.ts`) fails `npm run build` automatically; `spell ward --gate`
|
|
125
|
+
(`src/commands/ward.ts`) runs the same scan standalone but is not yet wired into CI.
|
|
115
126
|
- **Resolution rule:** a placeholder resolves from `.arcane.json` or the feature/PRD frontmatter; if it
|
|
116
|
-
is unset, the spell **asks** rather than assuming a default.
|
|
127
|
+
is unset, the spell **asks** rather than assuming a default. Enforcement: explicitly advisory prose
|
|
128
|
+
(ARC-023) — depends on each spell's own runtime judgment; no check exercises a spell's unset-placeholder
|
|
129
|
+
behavior.
|
|
117
130
|
- **Roster by reference, not by name:** when a spell needs the concept of an agent role, reference
|
|
118
131
|
[[agent-policies]] / [[naming-conventions]] as context (with a fallback) instead of naming personas
|
|
119
|
-
inline.
|
|
132
|
+
inline. Enforcement: explicitly advisory prose (ARC-023) — self-graded during spell audit; no coded
|
|
133
|
+
scorer verifies this convention.
|
|
120
134
|
- **Trackers are optional:** never assume Azure DevOps (or any single provider). Respect
|
|
121
135
|
`tracking_mode` (internal/external) and detect the provider; the shared rules live in
|
|
122
|
-
[[development-methodology]] — point to them rather than re-inlining ADO logic.
|
|
136
|
+
[[development-methodology]] — point to them rather than re-inlining ADO logic. Enforcement: explicitly
|
|
137
|
+
advisory prose (ARC-023) — self-graded during spell audit; no lint scans spell prompts for a
|
|
138
|
+
hard-coded tracker assumption.
|
|
123
139
|
|
|
124
140
|
> **Maintainer-internal exemption.** A few spells operate *on the Arcane framework itself*
|
|
125
141
|
> (e.g. `spell-bump`, `spell-arcane-version`) and legitimately reference repo internals like
|
|
126
142
|
> `registry.ts`, `src/assets/`, or the `arcane-cli` package name. Such
|
|
127
143
|
> **framework-self-referential** references do **not** count as a D2 violation. The exemption covers
|
|
128
144
|
> only the framework's own internals — never a consuming org's venture, person, machine, or tracker names.
|
|
145
|
+
> **Enforcement: explicitly advisory prose (ARC-023) — depends on an auditor's judgment about what
|
|
146
|
+
> counts as framework-self-reference; `org-token-lint`'s denylist is derived only from package
|
|
147
|
+
> author/repository identity plus the operator-supplied `ARCANE_ORG_TOKENS` list, so these terms were
|
|
148
|
+
> never candidates for that scan regardless of this clause, and no check specifically verifies the
|
|
149
|
+
> carve-out itself.**
|
|
129
150
|
|
|
130
151
|
## How to audit a spell
|
|
131
152
|
|
|
@@ -133,3 +154,6 @@ For each dimension, score Bronze/Silver/Gold with one line of evidence. Record t
|
|
|
133
154
|
score and flag any D2/D7 below Silver as **must-fix**. When elevating, prefer **additive** changes
|
|
134
155
|
(add a fallback, an edge case, an acceptance line, a cross-reference); preserve the spell's intent and
|
|
135
156
|
working prose, and treat any change to *behavior* (not just coverage) as requiring explicit sign-off.
|
|
157
|
+
**Enforcement: explicitly advisory prose (ARC-023) — this audit process, including the must-fix flag
|
|
158
|
+
and the sign-off convention, is self-graded during spell-enchant's review; no coded scorer or
|
|
159
|
+
workflow gate verifies it.**
|
|
@@ -12,10 +12,10 @@ Framework selection, coverage thresholds, and test evidence requirements across
|
|
|
12
12
|
|
|
13
13
|
## Executive Summary
|
|
14
14
|
|
|
15
|
-
- Every tech stack has a designated test framework — no ambiguity.
|
|
15
|
+
- Every tech stack has a designated test framework — no ambiguity. **Enforcement: explicitly advisory prose (ARC-023) — no script or CI step verifies that code for a given stack was tested with its designated framework; the mapping is a team convention enforced only by code review.**
|
|
16
16
|
- New code requires 80% unit test coverage; critical paths require 95%.
|
|
17
|
-
- Lince (QA Lead) must sign off on test evidence before any ticket moves to "Resolved."
|
|
18
|
-
- Test evidence is required in every PR: results, coverage report, known limitations.
|
|
17
|
+
- Lince (QA Lead) must sign off on test evidence before any ticket moves to "Resolved." **Enforcement: explicitly advisory prose (ARC-023) — a tracker-workflow convention Arcane's own tooling has no visibility into and cannot mechanically verify.**
|
|
18
|
+
- Test evidence is required in every PR: results, coverage report, known limitations. **Enforcement: explicitly advisory prose (ARC-023) — no CI step or PR template parses PR descriptions for these sections; `check:review-round` verifies review-approval state only, not test-evidence content.**
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -46,8 +46,8 @@ Framework selection, coverage thresholds, and test evidence requirements across
|
|
|
46
46
|
|
|
47
47
|
| Category | Minimum Coverage | Examples |
|
|
48
48
|
|----------|-----------------|----------|
|
|
49
|
-
| **Standard code** | 80% | Business logic, data access, UI components, API handlers |
|
|
50
|
-
| **Critical paths** | 95% | Authentication, payment processing, IoT firmware commands, calibration protocols, encryption/signing |
|
|
49
|
+
| **Standard code** | 80% | Business logic, data access, UI components, API handlers. Enforcement: executable check (ARC-023) — vitest.config.ts configures a global 80% lines/branches/functions/statements threshold under `coverage.thresholds`, but ci.yml's build-test Test step runs `npm test` (bare `vitest run`), not `npm run test:coverage`, so it is never evaluated in CI. |
|
|
50
|
+
| **Critical paths** | 95% | Authentication, payment processing, IoT firmware commands, calibration protocols, encryption/signing. Enforcement: executable check (ARC-023) — vitest.config.ts overrides this to 95% for src/modules/copier.ts, manifest.ts, merger.ts, registry.ts, and src/config/profiles.ts (manifest.ts's branches override is 90%, not 95%), but the same CI gap applies: `npm test` runs bare `vitest run`, not `npm run test:coverage`, so these overrides are never evaluated in CI. |
|
|
51
51
|
|
|
52
52
|
### What Counts as "Critical"
|
|
53
53
|
|
|
@@ -101,6 +101,8 @@ Every PR must include:
|
|
|
101
101
|
|
|
102
102
|
### Unit Tests (Required)
|
|
103
103
|
|
|
104
|
+
**Enforcement: executable check (ARC-023) — ci.yml's build-test job's Test step runs `npm test` (`vitest run`), which fails the job on any failing unit test; `.husky/pre-commit` runs only `lint` and `typecheck`, not tests, so the "every commit" portion of this rule is not locally enforced.**
|
|
105
|
+
|
|
104
106
|
- Test individual functions/methods in isolation
|
|
105
107
|
- Mock external dependencies (DB, API, hardware)
|
|
106
108
|
- Fast execution (< 1 second per test)
|
|
@@ -108,18 +110,24 @@ Every PR must include:
|
|
|
108
110
|
|
|
109
111
|
### Integration Tests (Recommended)
|
|
110
112
|
|
|
113
|
+
**Enforcement: explicitly advisory prose (ARC-023) — self-labeled Recommended rather than Required, and ci.yml runs a single `npm test` step with no distinct integration-test job or gate.**
|
|
114
|
+
|
|
111
115
|
- Test component interactions (API → DB, mobile → backend)
|
|
112
116
|
- Use real dependencies where practical (in-memory DB, test containers)
|
|
113
117
|
- Run in CI on PR creation and merge
|
|
114
118
|
|
|
115
119
|
### End-to-End Tests (For UI Stories)
|
|
116
120
|
|
|
121
|
+
**Enforcement: explicitly advisory prose (ARC-023) — no Playwright or other end-to-end job exists in ci.yml, and Arcane's own repository is a CLI tool with no UI for this rule to apply to.**
|
|
122
|
+
|
|
117
123
|
- Test complete user workflows
|
|
118
124
|
- Use browser automation (Playwright for web, Flutter integration_test for mobile)
|
|
119
125
|
- Run in CI on merge to main (not on every commit — too slow)
|
|
120
126
|
|
|
121
127
|
### Firmware Tests ({BUSINESS_NAME}-Specific)
|
|
122
128
|
|
|
129
|
+
**Enforcement: explicitly advisory prose (ARC-023) — Arcane's own repository has no firmware or hardware target; this is template guidance for consuming projects that Arcane's own tooling does not verify.**
|
|
130
|
+
|
|
123
131
|
- Host-based unit tests via PlatformIO Unity (no hardware required)
|
|
124
132
|
- Hardware-in-the-loop tests for calibration validation (requires physical device)
|
|
125
133
|
- BLE protocol tests via mock transport
|
|
@@ -130,14 +138,14 @@ Every PR must include:
|
|
|
130
138
|
|
|
131
139
|
Adapt the ticket lifecycle policy to your tracker:
|
|
132
140
|
|
|
133
|
-
The **Code Review → QA** transition now requires:
|
|
141
|
+
The **Code Review → QA** transition now requires: **Enforcement: explicitly advisory prose (ARC-023) — a tracker-workflow gate Arcane's own tooling cannot observe or enforce; items 1 and 2 below (tests passing, coverage thresholds) are independently verified by CI, but the transition itself is not.**
|
|
134
142
|
|
|
135
143
|
1. All unit tests pass (CI green)
|
|
136
144
|
2. Coverage meets thresholds (80% standard / 95% critical)
|
|
137
145
|
3. No HIGH-severity review findings unresolved
|
|
138
146
|
4. Lince signs off with test evidence linked to the work item
|
|
139
147
|
|
|
140
|
-
The **QA → Resolved** transition requires:
|
|
148
|
+
The **QA → Resolved** transition requires: **Enforcement: explicitly advisory prose (ARC-023) — a tracker-workflow gate Arcane's own tooling cannot observe or enforce, the same gap ARC-023 identifies for the Lince sign-off rule above.**
|
|
141
149
|
|
|
142
150
|
1. Integration tests pass (if applicable)
|
|
143
151
|
2. Manual verification for UI stories (screenshot or recording)
|
|
@@ -15,59 +15,59 @@ See also: [[README]], [[DECISIONS]], [[governance/git-conventions|Git Convention
|
|
|
15
15
|
|
|
16
16
|
## Non-Negotiable Safety Rules
|
|
17
17
|
|
|
18
|
-
1. **Never access an encrypted or cross-OS volume you are not authorized to touch.** Do not suggest, execute, or recommend any action that would mount, read, or probe a drive outside the agent's authorized environment. This rule stands as defense-in-depth regardless of encryption status.
|
|
18
|
+
1. **Never access an encrypted or cross-OS volume you are not authorized to touch. Enforcement: explicitly advisory prose (ARC-023) — depends on agent judgment about authorization boundaries; no script scans proposed commands for drive or volume access before execution.** Do not suggest, execute, or recommend any action that would mount, read, or probe a drive outside the agent's authorized environment. This rule stands as defense-in-depth regardless of encryption status.
|
|
19
19
|
|
|
20
|
-
2. **No root commands without justification.** Do not generate or suggest commands that run as root unless explicitly scoped and justified. The agent runtime should run as a dedicated non-root user by design. See [[security/hardening-checklist|Hardening Checklist]].
|
|
20
|
+
2. **No root commands without justification. Enforcement: explicitly advisory prose (ARC-023) — depends on judgment about what justifies root scope; no script inspects generated commands for root usage before they run.** Do not generate or suggest commands that run as root unless explicitly scoped and justified. The agent runtime should run as a dedicated non-root user by design. See [[security/hardening-checklist|Hardening Checklist]].
|
|
21
21
|
|
|
22
|
-
3. **No secrets on the command line.** Never pass API keys, tokens, or secrets on the command line, in chat, or in config files. Use SecretRef (env vars) and `read -s` for interactive input.
|
|
22
|
+
3. **No secrets on the command line. Enforcement: explicitly advisory prose (ARC-023) — no secret-scanner exists in this repo yet (tracked as future work, BC-30), so no mechanical check catches a violation.** Never pass API keys, tokens, or secrets on the command line, in chat, or in config files. Use SecretRef (env vars) and `read -s` for interactive input.
|
|
23
23
|
|
|
24
|
-
4. **This is a production system.** No "fix it later" shortcuts. No experimental changes without rollback plans.
|
|
24
|
+
4. **This is a production system. Enforcement: explicitly advisory prose (ARC-023) — the no-shortcuts and rollback-plan requirements depend on engineering judgment; no check evaluates whether a rollback plan exists.** No "fix it later" shortcuts. No experimental changes without rollback plans.
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
28
|
## Documentation Rules
|
|
29
29
|
|
|
30
|
-
5. **Update `last_updated` frontmatter
|
|
30
|
+
5. **Update `last_updated` frontmatter. Enforcement: explicitly advisory prose (ARC-023) — no lint validates frontmatter fields or verifies `last_updated` was bumped when a document changes.** whenever you edit a document. Every document must have YAML frontmatter with `audience`, `status`, `last_updated`, and `tags`.
|
|
31
31
|
|
|
32
|
-
6. **Log significant decisions in [[DECISIONS]].** Use the next sequential ADR number. Format: Date, Status, Context, Decision, Reasoning, Rejected alternatives.
|
|
32
|
+
6. **Log significant decisions in [[DECISIONS]]. Enforcement: explicitly advisory prose (ARC-023) — whether a decision is "significant" enough to log is a judgment call; `check:adr-references` verifies that ADR citations resolve, not that decisions get logged in the first place.** Use the next sequential ADR number. Format: Date, Status, Context, Decision, Reasoning, Rejected alternatives.
|
|
33
33
|
|
|
34
|
-
7. **Use wiki-links for cross-references
|
|
34
|
+
7. **Use wiki-links for cross-references. Enforcement: explicitly advisory prose (ARC-023) — no link-checker validates wiki-link usage or resolution across this repo's docs.** (e.g., `[[DECISIONS#ADR-NNN|Short Title]]`, `[[journal/YYYY-MM-DD-topic-slug|Session Label]]`). This enables knowledge graph visualization.
|
|
35
35
|
|
|
36
|
-
8. **Use Mermaid for diagrams
|
|
36
|
+
8. **Use Mermaid for diagrams. Enforcement: explicitly advisory prose (ARC-023) — no lint validates diagram block type or the generated-state-diagrams determinism convention.** (` ```mermaid ` blocks) for all flow charts, architecture diagrams, and sequence diagrams. Directory trees stay as plain code blocks. Spell output describing state the spell already computed — not authored, freehand explanatory content — additionally follows the **generated state diagrams** convention ([ARC-036](https://github.com/codemagicianhq/arcane/blob/main/DECISIONS.md#arc-036--generated-state-diagrams-deterministic-mermaid-for-computed-spell-state)): a deterministic, data-derived Mermaid diagram built only from values already in scope, never modeled or invented. Skip it for one-line outputs, speed-rule spells, or any state with only a single reading — the diagram exists to make relationships between multiple already-computed values legible, not to decorate simple output.
|
|
37
37
|
|
|
38
|
-
9. **Journal files use date-prefix naming
|
|
38
|
+
9. **Journal files use date-prefix naming. Enforcement: explicitly advisory prose (ARC-023) — `checkSessionContinuity` only verifies `journal/.gitkeep` exists, not that individual journal filenames follow the date-prefix pattern.** `journal/YYYY-MM-DD-topic-slug.md` for chronological sorting.
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
42
|
## Git Rules
|
|
43
43
|
|
|
44
|
-
10. **Never auto-commit during interactive sessions.** Stage changes and present the proposed commit message for human approval before executing `git commit`. This applies to Copilot, Claude Code, Codex, and any other interactive AI tool. The human decides when to commit. Exception: autonomous agents at Magus+ power level may self-commit within approved scope.
|
|
44
|
+
10. **Never auto-commit during interactive sessions. Enforcement: structured spell gate (ARC-023) — `spell-commit-work`'s Step 8 computes an approval fingerprint over the staged diff and message and halts until an authenticated operator response is tied to it before `git commit` runs.** Stage changes and present the proposed commit message for human approval before executing `git commit`. This applies to Copilot, Claude Code, Codex, and any other interactive AI tool. The human decides when to commit. Exception: autonomous agents at Magus+ power level may self-commit within approved scope.
|
|
45
45
|
|
|
46
|
-
11. **Use Conventional Commits format
|
|
46
|
+
11. **Use Conventional Commits format. Enforcement: explicitly advisory prose (ARC-023) — no commitlint or equivalent hook validates commit message format.** for all commit messages: `type(scope): description`. See [[governance/git-conventions|Git Conventions]] for types, scopes, and examples.
|
|
47
47
|
|
|
48
|
-
12. **Agent attribution trailers
|
|
48
|
+
12. **Agent attribution trailers. Enforcement: explicitly advisory prose (ARC-023) — `spell-commit-work`'s Step 7 documents the required trailers, but no hook or CI check verifies they are actually present on a given commit.** are required on agent-authored commits (`Agent`, `Model`, `Model-Source`, `Provider`). `Persona`/`Role` are conditional — present only when a roster exists and one was assigned, never guessed. See [[governance/git-conventions#agent-attribution-model|Attribution Model]].
|
|
49
49
|
|
|
50
|
-
13. **For runtime config changes
|
|
50
|
+
13. **For runtime config changes. Enforcement: structured spell gate (ARC-023), hedged — `spell-commit-work`'s Step 8 operator-approval gate covers this commit like any other before it can be made, though it verifies diff/message approval rather than a dedicated confirmation that testing occurred.** (anything touching the agent runtime's config files or service restarts): do NOT commit supporting docs until the user has confirmed the change is working. Stage and present — but wait for explicit approval after testing.
|
|
51
51
|
|
|
52
|
-
14. **Never commit directly to main.** All work — human or agent — happens on topic branches. Humans use `type/short-description`; agents use `{agent-slug}/type/short-description`. Main receives changes only through PR completion, not local direct merges. See [[governance/git-conventions#branch-discipline|Branch Discipline]].
|
|
52
|
+
14. **Never commit directly to main. Enforcement: explicitly advisory prose (ARC-023) — `spell doctor`'s `checkPlatformBranchPolicy` verifies only the platform's merge-method policy (squash disallowed), not that direct pushes/commits to main are blocked.** All work — human or agent — happens on topic branches. Humans use `type/short-description`; agents use `{agent-slug}/type/short-description`. Main receives changes only through PR completion, not local direct merges. See [[governance/git-conventions#branch-discipline|Branch Discipline]].
|
|
53
53
|
|
|
54
54
|
---
|
|
55
55
|
|
|
56
56
|
## Spell Lifecycle
|
|
57
57
|
|
|
58
|
-
22. **Lifecycle operations run through their spell when one is installed.** Committing, opening a PR, opening or closing a session, reviewing code, and shipping each have a dedicated spell (`spell-commit-work`, `spell-create-pull-request`, `spell-open-session`/`spell-close-session`, `spell-review`, `spell-ship`). When the installed component set includes the matching spell, invoke it for that operation rather than improvising the workflow from general knowledge — even when the user does not name the spell explicitly. The intent→spell routing table injected into each client's L1 instruction file (`CLAUDE.md`, `.github/copilot-instructions.md`, `AGENTS.md`) is normative for this mapping, not illustrative.
|
|
58
|
+
22. **Lifecycle operations run through their spell when one is installed. Enforcement: explicitly advisory prose (ARC-023) — invoking the correct spell instead of improvising depends on agent judgment; no check verifies that a matching spell was actually invoked for a given operation.** Committing, opening a PR, opening or closing a session, reviewing code, and shipping each have a dedicated spell (`spell-commit-work`, `spell-create-pull-request`, `spell-open-session`/`spell-close-session`, `spell-review`, `spell-ship`). When the installed component set includes the matching spell, invoke it for that operation rather than improvising the workflow from general knowledge — even when the user does not name the spell explicitly. The intent→spell routing table injected into each client's L1 instruction file (`CLAUDE.md`, `.github/copilot-instructions.md`, `AGENTS.md`) is normative for this mapping, not illustrative.
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
62
|
## Recommendation Guardrails (ADR-034)
|
|
63
63
|
|
|
64
|
-
15. **Flag actionable recommendations.** Any recommendation that could lead to a purchase, subscription, account creation, or irreversible action must: (a) be flagged explicitly, (b) use verified current information — never assume or fabricate, (c) present free/no-cost alternatives when they exist, (d) state confidence level if based on general knowledge. For >$50 or contracts, require explicit confirmation. See [[agents/agent-policies#actionable-recommendation-policy-adr-034|Full Policy]].
|
|
64
|
+
15. **Flag actionable recommendations. Enforcement: explicitly advisory prose (ARC-023) — whether a recommendation is flagged, sourced, and confidence-rated depends on judgment; no automated check evaluates response content against this policy.** Any recommendation that could lead to a purchase, subscription, account creation, or irreversible action must: (a) be flagged explicitly, (b) use verified current information — never assume or fabricate, (c) present free/no-cost alternatives when they exist, (d) state confidence level if based on general knowledge. For >$50 or contracts, require explicit confirmation. See [[agents/agent-policies#actionable-recommendation-policy-adr-034|Full Policy]].
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
68
|
## Screenshot Curation
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
24. **Curate screenshots — not every screenshot needs saving. Enforcement: explicitly advisory prose (ARC-023) — which screenshots to keep is a judgment call; no check evaluates screenshot-retention decisions.** Use these heuristics:
|
|
71
71
|
- **Save** when it shows a completed setup, config state, UI result, or evidence of a problem/fix.
|
|
72
72
|
- **Save** when the user explicitly says "save this" or "add this to docs."
|
|
73
73
|
- **Save key decision points and final states** in multi-step flows; skip intermediate steps.
|
|
@@ -80,7 +80,7 @@ See also: [[README]], [[DECISIONS]], [[governance/git-conventions|Git Convention
|
|
|
80
80
|
|
|
81
81
|
## Sensitive Repositories
|
|
82
82
|
|
|
83
|
-
21. **Reference, don't transcribe, when the repository is marked sensitive.** If
|
|
83
|
+
21. **Reference, don't transcribe, when the repository is marked sensitive. Enforcement: explicitly advisory prose (ARC-023) — whether written output cites versus transcribes sensitive content depends on judgment; no check scans agent output for this distinction.** If
|
|
84
84
|
`.arcane.json` has `content_sensitivity: "sensitive"`, the repository's own
|
|
85
85
|
documents are the sensitive material — not just credentials inside them. In
|
|
86
86
|
that mode:
|
|
@@ -106,7 +106,7 @@ See also: [[README]], [[DECISIONS]], [[governance/git-conventions|Git Convention
|
|
|
106
106
|
|
|
107
107
|
## Naming Conventions
|
|
108
108
|
|
|
109
|
-
16. **Three naming tiers — never mix them
|
|
109
|
+
16. **Three naming tiers — never mix them. Enforcement: explicitly advisory prose (ARC-023) — `spell ward` and `org-token-lint` scan for denylisted org/venture/customer names, not for adherence to this tier taxonomy; no check verifies tier consistency.**
|
|
110
110
|
|
|
111
111
|
| Tier | What | Style | Examples |
|
|
112
112
|
|------|------|-------|---------|
|
|
@@ -114,19 +114,19 @@ See also: [[README]], [[DECISIONS]], [[governance/git-conventions|Git Convention
|
|
|
114
114
|
| AI Agents | Autonomous agents | Persona name + role title | Merlin — CTO, Kellar — Product Ops |
|
|
115
115
|
| Systems/Services | DBs, APIs, tools | Functional `[slug]-[function]` | `inventory-api`, `orders-worker` |
|
|
116
116
|
|
|
117
|
-
17. **Projects and repos follow a consistent naming convention.** Pick one (TitleCase or kebab-case) and apply it uniformly across your org.
|
|
117
|
+
17. **Projects and repos follow a consistent naming convention. Enforcement: explicitly advisory prose (ARC-023) — no check verifies TitleCase/kebab-case consistency across projects and repos.** Pick one (TitleCase or kebab-case) and apply it uniformly across your org.
|
|
118
118
|
|
|
119
119
|
---
|
|
120
120
|
|
|
121
121
|
## Operational Rules
|
|
122
122
|
|
|
123
|
-
18. **TODO.md is a scratchpad.** Resolved items move to the relevant doc, then get deleted from TODO.md.
|
|
123
|
+
18. **TODO.md is a scratchpad. Enforcement: explicitly advisory prose (ARC-023) — `checkSessionContinuity` verifies TODO.md exists, not that resolved items are removed from it.** Resolved items move to the relevant doc, then get deleted from TODO.md.
|
|
124
124
|
|
|
125
|
-
19. **After any onboarding or config wizard
|
|
125
|
+
19. **After any onboarding or config wizard. Enforcement: explicitly advisory prose (ARC-023) — no wizard or check re-validates authentication and network-exposure settings after configuration changes.**, re-validate authentication and network-exposure settings — wizards can silently downgrade security settings.
|
|
126
126
|
|
|
127
|
-
20. **For repo path requests
|
|
127
|
+
20. **For repo path requests. Enforcement: explicitly advisory prose (ARC-023) — performing read-only discovery before claiming no access depends on agent judgment; no check verifies this behavior occurred.**, perform read-only discovery before claiming "no access." Use [[agents/agent-approved-paths|Agent Approved Paths Registry]].
|
|
128
128
|
|
|
129
|
-
23. **Diff before deleting a "duplicate."
|
|
129
|
+
23. **Diff before deleting a "duplicate." Enforcement: explicitly advisory prose (ARC-023) — the branch-specific case this generalizes from has a structured procedure (git-conventions.md's Content-Verified Branch Deletion), but no equivalent structured check exists for arbitrary documents, configs, or data files.** When housekeeping surfaces two blocks of content that look
|
|
130
130
|
like duplicates — in a document, a config, a data file — compare them in full before removing
|
|
131
131
|
either. A near-identical pair is usually a **drifted copy carrying unique content in one and not the
|
|
132
132
|
other**, not byte-identical redundancy; deleting on sight can destroy the unique content silently.
|
|
@@ -47,19 +47,19 @@ How a web property becomes retrievable by search-engine crawlers and by the AI a
|
|
|
47
47
|
|
|
48
48
|
### WD-01 — Metadata renders before JavaScript runs
|
|
49
49
|
|
|
50
|
-
**Rule
|
|
50
|
+
**Rule: Per-route share/SEO metadata — title, description, canonical URL, and structured preview tags (Open Graph, a card-style social preview format, JSON-LD) — must be present in the raw HTML response *before* any client-side JavaScript executes. Enforcement: structured spell gate (ARC-023) — spell-make-discoverable's Phase 2 Audit table (Per-route share metadata, WD-01) fetches a live deep route with a non-executing HTTP client and requires a title/description distinct from the homepage before Phase 3's approval gate allows any fix to proceed.**
|
|
51
51
|
|
|
52
52
|
**Why:** Link-unfurl scrapers used by chat apps, messaging platforms, and social platforms fetch the HTML document once over HTTP and do not execute JavaScript. A client-side head-management approach — a library that sets `document.title` and injects meta tags after the app mounts — is invisible to that entire audience, even though it looks completely correct to a human inspecting the live DOM in a browser. The browser ran the JavaScript; the scraper didn't. "Works when I look at it" and "works for the audience that matters here" are different claims, and only one of them is being tested by opening dev tools.
|
|
53
53
|
|
|
54
54
|
### WD-02 — Inject at the existing serving layer, not a new rendering pipeline
|
|
55
55
|
|
|
56
|
-
**Rule
|
|
56
|
+
**Rule: The correct injection point for per-route metadata is the layer *already* serving the built application to browsers — intercept and augment the response there (template substitution, response rewriting, an edge/proxy rule) — not a separate server-side rendering pipeline built to solve this one problem. Enforcement: explicitly advisory (ARC-023) — which layer performed the injection is indistinguishable from the outside, so no executable check or spell gate confirms it; spell-make-discoverable's Phase 2 table cites WD-02 only for Open Graph tag content, not injection-layer architecture.**
|
|
57
57
|
|
|
58
58
|
**Why:** That layer already sees every request and already returns the HTML document; per-route string-level substitution at that point gets the metadata into the raw response without introducing a second rendering runtime, a hydration story, or a new build target. See "Why per-route injection beats both alternatives" below for the fuller comparison.
|
|
59
59
|
|
|
60
60
|
### WD-03 — Dead or non-public routes return a real not-found status
|
|
61
61
|
|
|
62
|
-
**Rule
|
|
62
|
+
**Rule: A route representing content that no longer exists, or that was never public, must return a genuine "not found" HTTP status (404, or 410 if the removal is intentional and permanent) while still rendering the application's own not-found UI in the response body. Enforcement: explicitly advisory (ARC-023) — no executable check or spell gate in this codebase asserts response status codes for dead routes; spell-make-discoverable's Phase 2 table cites WD-03 for canonical-tag uniqueness, a different check.**
|
|
63
63
|
|
|
64
64
|
**Why:** An always-200 catch-all — common with client-side routing, where every path resolves to the same shell and the app decides what to render after the fact — is invisible to a human browsing normally; they see a "not found" page and move on. A search engine reads the status code, not the rendered pixels. A 200 on a dead URL tells the crawler the page is valid and indexable — a "soft 404" — and the URL gets indexed, sometimes ranked, and eventually shown to a searcher as a dead end.
|
|
65
65
|
|
|
@@ -81,13 +81,13 @@ Between an approach that solves a narrower problem than it claims to and one tha
|
|
|
81
81
|
|
|
82
82
|
### WD-04 — Environment-specific values resolve at runtime
|
|
83
83
|
|
|
84
|
-
**Rule
|
|
84
|
+
**Rule: Any value that legitimately differs between deployed environments — most commonly the canonical public origin or hostname embedded in canonical URLs, structured data, or preview metadata — must be resolved at runtime from the actual running environment, never baked in at build time. Enforcement: explicitly advisory (ARC-023) — no executable check confirms build-time values are absent from the running artifact; spell-make-discoverable's Phase 2 table cites WD-04 for JSON-LD validity, a different check.**
|
|
85
85
|
|
|
86
86
|
**Why:** When a single build artifact is deployed unchanged to multiple environments (build once, promote the same artifact — standard practice, and good practice for other reasons), any value fixed at build time is physically identical across every environment that artifact runs in. It cannot carry an environment-specific answer no matter how carefully it was set at build time, because build time happens once, upstream of every environment the artifact will later run in. There is no way to make a single frozen value simultaneously correct for staging and production; the fix is to stop trying and read the value from the environment that's actually running.
|
|
87
87
|
|
|
88
88
|
### WD-05 — Confirm environment flags actually vary, don't trust their default
|
|
89
89
|
|
|
90
|
-
**Rule
|
|
90
|
+
**Rule: A generic "is this production" flag commonly defaults to the same value across *all* deployed environments, not only production. Branching discoverability logic on it (for example, suppressing indexing everywhere that isn't production) silently gives every environment the production answer unless that default has been checked. Before relying on any such signal, confirm it actually differs per environment by reading it back from each running environment — not by trusting how it was configured or assumed to behave. Enforcement: explicitly advisory (ARC-023) — confirming this requires operator judgment about which signal to trust and read back per environment; spell-make-discoverable's Phase 2 table cites WD-05 for basic robots.txt validity, a different check.**
|
|
91
91
|
|
|
92
92
|
**Why:** The mistake is invisible precisely because production looks correct — it's the one environment where the flag's default happens to match reality. The bug only shows up in every *other* environment, which is exactly where it's least likely to get noticed during a review that (reasonably) focuses attention on production. Prefer a signal already confirmed to vary — a runtime-resolved hostname, an explicitly-set per-environment value — over a flag whose default was never actually read back from a non-production environment.
|
|
93
93
|
|
|
@@ -97,13 +97,13 @@ Between an approach that solves a narrower problem than it claims to and one tha
|
|
|
97
97
|
|
|
98
98
|
### WD-06 — Never route crawlers through user-traffic side effects
|
|
99
99
|
|
|
100
|
-
**Rule
|
|
100
|
+
**Rule: Never route crawler or bot traffic through an endpoint that has view-counting, rate-limiting-by-request, or other side effects meant for real user traffic. Serve crawler-facing responses — sitemaps, crawler-visible pages, structured-data feeds — by reading the underlying data directly, bypassing those side-effecting code paths. Enforcement: explicitly advisory (ARC-023) — no executable check or spell gate in this codebase confirms crawler routes bypass side-effecting code paths; spell-make-discoverable's Phase 2 table cites WD-06 for sitemap-directive presence, a different check.**
|
|
101
101
|
|
|
102
102
|
**Why:** A well-behaved crawler generates a high volume of requests across a large route set in a short window, and that volume is not representative of user behavior even when the crawler is behaving exactly as intended. Run that volume through a view counter and the counter becomes meaningless noise on top of real signal. Run it through a rate limiter designed to catch abusive human traffic and it trips the limiter, throttling or blocking the crawler — and the content behind it — for doing nothing wrong.
|
|
103
103
|
|
|
104
104
|
### WD-07 — Crawler listings reuse the application's own visibility rule
|
|
105
105
|
|
|
106
|
-
**Rule
|
|
106
|
+
**Rule: Any listing of publicly discoverable content generated for a crawler — most commonly a sitemap — must be derived from the *exact same* visibility rule the application's own public listing or feed uses for that content, never a second, independently written copy of that rule. Enforcement: structured spell gate (ARC-023) — spell-make-discoverable's Phase 2 Audit table (Robots and sitemap policy, WD-07) checks every sitemap URL against `{PUBLIC_VISIBILITY_PREDICATE}` before Phase 3's approval gate allows any fix to proceed.**
|
|
107
107
|
|
|
108
108
|
**Why:** A hand-maintained second copy of a visibility rule is correct on the day it's written and drifts silently after that. The real rule gains a condition over time — a moderation flag, a scheduled-publish date, a soft-delete check — and the sitemap-generation copy doesn't get the same update, because nothing forces the two to change together. The result is a sitemap that lists things a visitor can't actually reach, or omits things that are genuinely public. Call or import the same predicate the listing endpoint already uses; don't restate its logic anywhere else.
|
|
109
109
|
|
|
@@ -113,7 +113,7 @@ Between an approach that solves a narrower problem than it claims to and one tha
|
|
|
113
113
|
|
|
114
114
|
### WD-08 — A specific allow-rule must be declared to escape a broader disallow
|
|
115
115
|
|
|
116
|
-
**Rule
|
|
116
|
+
**Rule: In a robots-exclusion file, when both an explicit allow-rule for a specific path (for example, a public media/asset path that page metadata references) and a broader disallow-rule for a prefix that would otherwise contain it (for example, a general API path prefix) are both relevant, the specific allow-rule *must be declared* so that it actually takes effect. Enforcement: explicitly advisory (ARC-023) — no executable check or spell gate in this codebase verifies allow/disallow specificity for a given path; spell-make-discoverable's Phase 2 table cites WD-08 for an unrelated non-production noindex-signal check, not this rule's actual claim.**
|
|
117
117
|
|
|
118
118
|
**Why:** Crawlers that respect a robots-exclusion file resolve overlapping rules by specificity — the most specific matching path generally wins over a broader one, not "whichever rule appears first in the file" and not "disallow always wins." Get the specificity wrong, or simply omit the specific allow-rule and assume the broader disallow won't apply to it, and a media-asset path nested under a disallowed API prefix becomes entirely invisible to image crawling — even though the page's own metadata correctly points at that image. A correct metadata reference doesn't help if the crawler was never permitted to fetch what it points to.
|
|
119
119
|
|
|
@@ -127,7 +127,7 @@ The allow-rule for the more specific path has to exist in the file; it isn't inf
|
|
|
127
127
|
|
|
128
128
|
### WD-09 — Non-production origins need crawl control AND index control
|
|
129
129
|
|
|
130
|
-
**Rule
|
|
130
|
+
**Rule: A non-production or staging origin needs *both* a crawl-blocking mechanism (a robots-exclusion rule disallowing the origin) *and* an index-suppression response header (for example, a `noindex` directive delivered via response header, or an equivalent tag) on every response. Enforcement: structured spell gate (ARC-023) — spell-make-discoverable's Phase 2 Audit table (Non-production noindexing, WD-09) fetches a sampled non-prod route and requires both an `X-Robots-Tag: noindex` header and a matching meta tag before Phase 3's approval gate allows any fix to proceed.**
|
|
131
131
|
|
|
132
132
|
```http
|
|
133
133
|
X-Robots-Tag: noindex, nofollow
|
|
@@ -158,15 +158,15 @@ Using only the robots-exclusion rule leaves the bare-URL-listing gap open. Using
|
|
|
158
158
|
|
|
159
159
|
### WD-10 — Apex DNS verification records are appended, not replaced
|
|
160
160
|
|
|
161
|
-
**Rule
|
|
161
|
+
**Rule: Registering a property's ownership with a search console commonly requires adding a DNS TXT record at the domain apex. Follow EV-05 (see [[.arcane/governance/external-verification-standards|External Verification Standards]]) when writing it, rather than re-deriving the append-vs-replace reasoning here — the apex TXT record set is very often already carrying other unrelated values (a mail-sender authorization policy, other verification strings), and a careless write destroys them. Enforcement: structured spell gate (ARC-023) — spell-make-discoverable's Phase 2 Audit table (Search-engine registration, WD-10) re-queries the live DNS record, and Phase 4b requires the operator to confirm the full resulting record as an append before any write is made.**
|
|
162
162
|
|
|
163
163
|
### WD-11 — Cover both instant notification and sitemap freshness
|
|
164
164
|
|
|
165
|
-
**Rule
|
|
165
|
+
**Rule: Instant crawl/recrawl notification protocols exist and are adopted by some search engines and services — IndexNow is one — but not by the search engine with the largest share of global query volume, which instead relies on periodically re-fetching a submitted sitemap. Covering "notify search engines the moment content changes" therefore requires *both*: an instant-notification call where the protocol is supported, *and* ensuring the sitemap itself is submitted through the relevant search console and kept current for the engine(s) that don't support instant notification. Enforcement: structured spell gate (ARC-023) — spell-make-discoverable's Phase 2 Audit table (Search-engine registration, WD-11) checks notification-endpoint wiring and console submission status before Phase 3's approval gate allows any fix to proceed.**
|
|
166
166
|
|
|
167
167
|
### WD-12 — Search-index presence outweighs a static AI-readable file
|
|
168
168
|
|
|
169
|
-
**Rule/observation
|
|
169
|
+
**Rule/observation: For the specific goal of being retrievable *by AI assistants* — as distinct from being found by a human searching directly — being present and current in a major search engine's index is a substantially stronger lever than any single static "AI-readable" convention file placed at a well-known path (for example, a plain-text site-description file such as the emerging `llms.txt` convention). Several AI assistants answer by drawing on a search engine's index rather than crawling the web independently, so an assistant's ability to surface a page is frequently bottlenecked on that page's search-index presence, not on whether a convention file exists at all. A convention file is still worth publishing — it costs little and helps the assistants that do read it directly — but it should not be mistaken for the primary lever. The everything-else in this document (WD-01 through WD-11) is the primary lever. Enforcement: structured spell gate (ARC-023) — spell-make-discoverable's Phase 2 Audit table (Search-engine registration, WD-12) reads the webmaster console's own coverage status verbatim before Phase 3's approval gate allows any fix to proceed.**
|
|
170
170
|
|
|
171
171
|
---
|
|
172
172
|
|
|
@@ -176,8 +176,8 @@ Using only the robots-exclusion rule leaves the bare-URL-listing gap open. Using
|
|
|
176
176
|
|
|
177
177
|
**Rule:** Any user-supplied text embedded into page metadata needs two independent escaping treatments:
|
|
178
178
|
|
|
179
|
-
1. Standard HTML-attribute escaping for the visible meta tags (title, description, preview-card values) — the ordinary defense against a value breaking out of an attribute or tag context
|
|
180
|
-
2. Separately, for structured data embedded as inline JSON inside a `<script type="application/ld+json">` tag: escape the `<` character wherever it appears inside JSON string values (for example, to its Unicode-escape form), in addition to standard JSON string escaping.
|
|
179
|
+
1. **Standard HTML-attribute escaping for the visible meta tags (title, description, preview-card values) — the ordinary defense against a value breaking out of an attribute or tag context.**
|
|
180
|
+
2. **Separately, for structured data embedded as inline JSON inside a `<script type="application/ld+json">` tag: escape the `<` character wherever it appears inside JSON string values (for example, to its Unicode-escape form), in addition to standard JSON string escaping. Enforcement: structured spell gate (ARC-023) — spell-make-discoverable's Phase 2 Audit table (Per-route share metadata, WD-13) renders a sampled route's JSON-LD and surrounding HTML attribute side by side before Phase 3's approval gate allows any fix to proceed.**
|
|
181
181
|
|
|
182
182
|
```json
|
|
183
183
|
{
|
|
@@ -194,13 +194,13 @@ Using only the robots-exclusion rule leaves the bare-URL-listing gap open. Using
|
|
|
194
194
|
|
|
195
195
|
### WD-14 — Aspect ratio, safe margin, file size
|
|
196
196
|
|
|
197
|
-
**Rule
|
|
197
|
+
**Rule: Link-preview (share) images should follow the aspect ratio broadly adopted across major platforms — close to 1.91:1 — with a safe-content margin around the edges so platform-specific cropping doesn't cut off text or a focal subject, and should stay modest in file size. Enforcement: explicitly advisory (ARC-023) — no executable check measures aspect ratio or safe-margin compliance in this codebase; spell-make-discoverable's Phase 2 table cites WD-14 for restricted-path sitemap exclusion, a different check, and checks share-image fetchability/size under the WD-15 label instead.**
|
|
198
198
|
|
|
199
199
|
**Why:** Scrapers fetch preview images synchronously as part of unfurling a link, and some platforms silently refuse to fetch, or silently fail to display, an image above their own size ceiling — there is usually no visible error; the preview simply renders without an image. A safe-content margin matters because different platforms crop the same source image to slightly different final frames; content placed right at the edge survives on some platforms and gets cut on others.
|
|
200
200
|
|
|
201
201
|
### WD-15 — Composite real assets; don't ask a generator for exact type or logos
|
|
202
202
|
|
|
203
|
-
**Rule
|
|
203
|
+
**Rule: Current AI image-generation tools cannot reliably reproduce an exact existing typeface or an exact existing vector logo/mark — both come out as a visible approximation, and no amount of prompt refinement reliably fixes this. It's a property of how these generators work (they produce plausible-looking glyphs and marks probabilistically rather than reproducing exact vector paths or font outlines), not a quality issue specific to any one generation attempt. When brand-exact typography or an exact logo mark matters for a share image, composite the real font files and the real vector logo asset over separately generated artwork or background — don't ask the generator to produce the whole image including the exact type and mark. Enforcement: explicitly advisory (ARC-023) — whether generated artwork faithfully reproduces exact type or a logo is a design judgment call no automated check can verify; spell-make-discoverable's Phase 2 table cites WD-15 for share-image fetchability, a different, mechanically-checkable concern.**
|
|
204
204
|
|
|
205
205
|
---
|
|
206
206
|
|
|
@@ -81,7 +81,7 @@ Show a table (`# | category | disposition | author | file:line | summary | plann
|
|
|
81
81
|
|
|
82
82
|
## Step 5 — Execute
|
|
83
83
|
|
|
84
|
-
Commits in this spell follow `.arcane/governance/git-conventions.md`: Conventional Commits format, agent attribution (`--author` + required `Agent`/`Model`/`Provider` trailers) when an agent authors the change, and — because this is an **interactive session** — present each proposed commit message and **wait for the human's approval before committing** (the Step 4 plan approval covers *what* to do, not the commit itself). Never squash.
|
|
84
|
+
Commits in this spell follow `.arcane/governance/git-conventions.md`: Conventional Commits format, agent attribution (`--author` + required `Agent`/`Model`/`Model-Source`/`Provider` trailers, plus `Persona`/`Role` when a roster exists and one was assigned) when an agent authors the change, and — because this is an **interactive session** — present each proposed commit message and **wait for the human's approval before committing** (the Step 4 plan approval covers *what* to do, not the commit itself). Never squash.
|
|
85
85
|
|
|
86
86
|
For **must-fix** (one thread at a time): read the code → implement → run the relevant tests.
|
|
87
87
|
- **If tests pass:** commit (e.g. `fix(scope): address review — <desc>`) → reply `Fixed in <hash>. <what changed>` (cite the `R#` finding ID if one exists) → resolve the thread immediately.
|
|
@@ -116,12 +116,14 @@ Workflow:
|
|
|
116
116
|
- References to ADRs or files
|
|
117
117
|
- Context for why]
|
|
118
118
|
|
|
119
|
-
Agent: [
|
|
119
|
+
Agent: [runtime/tool name only -- claude, copilot, codex -- never a persona name]
|
|
120
|
+
Persona: [roster identity operated as, ONLY if a roster exists (.arcane/agents.yaml) and one was assigned this session -- omit entirely otherwise, never guess]
|
|
121
|
+
Role: [Persona's own AgentDefinition.role value, resolved from the roster -- never typed by hand. Present only if Persona is present]
|
|
120
122
|
Model: [model identifier, e.g., claude-opus-4-20250918]
|
|
123
|
+
Model-Source: [self-reported -- currently the only defined value; marks Model/Agent as self-reported, not independently verified]
|
|
121
124
|
Provider: [anthropic or openai]
|
|
122
125
|
Vendor: [arcane-cli, for vendored scaffold/update commits]
|
|
123
126
|
Vendor-Version: [programmatically derived installed package version, when available]
|
|
124
|
-
Role: [agent role slug, if applicable]
|
|
125
127
|
Task-Type: [docs, code, review, marketing, infra]
|
|
126
128
|
Channel: [vscode, cli, chat]
|
|
127
129
|
```
|
|
@@ -132,7 +134,7 @@ Workflow:
|
|
|
132
134
|
- Body is optional but useful for complex changes
|
|
133
135
|
- Reference ADRs if applicable (e.g., "Implements ADR-028")
|
|
134
136
|
- Trailers go after a blank line following the body (standard Git footer position)
|
|
135
|
-
- Required trailers for agent commits: `Agent`, `Model`, `Provider`
|
|
137
|
+
- Required trailers for agent commits: `Agent`, `Model`, `Model-Source`, `Provider`. `Persona`/`Role` are conditional -- see `.arcane/governance/git-conventions.md`'s Agent Attribution Model for the full rule and the grading-probe example of what happens when `Role` is guessed instead of sourced.
|
|
136
138
|
- Required trailer for Arcane-vendored commits: `Vendor: arcane-cli`; include `Vendor-Version` only when derived from the installed CLI at commit time
|
|
137
139
|
- Human-authored commits: trailers are optional
|
|
138
140
|
|
|
@@ -122,7 +122,7 @@ Execute the `spell-implement` workflow:
|
|
|
122
122
|
b1. **DB migration guard.** If `architecture.md`/the PRD did not name a database migration as part of this feature's scope, but implementing this story is about to produce one anyway, **halt and flag it** — do not write the migration file silently (2026-07-22 dogfooding finding: this is a scoped hard guard, not a blanket ban). If a migration genuinely is in scope, **re-derive its sequence number from a fresh `git pull --ff-only` of the target branch immediately before writing the file** — not once at branch-creation time in step 0 — so a concurrent epic that landed a migration in the meantime is reflected. This is the concrete fix for a real incident: two epics run in parallel worktrees each independently claimed the same migration sequence number, invisible until human merge review.
|
|
123
123
|
c. Write tests per `governance/testing-standards.md`.
|
|
124
124
|
d. Run tests. If passing:
|
|
125
|
-
- In `external/ado` mode, commit with `#{adoWorkItemId} type(scope): description` and agent attribution trailers (`Agent`, `Model`, `Provider`).
|
|
125
|
+
- In `external/ado` mode, commit with `#{adoWorkItemId} type(scope): description` and agent attribution trailers (`Agent`, `Model`, `Model-Source`, `Provider`).
|
|
126
126
|
- In `internal` mode, commit with standard Conventional Commits format (no ADO prefix) plus attribution trailers.
|
|
127
127
|
e. Update `stories.json`: set `passes: true`, fill `testEvidence`.
|
|
128
128
|
f. Append learnings to `progress.txt`.
|
|
@@ -240,7 +240,7 @@ exactly one phase carries it at a time, matching the status line's own `[Phase N
|
|
|
240
240
|
- **One human gate only.** Everything before Phase 6 step 5 is autonomous. Do not ask for intermediate approvals unless a gate fails.
|
|
241
241
|
- **No scope creep.** Only build what the feature description specifies.
|
|
242
242
|
- **Fail fast.** If a phase cannot succeed, halt immediately rather than producing garbage for downstream phases.
|
|
243
|
-
- **Attribution required.** Every commit must carry `Agent`, `Model`, and `Provider` trailers per ADR-028/ADR-029.
|
|
243
|
+
- **Attribution required.** Every commit must carry `Agent`, `Model`, `Model-Source`, and `Provider` trailers per ADR-028/ADR-029, plus `Persona`/`Role` when a roster exists and one was assigned.
|
|
244
244
|
- **Branch discipline.** All work on topic branches, never on main — see `.arcane/governance/git-conventions.md`'s Trunk-based development rule. (Corrected 2026-08-31, BC-14: previously cited "ADR-048," which does exist in the shipped `framework-decisions.md` reference but is actually about the Code-Versus-Docs Branch Policy's local-only-repo fallback, unrelated to this general rule — a topical miscitation, the same class BC-06 found and fixed elsewhere. `git-conventions.md` states this rule directly with no ADR/ARC number attached, so there is nothing to cite beyond the file itself.)
|
|
245
245
|
- **Fresh context per story.** Do not carry assumptions between stories during Phase 3.
|
|
246
246
|
- **Epic checkpointing.** When this spell is run as one epic in a multi-epic plan, recommend running `spell-commit-work` before starting the next epic.
|