@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.
- package/LICENSE +201 -0
- package/README.md +68 -0
- package/bin/facility.mjs +10 -0
- package/modules/README.md +35 -0
- package/modules/ai-queryability/agents/queryability-reviewer.md +35 -0
- package/modules/ai-queryability/module.json +9 -0
- package/modules/ai-queryability/standard-section.md +22 -0
- package/modules/analytics/agents/analytics-reviewer.md +32 -0
- package/modules/analytics/commands/add-telemetry.md +23 -0
- package/modules/analytics/module.json +10 -0
- package/modules/analytics/standard-section.md +23 -0
- package/modules/database/agents/data-security-reviewer.md +38 -0
- package/modules/database/commands/new-migration.md +24 -0
- package/modules/database/guards/migration-versions.mjs +41 -0
- package/modules/database/guards/migrations-immutable.mjs +57 -0
- package/modules/database/hooks/protect-migrations.fragment.mjs +10 -0
- package/modules/database/module.json +25 -0
- package/modules/database/standard-section.md +20 -0
- package/modules/design-system/agents/design-reviewer.md +37 -0
- package/modules/design-system/module.json +9 -0
- package/modules/design-system/standard-section.md +15 -0
- package/package.json +42 -0
- package/src/add.mjs +77 -0
- package/src/cli.mjs +352 -0
- package/src/detect.mjs +127 -0
- package/src/doctor.mjs +582 -0
- package/src/init.mjs +572 -0
- package/src/instance.mjs +114 -0
- package/src/platform-admin.mjs +1542 -0
- package/src/platform-config.mjs +39 -0
- package/src/platform.mjs +1759 -0
- package/src/prompts.mjs +64 -0
- package/src/render.mjs +66 -0
- package/src/ui.mjs +30 -0
- package/templates/claude/agents/security-reviewer.md +41 -0
- package/templates/claude/agents/standards-reviewer.md +31 -0
- package/templates/claude/commands/open-pr.md +21 -0
- package/templates/claude/commands/verify.md +16 -0
- package/templates/claude/hooks/protect-branch.mjs +58 -0
- package/templates/claude/hooks/protect-files.mjs +35 -0
- package/templates/claude/settings.json +71 -0
- package/templates/claude/skills/maintainable-software/SKILL.md +67 -0
- package/templates/claude/skills/reviewing-to-standard/SKILL.md +49 -0
- package/templates/claude/skills/working-to-standard/SKILL.md +45 -0
- package/templates/delivery/verify.mjs +157 -0
- package/templates/doctor/resolve.mjs +144 -0
- package/templates/guards/README.md +30 -0
- package/templates/guards/_kit.mjs +81 -0
- package/templates/guards/actions-pinned.mjs +38 -0
- package/templates/guards/run.mjs +111 -0
- package/templates/guards/watchtower-locked.mjs +66 -0
- package/templates/prompts/address-review.md +14 -0
- package/templates/prompts/architect.md +62 -0
- package/templates/prompts/builder.md +71 -0
- package/templates/prompts/doctor.md +64 -0
- package/templates/prompts/review.md +14 -0
- package/templates/prompts/sweep.md +75 -0
- package/templates/receipts/collect.mjs +289 -0
- package/templates/review/finalize.mjs +38 -0
- package/templates/scripts/move-board-status.sh +155 -0
- package/templates/security/sync-findings.mjs +226 -0
- package/templates/standard/STANDARD.md +141 -0
- package/templates/standard/agents-block.md +25 -0
- package/templates/watchtower/budgets.json +12 -0
- package/templates/watchtower/canary.mjs +216 -0
- package/templates/watchtower/health.mjs +148 -0
- package/templates/watchtower/outcomes.mjs +188 -0
- package/templates/workflows/facility-address-review.yml +153 -0
- package/templates/workflows/facility-canary.yml +61 -0
- package/templates/workflows/facility-codex.yml +326 -0
- package/templates/workflows/facility-crew.yml +350 -0
- package/templates/workflows/facility-doctor.yml +155 -0
- package/templates/workflows/facility-review.yml +134 -0
- package/templates/workflows/facility-security-sweep.yml +204 -0
- 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)
|
package/bin/facility.mjs
ADDED
|
@@ -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
|
+
}
|