@fro.bot/systematic 2.2.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,222 @@
1
+ # Documentation schema for learnings written by ce:compound
2
+ # Treat this as the canonical frontmatter contract for docs/solutions/.
3
+ #
4
+ # The schema has two tracks based on problem_type:
5
+ # Bug track — problem_type is a defect or failure (build_error, test_failure, etc.)
6
+ # Knowledge track — problem_type is guidance or practice (best_practice, workflow_issue, etc.)
7
+ #
8
+ # Both tracks share the same required core fields. The tracks differ in which
9
+ # additional fields are required vs optional (see track_rules below).
10
+
11
+ # --- Track classification ---------------------------------------------------
12
+ tracks:
13
+ bug:
14
+ description: "Defects, failures, and errors that were diagnosed and fixed"
15
+ problem_types:
16
+ - build_error
17
+ - test_failure
18
+ - runtime_error
19
+ - performance_issue
20
+ - database_issue
21
+ - security_issue
22
+ - ui_bug
23
+ - integration_issue
24
+ - logic_error
25
+ knowledge:
26
+ description: "Best practices, workflow improvements, patterns, and documentation"
27
+ problem_types:
28
+ - best_practice
29
+ - documentation_gap
30
+ - workflow_issue
31
+ - developer_experience
32
+
33
+ # --- Fields required by BOTH tracks -----------------------------------------
34
+ required_fields:
35
+ module:
36
+ type: string
37
+ description: "Module or area affected"
38
+
39
+ date:
40
+ type: string
41
+ pattern: '^\d{4}-\d{2}-\d{2}$'
42
+ description: "Date documented (YYYY-MM-DD)"
43
+
44
+ problem_type:
45
+ type: enum
46
+ values:
47
+ - build_error
48
+ - test_failure
49
+ - runtime_error
50
+ - performance_issue
51
+ - database_issue
52
+ - security_issue
53
+ - ui_bug
54
+ - integration_issue
55
+ - logic_error
56
+ - developer_experience
57
+ - workflow_issue
58
+ - best_practice
59
+ - documentation_gap
60
+ description: "Primary category — determines track (bug vs knowledge)"
61
+
62
+ component:
63
+ type: enum
64
+ values:
65
+ - rails_model
66
+ - rails_controller
67
+ - rails_view
68
+ - service_object
69
+ - background_job
70
+ - database
71
+ - frontend_stimulus
72
+ - hotwire_turbo
73
+ - email_processing
74
+ - brief_system
75
+ - assistant
76
+ - authentication
77
+ - payments
78
+ - development_workflow
79
+ - testing_framework
80
+ - documentation
81
+ - tooling
82
+ description: "Component involved"
83
+
84
+ severity:
85
+ type: enum
86
+ values:
87
+ - critical
88
+ - high
89
+ - medium
90
+ - low
91
+ description: "Impact severity"
92
+
93
+ # --- Track-specific rules ----------------------------------------------------
94
+ track_rules:
95
+ bug:
96
+ required:
97
+ symptoms:
98
+ type: array[string]
99
+ min_items: 1
100
+ max_items: 5
101
+ description: "Observable symptoms such as errors or broken behavior"
102
+ root_cause:
103
+ type: enum
104
+ values:
105
+ - missing_association
106
+ - missing_include
107
+ - missing_index
108
+ - wrong_api
109
+ - scope_issue
110
+ - thread_violation
111
+ - async_timing
112
+ - memory_leak
113
+ - config_error
114
+ - logic_error
115
+ - test_isolation
116
+ - missing_validation
117
+ - missing_permission
118
+ - missing_workflow_step
119
+ - inadequate_documentation
120
+ - missing_tooling
121
+ - incomplete_setup
122
+ description: "Fundamental technical cause of the problem"
123
+ resolution_type:
124
+ type: enum
125
+ values:
126
+ - code_fix
127
+ - migration
128
+ - config_change
129
+ - test_fix
130
+ - dependency_update
131
+ - environment_setup
132
+ - workflow_improvement
133
+ - documentation_update
134
+ - tooling_addition
135
+ - seed_data_update
136
+ description: "Type of fix applied"
137
+
138
+ knowledge:
139
+ optional:
140
+ applies_when:
141
+ type: array[string]
142
+ max_items: 5
143
+ description: "Conditions or situations where this guidance applies"
144
+ symptoms:
145
+ type: array[string]
146
+ max_items: 5
147
+ description: "Observable gaps or friction that prompted this guidance (optional for knowledge track)"
148
+ root_cause:
149
+ type: enum
150
+ values:
151
+ - missing_association
152
+ - missing_include
153
+ - missing_index
154
+ - wrong_api
155
+ - scope_issue
156
+ - thread_violation
157
+ - async_timing
158
+ - memory_leak
159
+ - config_error
160
+ - logic_error
161
+ - test_isolation
162
+ - missing_validation
163
+ - missing_permission
164
+ - missing_workflow_step
165
+ - inadequate_documentation
166
+ - missing_tooling
167
+ - incomplete_setup
168
+ description: "Underlying cause, if there is a specific one (optional for knowledge track)"
169
+ resolution_type:
170
+ type: enum
171
+ values:
172
+ - code_fix
173
+ - migration
174
+ - config_change
175
+ - test_fix
176
+ - dependency_update
177
+ - environment_setup
178
+ - workflow_improvement
179
+ - documentation_update
180
+ - tooling_addition
181
+ - seed_data_update
182
+ description: "Type of change, if applicable (optional for knowledge track)"
183
+
184
+ # --- Fields optional for BOTH tracks ----------------------------------------
185
+ optional_fields:
186
+ related_components:
187
+ type: array[string]
188
+ description: "Other components involved"
189
+
190
+ tags:
191
+ type: array[string]
192
+ max_items: 8
193
+ description: "Search keywords, lowercase and hyphen-separated"
194
+
195
+ # --- Fields optional for bug track only -------------------------------------
196
+ bug_optional_fields:
197
+ rails_version:
198
+ type: string
199
+ pattern: '^\d+\.\d+\.\d+$'
200
+ description: "Rails version in X.Y.Z format. Only relevant for bug-track docs."
201
+
202
+ # --- Backward compatibility --------------------------------------------------
203
+ # Docs created before the track system was introduced may have bug-track
204
+ # fields (symptoms, root_cause, resolution_type) on knowledge-type
205
+ # problem_types. These are valid legacy docs:
206
+ # - Bug-track fields present on a knowledge-track doc are harmless. Do not
207
+ # strip them during refresh unless the doc is being rewritten for other reasons.
208
+ # - When creating NEW docs, follow the track rules above.
209
+
210
+ # --- Validation rules --------------------------------------------------------
211
+ validation_rules:
212
+ - "Determine track from problem_type using the tracks section above"
213
+ - "All shared required_fields must be present"
214
+ - "Bug-track required fields (symptoms, root_cause, resolution_type) must be present on bug-track docs"
215
+ - "Knowledge-track docs have no additional required fields beyond the shared ones"
216
+ - "Bug-track fields on existing knowledge-track docs are harmless (see backward compatibility note)"
217
+ - "Track-specific optional fields may be included but are not required"
218
+ - "Enum fields must match allowed values exactly"
219
+ - "Array fields must respect min_items/max_items when specified"
220
+ - "date must match YYYY-MM-DD format"
221
+ - "rails_version, if provided, must match X.Y.Z format and only applies to bug-track docs"
222
+ - "tags should be lowercase and hyphen-separated"
@@ -0,0 +1,87 @@
1
+ # YAML Frontmatter Schema
2
+
3
+ `schema.yaml` in this directory is the canonical contract for `docs/solutions/` frontmatter written by `ce:compound`.
4
+
5
+ Use this file as the quick reference for:
6
+ - required fields
7
+ - enum values
8
+ - validation expectations
9
+ - category mapping
10
+ - track classification (bug vs knowledge)
11
+
12
+ ## Tracks
13
+
14
+ The `problem_type` determines which **track** applies. Each track has different required and optional fields.
15
+
16
+ | Track | problem_types | Description |
17
+ |-------|--------------|-------------|
18
+ | **Bug** | `build_error`, `test_failure`, `runtime_error`, `performance_issue`, `database_issue`, `security_issue`, `ui_bug`, `integration_issue`, `logic_error` | Defects and failures that were diagnosed and fixed |
19
+ | **Knowledge** | `best_practice`, `documentation_gap`, `workflow_issue`, `developer_experience` | Practices, patterns, workflow improvements, and documentation |
20
+
21
+ ## Required Fields (both tracks)
22
+
23
+ - **module**: Module or area affected
24
+ - **date**: ISO date in `YYYY-MM-DD`
25
+ - **problem_type**: One of the values listed in the Tracks table above
26
+ - **component**: One of `rails_model`, `rails_controller`, `rails_view`, `service_object`, `background_job`, `database`, `frontend_stimulus`, `hotwire_turbo`, `email_processing`, `brief_system`, `assistant`, `authentication`, `payments`, `development_workflow`, `testing_framework`, `documentation`, `tooling`
27
+ - **severity**: One of `critical`, `high`, `medium`, `low`
28
+
29
+ ## Bug Track Fields
30
+
31
+ Required:
32
+ - **symptoms**: YAML array with 1-5 observable symptoms (errors, broken behavior)
33
+ - **root_cause**: One of `missing_association`, `missing_include`, `missing_index`, `wrong_api`, `scope_issue`, `thread_violation`, `async_timing`, `memory_leak`, `config_error`, `logic_error`, `test_isolation`, `missing_validation`, `missing_permission`, `missing_workflow_step`, `inadequate_documentation`, `missing_tooling`, `incomplete_setup`
34
+ - **resolution_type**: One of `code_fix`, `migration`, `config_change`, `test_fix`, `dependency_update`, `environment_setup`, `workflow_improvement`, `documentation_update`, `tooling_addition`, `seed_data_update`
35
+
36
+ ## Knowledge Track Fields
37
+
38
+ No additional required fields beyond the shared ones. All fields below are optional:
39
+
40
+ - **applies_when**: Conditions or situations where this guidance applies
41
+ - **symptoms**: Observable gaps or friction that prompted this guidance
42
+ - **root_cause**: Underlying cause, if there is a specific one
43
+ - **resolution_type**: Type of change, if applicable
44
+
45
+ ## Optional Fields (both tracks)
46
+
47
+ - **related_components**: Other components involved
48
+ - **tags**: Search keywords, lowercase and hyphen-separated
49
+
50
+ ## Optional Fields (bug track only)
51
+
52
+ - **rails_version**: Rails version in `X.Y.Z` format
53
+
54
+ ## Backward Compatibility
55
+
56
+ Docs created before the track system may have `symptoms`/`root_cause`/`resolution_type` on knowledge-type problem_types. These are valid legacy docs:
57
+
58
+ - Bug-track fields present on a knowledge-track doc are harmless. Do not strip them during refresh unless the doc is being rewritten for other reasons.
59
+ - When creating **new** docs, follow the track rules above.
60
+
61
+ ## Category Mapping
62
+
63
+ - `build_error` -> `docs/solutions/build-errors/`
64
+ - `test_failure` -> `docs/solutions/test-failures/`
65
+ - `runtime_error` -> `docs/solutions/runtime-errors/`
66
+ - `performance_issue` -> `docs/solutions/performance-issues/`
67
+ - `database_issue` -> `docs/solutions/database-issues/`
68
+ - `security_issue` -> `docs/solutions/security-issues/`
69
+ - `ui_bug` -> `docs/solutions/ui-bugs/`
70
+ - `integration_issue` -> `docs/solutions/integration-issues/`
71
+ - `logic_error` -> `docs/solutions/logic-errors/`
72
+ - `developer_experience` -> `docs/solutions/developer-experience/`
73
+ - `workflow_issue` -> `docs/solutions/workflow-issues/`
74
+ - `best_practice` -> `docs/solutions/best-practices/`
75
+ - `documentation_gap` -> `docs/solutions/documentation-gaps/`
76
+
77
+ ## Validation Rules
78
+
79
+ 1. Determine the track from `problem_type` using the Tracks table.
80
+ 2. All shared required fields must be present.
81
+ 3. Bug-track required fields (`symptoms`, `root_cause`, `resolution_type`) must be present on bug-track docs.
82
+ 4. Knowledge-track docs have no additional required fields beyond the shared ones.
83
+ 5. Bug-track fields on existing knowledge-track docs are harmless (see Backward Compatibility).
84
+ 6. Enum fields must match the allowed values exactly.
85
+ 7. Array fields must respect min/max item counts.
86
+ 8. `date` must match `YYYY-MM-DD`.
87
+ 9. `rails_version`, if present, must match `X.Y.Z` and only applies to bug-track docs.
@@ -0,0 +1,31 @@
1
+ # Diff Scope Rules
2
+
3
+ These rules apply to every reviewer. They define what is "your code to review" versus pre-existing context.
4
+
5
+ ## Scope Discovery
6
+
7
+ Determine the diff to review using this priority order:
8
+
9
+ 1. **User-specified scope.** If the caller passed `BASE:`, `FILES:`, or `DIFF:` markers, use that scope exactly.
10
+ 2. **Working copy changes.** If there are unstaged or staged changes (`git diff HEAD` is non-empty), review those.
11
+ 3. **Unpushed commits vs base branch.** If the working copy is clean, review `git diff $(git merge-base HEAD <base>)..HEAD` where `<base>` is the default branch (main or master).
12
+
13
+ The scope step in the SKILL.md handles discovery and passes you the resolved diff. You do not need to run git commands yourself.
14
+
15
+ ## Finding Classification Tiers
16
+
17
+ Every finding you report falls into one of three tiers based on its relationship to the diff:
18
+
19
+ ### Primary (directly changed code)
20
+
21
+ Lines added or modified in the diff. This is your main focus. Report findings against these lines at full confidence.
22
+
23
+ ### Secondary (immediately surrounding code)
24
+
25
+ Unchanged code within the same function, method, or block as a changed line. If a change introduces a bug that's only visible by reading the surrounding context, report it -- but note that the issue exists in the interaction between new and existing code.
26
+
27
+ ### Pre-existing (unrelated to this diff)
28
+
29
+ Issues in unchanged code that the diff didn't touch and doesn't interact with. Mark these as `"pre_existing": true` in your output. They're reported separately and don't count toward the review verdict.
30
+
31
+ **The rule:** If you'd flag the same issue on an identical diff that didn't include the surrounding file, it's pre-existing. If the diff makes the issue *newly relevant* (e.g., a new caller hits an existing buggy function), it's secondary.
@@ -0,0 +1,129 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Code Review Findings",
4
+ "description": "Structured output schema for code review sub-agents",
5
+ "type": "object",
6
+ "required": ["reviewer", "findings", "residual_risks", "testing_gaps"],
7
+ "properties": {
8
+ "reviewer": {
9
+ "type": "string",
10
+ "description": "Persona name that produced this output (e.g., 'correctness', 'security')"
11
+ },
12
+ "findings": {
13
+ "type": "array",
14
+ "description": "List of code review findings. Empty array if no issues found.",
15
+ "items": {
16
+ "type": "object",
17
+ "required": [
18
+ "title",
19
+ "severity",
20
+ "file",
21
+ "line",
22
+ "why_it_matters",
23
+ "autofix_class",
24
+ "owner",
25
+ "requires_verification",
26
+ "confidence",
27
+ "evidence",
28
+ "pre_existing"
29
+ ],
30
+ "properties": {
31
+ "title": {
32
+ "type": "string",
33
+ "description": "Short, specific issue title. 10 words or fewer.",
34
+ "maxLength": 100
35
+ },
36
+ "severity": {
37
+ "type": "string",
38
+ "enum": ["P0", "P1", "P2", "P3"],
39
+ "description": "Issue severity level"
40
+ },
41
+ "file": {
42
+ "type": "string",
43
+ "description": "Relative file path from repository root"
44
+ },
45
+ "line": {
46
+ "type": "integer",
47
+ "description": "Primary line number of the issue",
48
+ "minimum": 1
49
+ },
50
+ "why_it_matters": {
51
+ "type": "string",
52
+ "description": "Impact and failure mode -- not 'what is wrong' but 'what breaks'"
53
+ },
54
+ "autofix_class": {
55
+ "type": "string",
56
+ "enum": ["safe_auto", "gated_auto", "manual", "advisory"],
57
+ "description": "Reviewer's conservative recommendation for how this issue should be handled after synthesis"
58
+ },
59
+ "owner": {
60
+ "type": "string",
61
+ "enum": ["review-fixer", "downstream-resolver", "human", "release"],
62
+ "description": "Who should own the next action for this finding after synthesis"
63
+ },
64
+ "requires_verification": {
65
+ "type": "boolean",
66
+ "description": "Whether any fix for this finding must be re-verified with targeted tests or a follow-up review pass"
67
+ },
68
+ "suggested_fix": {
69
+ "type": ["string", "null"],
70
+ "description": "Concrete minimal fix. Omit or null if no good fix is obvious -- a bad suggestion is worse than none."
71
+ },
72
+ "confidence": {
73
+ "type": "number",
74
+ "description": "Reviewer confidence in this finding, calibrated per persona",
75
+ "minimum": 0.0,
76
+ "maximum": 1.0
77
+ },
78
+ "evidence": {
79
+ "type": "array",
80
+ "description": "Code-grounded evidence: snippets, line references, or pattern descriptions. At least 1 item.",
81
+ "items": { "type": "string" },
82
+ "minItems": 1
83
+ },
84
+ "pre_existing": {
85
+ "type": "boolean",
86
+ "description": "True if this issue exists in unchanged code unrelated to the current diff"
87
+ }
88
+ }
89
+ }
90
+ },
91
+ "residual_risks": {
92
+ "type": "array",
93
+ "description": "Risks the reviewer noticed but could not confirm as findings",
94
+ "items": { "type": "string" }
95
+ },
96
+ "testing_gaps": {
97
+ "type": "array",
98
+ "description": "Missing test coverage the reviewer identified",
99
+ "items": { "type": "string" }
100
+ }
101
+ },
102
+
103
+ "_meta": {
104
+ "confidence_thresholds": {
105
+ "suppress": "Below 0.60 -- do not report. Finding is speculative noise. Exception: P0 findings at 0.50+ may be reported.",
106
+ "flag": "0.60-0.69 -- include only when the issue is clearly actionable with concrete evidence.",
107
+ "confident": "0.70-0.84 -- real and important. Report with full evidence.",
108
+ "certain": "0.85-1.00 -- verifiable from the code alone. Report."
109
+ },
110
+ "severity_definitions": {
111
+ "P0": "Critical breakage, exploitable vulnerability, data loss/corruption. Must fix before merge.",
112
+ "P1": "High-impact defect likely hit in normal usage, breaking contract. Should fix.",
113
+ "P2": "Moderate issue with meaningful downside (edge case, perf regression, maintainability trap). Fix if straightforward.",
114
+ "P3": "Low-impact, narrow scope, minor improvement. User's discretion."
115
+ },
116
+ "autofix_classes": {
117
+ "safe_auto": "Local, deterministic code or test fix suitable for the in-skill fixer. Examples: extract duplicated helper, add missing nil check, fix off-by-one, add missing test, remove dead code. Do not default to advisory when a concrete safe fix exists.",
118
+ "gated_auto": "Concrete fix exists, but it changes behavior, permissions, contracts, or other sensitive areas that deserve explicit approval. Examples: add auth to unprotected endpoint, change API response shape.",
119
+ "manual": "Actionable issue that requires design decisions or cross-cutting changes. Examples: redesign data model, add pagination strategy, choose between architectural approaches.",
120
+ "advisory": "Informational or operational item that should be surfaced in the report only. Examples: design asymmetry the PR improves but does not fully resolve, residual risk notes, deployment considerations."
121
+ },
122
+ "owners": {
123
+ "review-fixer": "The in-skill fixer can own this when policy allows.",
124
+ "downstream-resolver": "Turn this into residual work for later resolution.",
125
+ "human": "A person must make a judgment call before code changes should continue.",
126
+ "release": "Operational or rollout follow-up; do not convert into code-fix work automatically."
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,67 @@
1
+ # Persona Catalog
2
+
3
+ 17 reviewer personas organized into always-on, cross-cutting conditional, and stack-specific conditional layers, plus CE-specific agents. The orchestrator uses this catalog to select which reviewers to spawn for each review.
4
+
5
+ ## Always-on (4 personas + 2 CE agents)
6
+
7
+ Spawned on every review regardless of diff content.
8
+
9
+ **Persona agents (structured JSON output):**
10
+
11
+ | Persona | Agent | Focus |
12
+ |---------|-------|-------|
13
+ | `correctness` | `systematic:review:correctness-reviewer` | Logic errors, edge cases, state bugs, error propagation, intent compliance |
14
+ | `testing` | `systematic:review:testing-reviewer` | Coverage gaps, weak assertions, brittle tests, missing edge case tests |
15
+ | `maintainability` | `systematic:review:maintainability-reviewer` | Coupling, complexity, naming, dead code, premature abstraction |
16
+ | `project-standards` | `systematic:review:project-standards-reviewer` | AGENTS.md and AGENTS.md compliance -- frontmatter, references, naming, cross-platform portability, tool selection |
17
+
18
+ **CE agents (unstructured output, synthesized separately):**
19
+
20
+ | Agent | Focus |
21
+ |-------|-------|
22
+ | `systematic:review:agent-native-reviewer` | Verify new features are agent-accessible |
23
+ | `systematic:research:learnings-researcher` | Search docs/solutions/ for past issues related to this PR's modules and patterns |
24
+
25
+ ## Conditional (8 personas)
26
+
27
+ Spawned when the orchestrator identifies relevant patterns in the diff. The orchestrator reads the full diff and reasons about selection -- this is agent judgment, not keyword matching.
28
+
29
+ | Persona | Agent | Select when diff touches... |
30
+ |---------|-------|---------------------------|
31
+ | `security` | `systematic:review:security-reviewer` | Auth middleware, public endpoints, user input handling, permission checks, secrets management |
32
+ | `performance` | `systematic:review:performance-reviewer` | Database queries, ORM calls, loop-heavy data transforms, caching layers, async/concurrent code |
33
+ | `api-contract` | `systematic:review:api-contract-reviewer` | Route definitions, serializer/interface changes, event schemas, exported type signatures, API versioning |
34
+ | `data-migrations` | `systematic:review:data-migrations-reviewer` | Migration files, schema changes, backfill scripts, data transformations |
35
+ | `reliability` | `systematic:review:reliability-reviewer` | Error handling, retry logic, circuit breakers, timeouts, background jobs, async handlers, health checks |
36
+ | `adversarial` | `systematic:review:adversarial-reviewer` | Diff has >=50 changed non-test, non-generated, non-lockfile lines, OR touches auth, payments, data mutations, external API integrations, or other high-risk domains |
37
+ | `cli-readiness` | `systematic:review:cli-readiness-reviewer` | CLI command definitions, argument parsing, CLI framework usage, command handler implementations |
38
+ | `previous-comments` | `systematic:review:previous-comments-reviewer` | **PR-only.** Reviewing a PR that has existing review comments or review threads from prior review rounds. Skip entirely when no PR metadata was gathered in Stage 1. |
39
+
40
+ ## Stack-Specific Conditional (5 personas)
41
+
42
+ These reviewers keep their original opinionated lens. They are additive with the cross-cutting personas above, not replacements for them.
43
+
44
+ | Persona | Agent | Select when diff touches... |
45
+ |---------|-------|---------------------------|
46
+ | `dhh-rails` | `systematic:review:dhh-rails-reviewer` | Rails architecture, service objects, authentication/session choices, Hotwire-vs-SPA boundaries, or abstractions that may fight Rails conventions |
47
+ | `kieran-rails` | `systematic:review:kieran-rails-reviewer` | Rails controllers, models, views, jobs, components, routes, or other application-layer Ruby code where clarity and conventions matter |
48
+ | `kieran-python` | `systematic:review:kieran-python-reviewer` | Python modules, endpoints, services, scripts, or typed domain code |
49
+ | `kieran-typescript` | `systematic:review:kieran-typescript-reviewer` | TypeScript components, services, hooks, utilities, or shared types |
50
+ | `julik-frontend-races` | `systematic:review:julik-frontend-races-reviewer` | Stimulus/Turbo controllers, DOM event wiring, timers, async UI flows, animations, or frontend state transitions with race potential |
51
+
52
+ ## CE Conditional Agents (migration-specific)
53
+
54
+ These CE-native agents provide specialized analysis beyond what the persona agents cover. Spawn them when the diff includes database migrations, schema.rb, or data backfills.
55
+
56
+ | Agent | Focus |
57
+ |-------|-------|
58
+ | `systematic:review:schema-drift-detector` | Cross-references schema.rb changes against included migrations to catch unrelated drift |
59
+ | `systematic:review:deployment-verification-agent` | Produces Go/No-Go deployment checklist with SQL verification queries and rollback procedures |
60
+
61
+ ## Selection rules
62
+
63
+ 1. **Always spawn all 4 always-on personas** plus the 2 CE always-on agents.
64
+ 2. **For each cross-cutting conditional persona**, the orchestrator reads the diff and decides whether the persona's domain is relevant. This is a judgment call, not a keyword match.
65
+ 3. **For each stack-specific conditional persona**, use file types and changed patterns as a starting point, then decide whether the diff actually introduces meaningful work for that reviewer. Do not spawn language-specific reviewers just because one config or generated file happens to match the extension.
66
+ 4. **For CE conditional agents**, spawn when the diff includes migration files (`db/migrate/*.rb`, `db/schema.rb`) or data backfill scripts.
67
+ 5. **Announce the team** before spawning with a one-line justification per conditional reviewer selected.
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env bash
2
+ # Resolve the review base branch and compute the merge-base for ce:review.
3
+ # Handles fork-safe remote resolution, PR metadata, and multi-fallback detection.
4
+ #
5
+ # Usage: bash references/resolve-base.sh
6
+ # Output: BASE:<sha> on success, ERROR:<message> on failure.
7
+ #
8
+ # Detects the base branch from (in priority order):
9
+ # 1. PR metadata (base ref + base repo for fork safety)
10
+ # 2. origin/HEAD symbolic ref
11
+ # 3. gh repo view defaultBranchRef
12
+ # 4. Common branch names: main, master, develop, trunk
13
+
14
+ set -euo pipefail
15
+
16
+ REVIEW_BASE_BRANCH=""
17
+ PR_BASE_REPO=""
18
+ PR_BASE_REMOTE=""
19
+ BASE_REF=""
20
+
21
+ # Step 1: Try PR metadata (handles fork workflows)
22
+ if command -v gh >/dev/null 2>&1; then
23
+ PR_META=$(gh pr view --json baseRefName,url 2>/dev/null || true)
24
+ if [ -n "$PR_META" ]; then
25
+ REVIEW_BASE_BRANCH=$(echo "$PR_META" | jq -r '.baseRefName // empty' 2>/dev/null || true)
26
+ PR_BASE_REPO=$(echo "$PR_META" | jq -r '.url // empty' 2>/dev/null | sed -n 's#https://github.com/\([^/]*/[^/]*\)/pull/.*#\1#p' || true)
27
+ fi
28
+ fi
29
+
30
+ # Step 2: Fall back to origin/HEAD
31
+ if [ -z "$REVIEW_BASE_BRANCH" ]; then
32
+ REVIEW_BASE_BRANCH=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's#^origin/##' || true)
33
+ fi
34
+
35
+ # Step 3: Fall back to gh repo view
36
+ if [ -z "$REVIEW_BASE_BRANCH" ] && command -v gh >/dev/null 2>&1; then
37
+ REVIEW_BASE_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' 2>/dev/null || true)
38
+ fi
39
+
40
+ # Step 4: Fall back to common branch names
41
+ if [ -z "$REVIEW_BASE_BRANCH" ]; then
42
+ for candidate in main master develop trunk; do
43
+ if git rev-parse --verify "origin/$candidate" >/dev/null 2>&1 || git rev-parse --verify "$candidate" >/dev/null 2>&1; then
44
+ REVIEW_BASE_BRANCH="$candidate"
45
+ break
46
+ fi
47
+ done
48
+ fi
49
+
50
+ # Resolve the base ref from the correct remote (fork-safe)
51
+ if [ -n "$REVIEW_BASE_BRANCH" ]; then
52
+ if [ -n "$PR_BASE_REPO" ]; then
53
+ PR_BASE_REMOTE=$(git remote -v | awk "index(\$2, \"github.com:$PR_BASE_REPO\") || index(\$2, \"github.com/$PR_BASE_REPO\") {print \$1; exit}")
54
+ if [ -n "$PR_BASE_REMOTE" ]; then
55
+ git rev-parse --verify "$PR_BASE_REMOTE/$REVIEW_BASE_BRANCH" >/dev/null 2>&1 || git fetch --no-tags "$PR_BASE_REMOTE" "$REVIEW_BASE_BRANCH:refs/remotes/$PR_BASE_REMOTE/$REVIEW_BASE_BRANCH" 2>/dev/null || git fetch --no-tags "$PR_BASE_REMOTE" "$REVIEW_BASE_BRANCH" 2>/dev/null || true
56
+ BASE_REF=$(git rev-parse --verify "$PR_BASE_REMOTE/$REVIEW_BASE_BRANCH" 2>/dev/null || true)
57
+ fi
58
+ fi
59
+ if [ -z "$BASE_REF" ]; then
60
+ # Only try origin if it exists as a remote; otherwise skip to avoid
61
+ # confusing errors in fork setups where origin points at the user's fork.
62
+ if git remote get-url origin >/dev/null 2>&1; then
63
+ git rev-parse --verify "origin/$REVIEW_BASE_BRANCH" >/dev/null 2>&1 || git fetch --no-tags origin "$REVIEW_BASE_BRANCH:refs/remotes/origin/$REVIEW_BASE_BRANCH" 2>/dev/null || git fetch --no-tags origin "$REVIEW_BASE_BRANCH" 2>/dev/null || true
64
+ BASE_REF=$(git rev-parse --verify "origin/$REVIEW_BASE_BRANCH" 2>/dev/null || true)
65
+ fi
66
+ # Fall back to a bare local ref only if remote resolution failed
67
+ if [ -z "$BASE_REF" ]; then
68
+ BASE_REF=$(git rev-parse --verify "$REVIEW_BASE_BRANCH" 2>/dev/null || true)
69
+ fi
70
+ fi
71
+ fi
72
+
73
+ # Compute merge-base
74
+ if [ -n "$BASE_REF" ]; then
75
+ BASE=$(git merge-base HEAD "$BASE_REF" 2>/dev/null) || BASE=""
76
+ if [ -z "$BASE" ] && [ "$(git rev-parse --is-shallow-repository 2>/dev/null || echo false)" = "true" ]; then
77
+ if git remote get-url origin >/dev/null 2>&1; then
78
+ git fetch --no-tags --unshallow origin 2>/dev/null || true
79
+ BASE=$(git merge-base HEAD "$BASE_REF" 2>/dev/null) || BASE=""
80
+ fi
81
+ if [ -z "$BASE" ] && [ -n "$PR_BASE_REMOTE" ] && [ "$PR_BASE_REMOTE" != "origin" ]; then
82
+ git fetch --no-tags --unshallow "$PR_BASE_REMOTE" 2>/dev/null || true
83
+ BASE=$(git merge-base HEAD "$BASE_REF" 2>/dev/null) || BASE=""
84
+ fi
85
+ fi
86
+ else
87
+ BASE=""
88
+ fi
89
+
90
+ if [ -n "$BASE" ]; then
91
+ echo "BASE:$BASE"
92
+ else
93
+ echo "ERROR:Unable to resolve review base branch locally. Fetch the base branch and rerun, or provide a PR number so the review scope can be determined from PR metadata."
94
+ fi