@theagilemonkeys/facility 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +68 -0
  3. package/bin/facility.mjs +10 -0
  4. package/modules/README.md +35 -0
  5. package/modules/ai-queryability/agents/queryability-reviewer.md +35 -0
  6. package/modules/ai-queryability/module.json +9 -0
  7. package/modules/ai-queryability/standard-section.md +22 -0
  8. package/modules/analytics/agents/analytics-reviewer.md +32 -0
  9. package/modules/analytics/commands/add-telemetry.md +23 -0
  10. package/modules/analytics/module.json +10 -0
  11. package/modules/analytics/standard-section.md +23 -0
  12. package/modules/database/agents/data-security-reviewer.md +38 -0
  13. package/modules/database/commands/new-migration.md +24 -0
  14. package/modules/database/guards/migration-versions.mjs +41 -0
  15. package/modules/database/guards/migrations-immutable.mjs +57 -0
  16. package/modules/database/hooks/protect-migrations.fragment.mjs +10 -0
  17. package/modules/database/module.json +25 -0
  18. package/modules/database/standard-section.md +20 -0
  19. package/modules/design-system/agents/design-reviewer.md +37 -0
  20. package/modules/design-system/module.json +9 -0
  21. package/modules/design-system/standard-section.md +15 -0
  22. package/package.json +42 -0
  23. package/src/add.mjs +77 -0
  24. package/src/cli.mjs +352 -0
  25. package/src/detect.mjs +127 -0
  26. package/src/doctor.mjs +582 -0
  27. package/src/init.mjs +572 -0
  28. package/src/instance.mjs +114 -0
  29. package/src/platform-admin.mjs +1542 -0
  30. package/src/platform-config.mjs +39 -0
  31. package/src/platform.mjs +1759 -0
  32. package/src/prompts.mjs +64 -0
  33. package/src/render.mjs +66 -0
  34. package/src/ui.mjs +30 -0
  35. package/templates/claude/agents/security-reviewer.md +41 -0
  36. package/templates/claude/agents/standards-reviewer.md +31 -0
  37. package/templates/claude/commands/open-pr.md +21 -0
  38. package/templates/claude/commands/verify.md +16 -0
  39. package/templates/claude/hooks/protect-branch.mjs +58 -0
  40. package/templates/claude/hooks/protect-files.mjs +35 -0
  41. package/templates/claude/settings.json +71 -0
  42. package/templates/claude/skills/maintainable-software/SKILL.md +67 -0
  43. package/templates/claude/skills/reviewing-to-standard/SKILL.md +49 -0
  44. package/templates/claude/skills/working-to-standard/SKILL.md +45 -0
  45. package/templates/delivery/verify.mjs +157 -0
  46. package/templates/doctor/resolve.mjs +144 -0
  47. package/templates/guards/README.md +30 -0
  48. package/templates/guards/_kit.mjs +81 -0
  49. package/templates/guards/actions-pinned.mjs +38 -0
  50. package/templates/guards/run.mjs +111 -0
  51. package/templates/guards/watchtower-locked.mjs +66 -0
  52. package/templates/prompts/address-review.md +14 -0
  53. package/templates/prompts/architect.md +62 -0
  54. package/templates/prompts/builder.md +71 -0
  55. package/templates/prompts/doctor.md +64 -0
  56. package/templates/prompts/review.md +14 -0
  57. package/templates/prompts/sweep.md +75 -0
  58. package/templates/receipts/collect.mjs +289 -0
  59. package/templates/review/finalize.mjs +38 -0
  60. package/templates/scripts/move-board-status.sh +155 -0
  61. package/templates/security/sync-findings.mjs +226 -0
  62. package/templates/standard/STANDARD.md +141 -0
  63. package/templates/standard/agents-block.md +25 -0
  64. package/templates/watchtower/budgets.json +12 -0
  65. package/templates/watchtower/canary.mjs +216 -0
  66. package/templates/watchtower/health.mjs +148 -0
  67. package/templates/watchtower/outcomes.mjs +188 -0
  68. package/templates/workflows/facility-address-review.yml +153 -0
  69. package/templates/workflows/facility-canary.yml +61 -0
  70. package/templates/workflows/facility-codex.yml +326 -0
  71. package/templates/workflows/facility-crew.yml +350 -0
  72. package/templates/workflows/facility-doctor.yml +155 -0
  73. package/templates/workflows/facility-review.yml +134 -0
  74. package/templates/workflows/facility-security-sweep.yml +204 -0
  75. package/templates/workflows/facility-watchtower.yml +87 -0
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # @theagilemonkeys/facility
2
+
3
+ The command-line half of [Facility](https://github.com/theam/facility) —
4
+ open-source, self-hosted tooling for running AI coding agents as part of a
5
+ reviewable delivery process, with the humans, the gates and the evidence in one
6
+ place.
7
+
8
+ One binary with two jobs, and you rarely need both:
9
+
10
+ - **A client for a Facility platform.** Dispatch agents, follow sessions, decide
11
+ proposals, inspect spend, manage projects and repositories — everything the
12
+ web application does, from a terminal or a script.
13
+ - **An installer for a repository.** When a team wants the process running in
14
+ its own CI, invoked from issue comments, `facility init` writes the workflows,
15
+ the standard, the skills and the guards into the repository.
16
+
17
+ ```bash
18
+ npx @theagilemonkeys/facility --help
19
+ ```
20
+
21
+ Node.js 20 or newer. Zero configuration to read; one dependency.
22
+
23
+ **Early software.** Facility is published while it is still being built: the
24
+ API is young, generated files change shape between `0.x` releases, and no
25
+ upgrade path is promised across them. Apache-2.0 means what it says — no
26
+ warranty, use at your own risk.
27
+
28
+ ## Talking to a platform
29
+
30
+ ```bash
31
+ npx @theagilemonkeys/facility login --url https://facility.example.com --key fak_…
32
+ npx @theagilemonkeys/facility status # runs, approvals, issues and spend at a glance
33
+ npx @theagilemonkeys/facility inbox # review and decide pending proposals
34
+ npx @theagilemonkeys/facility sessions # trigger, watch, steer or cancel agent runs
35
+ ```
36
+
37
+ Platform commands take a global `--json`, `--profile <name>` and
38
+ `--timeout <seconds>`, so the CLI is as usable from a script as from a prompt.
39
+ It speaks the same versioned REST API and obeys the same permissions as the web
40
+ application: what your key cannot do, the CLI will not do either.
41
+
42
+ ## Installing the process into a repository
43
+
44
+ ```bash
45
+ cd your-repository
46
+ npx @theagilemonkeys/facility init
47
+ npx @theagilemonkeys/facility doctor --run-guards --github
48
+ ```
49
+
50
+ `init` asks about the package manager, the default branch, the commands that
51
+ provision an environment and verify a change, then writes GitHub workflows for
52
+ planning, building, reviewing and repairing, plus `STANDARD.md`, agent
53
+ instructions, skills, deterministic guards, and a `.facility.json` recording the
54
+ answers. It never overwrites an existing generated file unless you pass
55
+ `--force`, and it appends to `AGENTS.md` and `CLAUDE.md` inside a delimited
56
+ managed block rather than replacing them.
57
+
58
+ This is the second step, not the entry price: a repository connected to a
59
+ Facility platform is operated entirely from the platform, without a single file
60
+ being added to it.
61
+
62
+ ## Documentation
63
+
64
+ - [CLI reference](https://github.com/theam/facility/blob/main/apps/docs/docs/reference/cli.md)
65
+ - [Self-hosting guide](https://github.com/theam/facility/blob/main/apps/docs/docs/self-host/quickstart.md)
66
+ - [Repository and issues](https://github.com/theam/facility)
67
+
68
+ Apache-2.0 · an initiative by [The Agile Monkeys](https://theagilemonkeys.com)
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "../src/cli.mjs";
3
+
4
+ main(process.argv.slice(2)).then(
5
+ (code) => process.exit(code ?? 0),
6
+ (error) => {
7
+ console.error(error?.code === "prompt_eof" ? error.message : (error?.stack ?? String(error)));
8
+ process.exit(1);
9
+ }
10
+ );
@@ -0,0 +1,35 @@
1
+ # Modules
2
+
3
+ A facility module packages one quality concern in every form a rule needs to
4
+ actually hold:
5
+
6
+ 1. **Prose** — a section inserted into your `STANDARD.md`, so agents and
7
+ humans know the rule and the reasoning.
8
+ 2. **A reviewer** — a subagent in `.claude/agents/` that judges the gray area
9
+ prose can't pin down.
10
+ 3. **Checks** — deterministic guards and hooks for the part that should never
11
+ depend on judgment.
12
+ 4. **Workflows** — slash commands in `.claude/commands/` for the procedures
13
+ the module prescribes (e.g. `/new-migration`, `/add-telemetry`), so the
14
+ right way is also the easy way.
15
+
16
+ Install one with:
17
+
18
+ ```
19
+ npx @theagilemonkeys/facility add <module>
20
+ ```
21
+
22
+ | module | what it enforces |
23
+ |---|---|
24
+ | `analytics` | new features ship privacy-safe analytics; missing events are correctness bugs |
25
+ | `database` | migrations are immutable and append-only; row-level security by default |
26
+ | `ai-queryability` | durable product data is queryable/actionable by AI, or the waiver is written down |
27
+ | `design-system` | UI changes conform to your design system and carry browser evidence |
28
+
29
+ ## Writing your own
30
+
31
+ Copy the shape of any module here: a `module.json` manifest, a
32
+ `standard-section.md`, and optional `agents/`, `guards/`, and `hooks/`
33
+ fragments. Then `npx @theagilemonkeys/facility add ./path/to/your-module`. If a concern
34
+ keeps biting your team, it deserves the full triple — a rule that exists only
35
+ as prose will be missed again.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: queryability-reviewer
3
+ description: Enforces "AI queryability by default". Use when a change adds or modifies durable, user-relevant data. Checks the feature is discoverable and actionable through search, agent tools, and MCP — or that a waiver is documented.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You verify that new durable product data is not trapped behind a human-only
8
+ UI. Every new durable feature should be queryable and actionable by AI by
9
+ default; if exposing it is unsafe or not product-sensible, the PR must
10
+ document the waiver.
11
+
12
+ ## What to check
13
+ 1. **Search**: new user-relevant data is indexed and discoverable under the
14
+ same access control the UI enforces.
15
+ 2. **Agent tools**: the product's chat/search agent can reach the feature
16
+ when users would expect it to read, explain, or act on it.
17
+ 3. **MCP**: safe read/list/get tools exist, plus any necessary action tools,
18
+ wired into the tool registry. Mutations are explicit about side effects,
19
+ confirmation, idempotency, and permissions.
20
+ 4. **Triggers/jobs**: if the change affects indexes/summaries/derived
21
+ state/notifications, a reliable trigger or job path exists with explicit
22
+ retries and idempotency.
23
+ 5. **Empty results are permission-safe** — no implication that hidden data
24
+ exists.
25
+
26
+ ## How to verify
27
+ - `grep` the search/agent/MCP registries to confirm the new entity is wired
28
+ end to end.
29
+ - Run the repo's MCP/tool test suite when one exists.
30
+
31
+ ## Output contract
32
+ For each new durable entity, report its exposure status across
33
+ Search / Agent tools / MCP / Triggers as Exposed / Missing / Waived, with
34
+ file:line and the fix for anything missing. If a waiver is claimed, confirm
35
+ the reason is written down in the PR. Flag only queryability/correctness gaps.
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "ai-queryability",
3
+ "title": "AI Queryability",
4
+ "description": "Durable product data is queryable and actionable by AI by default — or the waiver is written down.",
5
+ "standardSection": "standard-section.md",
6
+ "files": [
7
+ { "from": "agents/queryability-reviewer.md", "to": ".claude/agents/queryability-reviewer.md" }
8
+ ]
9
+ }
@@ -0,0 +1,22 @@
1
+ ### AI queryability (facility module)
2
+
3
+ Every new durable feature is queryable and actionable by AI by default. Data
4
+ trapped behind a human-only UI is invisible to your product's search, chat
5
+ agent, and MCP surface — and to every workflow your users will automate next
6
+ year. If exposing it is unsafe or not product-sensible, **document that
7
+ waiver in the PR**; an undocumented omission is a gap.
8
+
9
+ When a feature creates new user-relevant data, check each surface:
10
+
11
+ - **Search**: the data is indexed and discoverable under the same access
12
+ control the UI enforces.
13
+ - **Agent tools**: the product's chat/search agent can read, explain, or act
14
+ on the feature when users would expect it to.
15
+ - **MCP**: safe read/list/get tools exist, plus necessary action tools.
16
+ Mutating tools are explicit about side effects, confirmation, idempotency,
17
+ and permission boundaries.
18
+ - **Triggers/jobs**: if the feature changes data that affects search indexes,
19
+ summaries, derived state, or notifications, a reliable trigger/job path
20
+ exists with explicit retries and idempotency.
21
+ - **Empty results are permission-safe**: an AI surface must not imply hidden
22
+ data exists when access control returns nothing.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: analytics-reviewer
3
+ description: Reviews analytics coverage and telemetry privacy. Use when a feature adds runtime behavior, or when analytics events or telemetry helpers change. Treats missing analytics on a new feature as a correctness issue, and PII in product analytics as a defect.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You review whether a change ships the right analytics **and** respects the
8
+ privacy contract in `STANDARD.md` (Analytics section). Missing analytics on a
9
+ feature with runtime behavior is a correctness issue, not polish.
10
+
11
+ ## What to check
12
+ 1. New user-facing behavior has an event plan: started / completed / failed,
13
+ plus validation errors, permission denials, cancellations, retries, empty
14
+ results, and background-job lifecycle where relevant.
15
+ 2. Event names live in the repo's event catalog — flag any hard-coded
16
+ event-name string literals at call sites.
17
+ 3. **Privacy**: captured properties contain only IDs, enums, counts,
18
+ durations, booleans, route paths, and field names — never message text,
19
+ user content, names, credentials, or full URLs.
20
+ 4. Telemetry tests are added/updated when event names, sanitization, or
21
+ required properties change.
22
+
23
+ ## How to verify
24
+ - `grep` call sites for string-literal event names that bypass the catalog.
25
+ - Run the repo's telemetry tests when analytics changed.
26
+
27
+ ## Output contract
28
+ List gaps by severity, each with file:line and the fix. Explicitly confirm
29
+ there is no PII in captured properties, or name every offending property. If
30
+ analytics is intentionally skipped, require that the waiver reason is stated
31
+ in the PR. End with the checks you ran. Flag only correctness/privacy gaps,
32
+ not style.
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: Add privacy-safe analytics for a feature, per STANDARD.md's Analytics section
3
+ ---
4
+
5
+ Instrument a feature following STANDARD.md's Analytics section.
6
+
7
+ 1. Write the event plan BEFORE touching code, in the task notes or PR
8
+ summary: user story (who acts, what success/failure means), surface
9
+ (entry points, primary actions, failure/empty/completion states), and the
10
+ event catalog — started/completed/failed, validation errors, permission
11
+ denials, cancellations, retries, background-job lifecycle.
12
+ 2. Add event names to this repo's event catalog file — find it (grep for
13
+ existing event-name constants) and follow its convention. Never hard-code
14
+ event-name strings at call sites.
15
+ 3. Privacy check on every property: IDs, enums, counts, durations, booleans,
16
+ route paths, and field names only. No message text, no user content, no
17
+ names, no credentials, no full URLs. If a property could identify a person
18
+ or quote their content, it doesn't ship.
19
+ 4. Add or update telemetry tests when event names, sanitization, or required
20
+ properties change.
21
+ 5. Verify with the repo's telemetry tests, and finish by listing the events
22
+ added and the failure paths they cover — uninstrumented failure paths are
23
+ the gap reviewers will catch.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "analytics",
3
+ "title": "Analytics",
4
+ "description": "New features ship privacy-safe analytics; missing events are correctness bugs.",
5
+ "standardSection": "standard-section.md",
6
+ "files": [
7
+ { "from": "agents/analytics-reviewer.md", "to": ".claude/agents/analytics-reviewer.md" },
8
+ { "from": "commands/add-telemetry.md", "to": ".claude/commands/add-telemetry.md" }
9
+ ]
10
+ }
@@ -0,0 +1,23 @@
1
+ ### Analytics (facility module)
2
+
3
+ New features must ship with analytics unless the feature has no runtime
4
+ behavior. **Missing analytics on a new feature is a correctness issue, not
5
+ polish** — a feature you cannot measure is a feature you cannot operate.
6
+
7
+ Before implementing, write the event plan in the task notes or PR summary:
8
+
9
+ - User story: who acts, what they are trying to do, what success/failure means.
10
+ - Surface: entry points, primary actions, failure states, completion states.
11
+ - Event catalog: started/completed/failed, validation errors, permission
12
+ denials, cancellations, retries, empty results, background-job lifecycle.
13
+
14
+ Implementation rules:
15
+
16
+ - Event names live in one catalog file — never hard-coded strings at call
17
+ sites. (Declare the catalog path here once you have one.)
18
+ - Product analytics must not capture message text, user content, names,
19
+ credentials, or full URLs. Capture IDs, enums, counts, durations, booleans,
20
+ route paths, and field names.
21
+ - Add or update telemetry tests when event names, sanitization, or required
22
+ properties change.
23
+ - If a feature intentionally skips analytics, write the reason in the PR.
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: data-security-reviewer
3
+ description: Adversarial reviewer for database access control, migrations, privileged credentials, and data exposure. Use proactively before merging any change that touches migrations, access policies, auth helpers, or grants.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You are a database-authorization security reviewer. You review a diff in a
8
+ fresh context, so you are not biased toward the code under review. Assume
9
+ access-control gaps **fail silently** (they return empty rows, not errors) —
10
+ verify the negative case, never trust a prose claim that "access control is
11
+ enforced".
12
+
13
+ ## What to check
14
+ 1. New tables/collections in exposed scopes: access control enabled, deny by
15
+ default, broad default grants revoked, minimum grants only.
16
+ 2. No policy inlines raw token/claim parsing — authorization routes through
17
+ the repo's shared helper layer.
18
+ 3. Functions or procedures that bypass access control (e.g. SECURITY DEFINER,
19
+ stored procs running as owner): re-check authorization first, pin their
20
+ execution environment, and keep them listed in the repo's audit doc.
21
+ 4. Privileged credentials stay out of user-facing and agent-facing read
22
+ paths; any privileged action sits behind explicit permission checks with
23
+ tests.
24
+ 5. Migrations in the diff only ADD files — `node guards/run.mjs
25
+ --only=migrations-immutable` proves it.
26
+ 6. Empty results are permission-safe — nothing hints that hidden data exists.
27
+
28
+ ## How to verify
29
+ - `node guards/run.mjs --only=migrations-immutable`
30
+ - The repo's access-control test suite, when the diff touches policies,
31
+ grants, or auth helpers.
32
+
33
+ ## Output contract
34
+ Return findings ordered by severity (Blocker / High / Medium), each with
35
+ file:line, the exact risk, and the smallest fix. State which checks you ran
36
+ and their result. Report **only** authorization/security/privacy/correctness
37
+ gaps — not style. If you find nothing, say "No authorization gaps found" and
38
+ list the checks that prove it.
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: Scaffold a new migration with safety defaults — never edit an existing one
3
+ ---
4
+
5
+ Create a new database migration following STANDARD.md's Database section.
6
+
7
+ 1. Locate the migrations directory (`migrations/`, `supabase/migrations/`,
8
+ `db/migrations/`, `prisma/migrations/` — whichever this repo uses) and
9
+ follow its existing naming convention (timestamp prefix, snake_case
10
+ description).
11
+ 2. Create a NEW file. Never modify or delete an existing migration — they are
12
+ append-only; the `migrations-immutable` guard and the file hooks enforce
13
+ it.
14
+ 3. Safety defaults in the scaffold, adapted to this repo's stack:
15
+ - New tables start closed: enable row/document-level access control where
16
+ supported, deny by default, grant only the minimum operations.
17
+ - Authorization routes through the repo's shared helper layer — no inline
18
+ token/claim parsing in policies.
19
+ - Destructive operations (drop, irreversible data rewrites) get a written
20
+ justification comment and, where the stack supports it, a down path.
21
+ 4. If the feature needs realistic data to test, update the seeds in the same
22
+ change.
23
+ 5. Verify: run the repo's migration apply/reset command if one exists, then
24
+ `node guards/run.mjs --only=migrations-immutable`.
@@ -0,0 +1,41 @@
1
+ // facility module: database
2
+ //
3
+ // Two migrations with the same version prefix apply in undefined order — and
4
+ // on some stacks, silently skip. Collisions happen exactly when two branches
5
+ // (or two agents) scaffold migrations the same day and both merge. This guard
6
+ // fails the build the moment both exist on one branch.
7
+ import { readdirSync } from "node:fs";
8
+
9
+ const MIGRATION_DIRS = ["migrations", "supabase/migrations", "db/migrations", "prisma/migrations"];
10
+
11
+ export default {
12
+ name: "migration-versions",
13
+ description: "no two migration files share a version prefix",
14
+ run() {
15
+ const violations = [];
16
+ for (const dir of MIGRATION_DIRS) {
17
+ let files;
18
+ try {
19
+ files = readdirSync(dir).filter((f) => /^\d/.test(f));
20
+ } catch {
21
+ continue;
22
+ }
23
+ const byVersion = new Map();
24
+ for (const file of files) {
25
+ const version = file.match(/^(\d+)/)?.[1];
26
+ if (!version) continue;
27
+ if (!byVersion.has(version)) byVersion.set(version, []);
28
+ byVersion.get(version).push(file);
29
+ }
30
+ for (const [version, group] of byVersion) {
31
+ if (group.length > 1) {
32
+ violations.push({
33
+ file: `${dir}/${group[1]}`,
34
+ message: `version ${version} collides across: ${group.join(", ")} — regenerate with a fresh timestamp`,
35
+ });
36
+ }
37
+ }
38
+ }
39
+ return violations;
40
+ },
41
+ };
@@ -0,0 +1,57 @@
1
+ // facility module: database
2
+ //
3
+ // Applied migrations are immutable. This guard fails when a commit range
4
+ // modifies or deletes an existing migration file instead of adding a new one.
5
+ // In CI it diffs against the PR base; locally it diffs against the merge-base
6
+ // with the default branch.
7
+ import { execFileSync } from "node:child_process";
8
+
9
+ // Directories that hold ordered migration files. Adjust to your stack.
10
+ const MIGRATION_DIRS = [
11
+ "migrations/",
12
+ "supabase/migrations/",
13
+ "db/migrations/",
14
+ "prisma/migrations/",
15
+ ];
16
+
17
+ // key: "<path>", value: written reason (e.g. "squashed baseline, 2026-01").
18
+ const ALLOWLIST = {};
19
+
20
+ function git(args) {
21
+ try {
22
+ return execFileSync("git", args, {
23
+ encoding: "utf8",
24
+ stdio: ["ignore", "pipe", "ignore"],
25
+ }).trim();
26
+ } catch {
27
+ return "";
28
+ }
29
+ }
30
+
31
+ export default {
32
+ name: "migrations-immutable",
33
+ description: "existing migration files are never edited or deleted, only added",
34
+ run() {
35
+ const base =
36
+ process.env.GITHUB_BASE_SHA ||
37
+ git(["merge-base", "HEAD", `origin/${process.env.DEFAULT_BRANCH || "main"}`]) ||
38
+ git(["merge-base", "HEAD", "main"]);
39
+ if (!base) return []; // shallow clone or fresh repo — nothing to compare against
40
+
41
+ const out = git(["diff", "--name-status", base, "HEAD"]);
42
+ const violations = [];
43
+ for (const row of out.split("\n").filter(Boolean)) {
44
+ const [status, ...paths] = row.split("\t");
45
+ const path = paths[paths.length - 1];
46
+ if (!MIGRATION_DIRS.some((dir) => path.startsWith(dir))) continue;
47
+ if (status.startsWith("M") || status.startsWith("D") || status.startsWith("R")) {
48
+ if (ALLOWLIST[path]) continue;
49
+ violations.push({
50
+ file: path,
51
+ message: `migration ${status.startsWith("D") ? "deleted" : "modified"} — migrations are append-only; write a new one`,
52
+ });
53
+ }
54
+ }
55
+ return violations;
56
+ },
57
+ };
@@ -0,0 +1,10 @@
1
+ // facility module: database — migration immutability (PreToolUse)
2
+ if (/(^|\/)(supabase\/|db\/|prisma\/)?migrations\/[^/]+\.(sql|js|ts|rb|py)$/.test(filePath)) {
3
+ const tool = payload?.tool_name ?? "";
4
+ const isEdit = tool === "Edit" || tool === "MultiEdit";
5
+ if (isEdit) {
6
+ block(
7
+ "Migration files are immutable once written. Create a NEW timestamped migration instead.",
8
+ );
9
+ }
10
+ }