@mrciphersmith/keryx 0.3.118 → 0.3.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +104554 -96795
- package/dist/core.js +1767 -1061
- package/package.json +1 -1
- package/src/gdgraph/service.ts +4 -0
- package/src/gdgraph/symbol-reach.ts +1069 -0
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/SKILL.md +37 -40
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +6 -6
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/orchestrator-prompt.md +1 -1
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.md +12 -18
- package/src/gdskills/bundled/skills/orchestration/task-implementer/input-contract.schema.json +8 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/output-contract.schema.json +19 -0
- package/src/gdskills/bundled/skills/platform/scheduled-tasks/SKILL.md +2 -2
- package/src/gdskills/bundled/skills/review/review-architecture/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-backend/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-clean-code/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-core-boundaries/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-flow-graph/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-frontend/SKILL.md +3 -7
- package/src/gdskills/bundled/skills/review/review-frontend-conventions/SKILL.md +4 -6
- package/src/gdskills/bundled/skills/review/review-highload/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-logic/SKILL.md +2 -2
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.detail.md +82 -17
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +78 -111
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-finding.schema.json +13 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-input.schema.json +38 -0
- package/src/gdskills/bundled/skills/review/review-performance/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-pr-feedback/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-regression/SKILL.md +2 -2
- package/src/gdskills/bundled/skills/review/review-security-code/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-style/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-testing-practices/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-verifier/SKILL.md +3 -3
- package/src/gdskills/contracts/review-finding.schema.json +25 -0
|
@@ -173,8 +173,8 @@ When one is absent:
|
|
|
173
173
|
|
|
174
174
|
- **A legacy reviewer a flag asked for** is not dispatched and not replaced.
|
|
175
175
|
Record it in `Skipped reviewers` with reason `not-installed` and the command
|
|
176
|
-
below. `--legacy-profiles`
|
|
177
|
-
installed and
|
|
176
|
+
below. `--legacy-profiles` dispatches the legacy reviewers that are
|
|
177
|
+
installed and records the others the same way; `--all` never selects them. Leave an absent reviewer out of
|
|
178
178
|
the `Optional legacy/profile reviewers` preview: offering a flag that cannot
|
|
179
179
|
run is worse than not offering it.
|
|
180
180
|
- **`review-pr-feedback`** changes nothing about a round. No caller can declare
|
|
@@ -383,7 +383,7 @@ A review must be reproducible from its package: the same inputs give the same co
|
|
|
383
383
|
|
|
384
384
|
**One memory read, and the log.** The stage query is `keryx memory search "<changed modules and the concepts they touch>" --status accepted`, once. Pass the same text to `keryx review start … --memory-query "<query>"` so the manifest's `cleanContext` block holds it next to the start time. keryx writes the orchestrator log, `<package>/tool-calls/orchestrator.jsonl`, on its own: `keryx review start` and `keryx review attach` mark the package active, and every `keryx memory` command and every MCP memory tool (`memory_search`, `memory_handoff`, `memory_propose`) appends one line naming its caller. You do not write that file and must not edit it; a hand-written line is a forgery the readiness item cannot tell apart from a record. A call by a `spawn_subagent` child is recorded under the child's reviewer id and is not judged by item 10. A call from a host that names no caller is recorded as `unattributed`: it warns in the item's detail line and never blocks. Reviewer logs stay in their own files.
|
|
385
385
|
|
|
386
|
-
Item 10, `memory-outside-stage`, reads that log. Outside the stage is: a memory search with a different query, a search without `--status accepted`, any other memory command or MCP memory tool, and a stage call stamped before the round started. The same query repeated is the stage. Repair is to rerun from a session whose only memory read is the stage; only `keryx review complete <package> --waive memory-outside-stage "<operator quote>"`
|
|
386
|
+
Item 10, `memory-outside-stage`, reads that log. Outside the stage is: a memory search with a different query, a search without `--status accepted`, any other memory command or MCP memory tool, and a stage call stamped before the round started. The same query repeated is the stage. Repair is to rerun from a session whose only memory read is the stage; only the operator's waiver lifts it: in keryx shell call `review_waive_readiness` (the operator answers a card, never a terminal), then run `keryx review complete <package>`; outside keryx shell `keryx review complete <package> --waive memory-outside-stage "<operator quote>"` in a terminal; unattended, record Not run. With no orchestrator log the item passes and its evidence says it could not see your reads; with a log that holds no memory call it passes and says so. Outside keryx shell, `keryx review start` prints a caller token (`export KERYX_REVIEW_CALLER_TOKEN=…`): export it on this session's keryx calls so they are attributed to you; without it the item reads "not observable on this host" rather than a clean pass. Only calls that go through keryx are visible: a read through a tool keryx does not wrap is not in the log.
|
|
387
387
|
|
|
388
388
|
**Open questions.** One general rule, replacing per-fork wording: the answer is in this skill or `SKILL.detail.md`, or it is the user's. Interactive: one `AskUserQuestion`. Unattended: the whole output is one line, `STATUS: BLOCKED question — <the question>`, and you stop. A guess and a recollection are both wrong answers.
|
|
389
389
|
|
|
@@ -430,7 +430,7 @@ records them under `### How this review was run`.
|
|
|
430
430
|
```text
|
|
431
431
|
Context: <PR or branch>, <N> files / <N> lines, <domains>; risk: <class>
|
|
432
432
|
|
|
433
|
-
1) Reviewers A) --
|
|
433
|
+
1) Reviewers A) the `required --depth auto` set (default) B) --all C) tests only D) <domain> only E) choose
|
|
434
434
|
2) Counterpart found: <endpoints, rules, paired PR — or "no link found">
|
|
435
435
|
A) verify <backend|frontend> (default) B) skip — give a reason
|
|
436
436
|
3) Models complexity: <low|medium|high>; <role>: <tier> → <model>, …
|
|
@@ -462,10 +462,12 @@ flow (`flow-orchestrator` Phase 3), a pre-merge or pre-ship review, a
|
|
|
462
462
|
re-request after fixes. A gating round runs the composition the start questions
|
|
463
463
|
selected.
|
|
464
464
|
|
|
465
|
-
- **No dispatch tool, no review.** A host
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
465
|
+
- **No dispatch tool, no review.** A host with no spawn tool hands the round to
|
|
466
|
+
the autonomous runner (`keryx review run --autonomous --target pr --ref <pull
|
|
467
|
+
request URL>`, or `--target branch --ref <base> [--head <commit>]`), which
|
|
468
|
+
spawns the reviewers itself; a nested session whose depth budget is spent
|
|
469
|
+
returns `STATUS: BLOCKED` with reason `nested_dispatch_unavailable` and no
|
|
470
|
+
verdict. Neither reviews the diff alone and calls that a round. Measured (flow 405):
|
|
469
471
|
a single-agent round on a 150-line frontend PR wrote "did not dispatch any
|
|
470
472
|
sub-reviewers", approved it with two cosmetic minors, and the next human round
|
|
471
473
|
filed six real findings, every one reachable from the diff and the backend at
|
|
@@ -649,10 +651,10 @@ certifies the flow is the one that checked the least.
|
|
|
649
651
|
|
|
650
652
|
## Readiness — the checklist behind `completed` and behind publishing
|
|
651
653
|
|
|
652
|
-
`keryx review readiness <review-id-or-path> [--json]` reads the package and prints
|
|
654
|
+
`keryx review readiness <review-id-or-path> [--json]` reads the package and prints ten items, READY or NOT READY, each with the evidence and the command that repairs it. It writes nothing, and exits non-zero when the verdict is NOT READY. Only item 9 reaches GitHub (the PR's own file list); the TUI and `review status` read the package alone.
|
|
653
655
|
|
|
654
656
|
1. `files-covered` — every changed file is in a wave or carries a recorded waiver.
|
|
655
|
-
2. `blast-radius` — no file the blast radius cut is left unreviewed. A cut radius writes `chunks.json`; run `keryx review chunks plan`, `estimate`, `next`/`record`, `merge`. In an unattended run every wave runs without a question, up to the 25-pass ceiling; in an interactive run the operator is asked once.
|
|
657
|
+
2. `blast-radius` — no file the blast radius cut is left unreviewed. A cut radius writes `chunks.json`; run `keryx review chunks plan`, `estimate`, `next`/`record`, `merge`. In an unattended run every wave runs without a question, up to the 25-pass ceiling; in an interactive run the operator is asked once: in keryx shell call `review_chunks_answer` (a card, never a terminal); elsewhere the operator runs `keryx review chunks estimate --package <dir> --answer yes --quote "<their words>"` in their terminal; unattended, record Not run.
|
|
656
658
|
3. `reviewers` — every planned reviewer was dispatched and its result ingested.
|
|
657
659
|
4. `verifier` — the verifier checked every finding it should, or the report says how many it did not.
|
|
658
660
|
5. `ledger` — the ledger is READY.
|
|
@@ -660,8 +662,9 @@ certifies the flow is the one that checked the least.
|
|
|
660
662
|
7. `head` — the report's head is the PR head.
|
|
661
663
|
8. `report-names` — pending mutation candidates and parity warnings are named in the report.
|
|
662
664
|
9. `pr-files` — the changed-file count equals the PR's own file list. A recount more than 3x the recorded scope is refused: it came from the wrong base. Recount with `keryx review blast-radius --package <ref> --changed <the PR's files>`.
|
|
665
|
+
10. `memory-outside-stage` — the orchestrator read memory only in its memory stage ("Clean context" above). Outside keryx shell it reads "not observable on this host" unless this session's keryx calls carry the caller token `keryx review start` printed.
|
|
663
666
|
|
|
664
|
-
`keryx review complete` refuses status `completed` while any item fails. A failing item is waived only by the operator,
|
|
667
|
+
`keryx review complete` refuses status `completed` while any item fails. A failing item is waived only by the operator. In keryx shell call `review_waive_readiness` for the item: the operator answers it as a card, the waiver is recorded with the card text and the time, and then you run `keryx review complete`. Never send the operator to a terminal. Outside keryx shell the operator runs `keryx review complete --waive <item> "<their own words>"` in a terminal, repeatable. Unattended, record the item as Not run. `keryx review publish` is held by the same checklist. Publishing is the operator's decision too: in keryx shell call `review_publish` (a card shows the target and the body; never send the operator to a terminal). A not-ready package goes to GitHub only as a partial review (`review_publish` with `partial: true`, or `keryx review publish --partial`), which puts a "Partial review" header on the post and never approves. The shell guard stops a publish command that runs through the keryx shell; a publisher outside it (CI, another agent, a script file) is not stopped, and that limit is named, not hidden.
|
|
665
668
|
|
|
666
669
|
## Fix rounds — dispositions, regressions, withdrawal
|
|
667
670
|
|
|
@@ -684,6 +687,20 @@ sync as abandoned"* is a claim; the disposition is whether the branch it renamed
|
|
|
684
687
|
is reachable and pinned. On a recorded round, two such commits asserted behaviour
|
|
685
688
|
on lines no test could reach.
|
|
686
689
|
|
|
690
|
+
### Delta rounds — what `review start` hands you
|
|
691
|
+
|
|
692
|
+
`keryx review start` detects the round and writes `<package>/round.json` and `<package>/prior_findings.json`. It searches every source, because the earlier round may have run on another machine: the local package, git history (tracked package files), the PR's `keryx round` block, PR comments, and the flow's packages. `round.json` carries `round`, `source`, `sourcesTried`, `previous`, `mode`, `range`, `fixHunks`, `newHunks` and `carried`.
|
|
693
|
+
|
|
694
|
+
| `mode` | `range` | Review |
|
|
695
|
+
|---|---|---|
|
|
696
|
+
| `first` | merge-base..head | A first round. `sourcesTried` records what was searched when nothing was found. |
|
|
697
|
+
| `delta` | previous head..head | `fix` slices (a hunk that answers a prior finding): `review-logic`, `review-regression`, the authors of the attached findings and the verifier, each with its `prior_findings`. `new` slices: round 1, with the roles the slice names. Unchanged code: not re-reviewed. `carried` findings keep their dispositions. |
|
|
698
|
+
| `fallback-first` | merge-base..head | The previous head is not an ancestor (force-push, rebase). Review the whole range with the prior findings attached. |
|
|
699
|
+
|
|
700
|
+
A fix hunk still has a radius: enumerate what names the thing it changed (`review_context.scope.files`), as in any fix round. The attached findings are the contract: each leaves the round with a disposition, below.
|
|
701
|
+
|
|
702
|
+
A reviewer on a FIX slice reports those dispositions itself: its `REVIEW_RESULT` carries `prior_dispositions: [{id, disposition}]` with one entry for every attached finding id (`disposition` is `closed`, `open`, `partial`, `regressed` or `withdrawn`), judged against the code. `keryx review ingest` reads the array into the ledger; an attached id with no entry stays undisposed.
|
|
703
|
+
|
|
687
704
|
### A fix is a change, and changes get reviewed
|
|
688
705
|
|
|
689
706
|
The most expensive class in a multi-round review is **the defect the fix
|
|
@@ -756,9 +773,18 @@ and `.json`. A mutant is `killed` (the suite went red), `survived` (nothing pins
|
|
|
756
773
|
behaviour), `timeout`, or `invalid` (anchor missing or not unique, file outside the copy).
|
|
757
774
|
A survivor is evidence for the finding that names it.
|
|
758
775
|
|
|
759
|
-
`keryx review complete` refuses while proposed mutants are unrun, unless
|
|
760
|
-
|
|
761
|
-
|
|
776
|
+
`keryx review complete` refuses while proposed mutants are unrun on an attended round, unless the
|
|
777
|
+
operator waived the pass themselves: the `review_waive_mutation` card in keryx shell, or `keryx review
|
|
778
|
+
waive-mutation --package <review-dir> --reason "<why>"` in their terminal (it writes
|
|
779
|
+
`operator-decisions.json`; a `dispatch.mutationWaiver` quote you write is not enough on a package
|
|
780
|
+
`keryx review start` created). Attended is what the start recorded in `run-profile.json`: every round
|
|
781
|
+
except `review start --unattended` and `keryx review run --autonomous`, which record `Not run: mutation
|
|
782
|
+
pass` without asking.
|
|
783
|
+
|
|
784
|
+
These operator gates (cards, terminal-only commands, plan confirmation, decision records) keep a
|
|
785
|
+
cooperating agent from cutting corners and make every decision visible and attributable; they do not
|
|
786
|
+
stop a hostile same-user agent, which can fake a pty or write the JSON records itself (the TM-03/TM-04
|
|
787
|
+
boundary). The autonomous runner's mutation-gate exemption predates flow 457 and is kept on purpose.
|
|
762
788
|
|
|
763
789
|
`keryx review mutate --cap <n>` runs the first `n` candidates and records `cap` and `not_reached`
|
|
764
790
|
in `mutation-<n>.json`. The table then prints `Not run: N candidates` (and the report must carry
|
|
@@ -827,12 +853,13 @@ minute 119, and the PR merged first; the other re-dispatched a finished wave and
|
|
|
827
853
|
41 slices. The operator can only act on a risk they were told about.
|
|
828
854
|
|
|
829
855
|
1. On a PR target read merged / approved / CI (`gh pr view <n> --json state,reviewDecision,statusCheckRollup`). Say in one line what the state means for the round: an approved PR with green CI can merge any minute, and a merged PR makes the rest of the round a post-merge audit.
|
|
830
|
-
2. **Later, once the package and slices exist** (after `review scope`, `review start` and `review slice`, before the first reviewer starts): `keryx review required --mode all --scope .metaproject/data/review/scope.json --depth auto
|
|
856
|
+
2. **Later, once the package and slices exist** (after `review scope`, `review start` and `review slice --package`, before the first reviewer starts): `keryx review required --mode all --scope .metaproject/data/review/scope.json --depth auto --package <review-dir>` prints the reviewer set and the depth it chose (see "Depth floor"); auto needs the file list and a line count, else the round is full. `keryx review estimate --package <review-dir> [--manifest <slices/manifest.json>]` prints assignments, waves and a duration range; the manifest defaults to `<package>/slices/manifest.json`, then `.metaproject/data/review/slices/manifest.json`.
|
|
831
857
|
3. Show the operator depth + estimate and the merge risk before the first dispatch. Attended: let them choose `full` over a light default. Unattended: record both in the report and continue.
|
|
858
|
+
4. **An over-threshold plan waits for the operator.** `estimate` flags a plan over `reviewPlan.maxDispatches` (default 40) or `reviewPlan.maxMinutes` (default 90) in `routing.config.json`; `dispatch-check --package` and `ledger build` refuse it (`REVIEWER_INPUT_PLAN_UNCONFIRMED`) until `<review-dir>/plan-confirmation.json` exists. Only the operator writes it: the `review_confirm_plan` card in keryx shell, or `keryx review confirm-plan --package <review-dir>` (or `keryx review estimate --package <review-dir> --confirm --quote "<their words>"`) in their terminal; both refuse without a TTY. Unattended, the plan is not dispatched: report the estimate and stop.
|
|
832
859
|
|
|
833
860
|
## Early verdict — the verdict is interim until `complete`
|
|
834
861
|
|
|
835
|
-
As soon as every reviewer result and the verifier's are on disk, save each verifier pass to `research-evidence/verifications.json` first (without it a refuted finding still counts), then run `keryx review verdict <id|path>
|
|
862
|
+
As soon as every reviewer result and the verifier's are on disk, save each verifier pass to `research-evidence/verifications.json` first (without it a refuted finding still counts), then run `keryx review verdict <id|path> [--json]`: it reads `<package>/raw`, where every host keeps the round's results (`--raw <dir>` only for results kept elsewhere; the shared `.metaproject/data/review/raw` mixes in other rounds' replies). It prints the interim verdict and writes `verdict-interim.md` into the package. Give the operator that verdict in the same message; do not hold it for the mutation pass, the ledger or `complete`.
|
|
836
863
|
|
|
837
864
|
The tail keeps running after it: the mutation pass (`keryx review mutate`), `ledger build`, `ingest`, `readiness` and `keryx review complete`. Every managed round finishes them. The round is **not done** until `complete`: the verdict you gave is interim, and the report says so and names what the tail may still change (a surviving mutant, a verifier refutation, a late reviewer result). A light round has no mutation pass: its tail is `ledger build`, `ingest`, `readiness`, `complete`.
|
|
838
865
|
|
|
@@ -844,7 +871,7 @@ Do not wait for the last reviewer. When the first `blocker` or `major` finding a
|
|
|
844
871
|
|
|
845
872
|
After a timeout, a crash or a resumed session, in this order:
|
|
846
873
|
|
|
847
|
-
1. **Collect.** `keryx review retry-plan --manifest <slices
|
|
874
|
+
1. **Collect.** `keryx review retry-plan --manifest <package>/slices/manifest.json --package <package> --reviewer <id> --next-wave` reads `<package>/raw/` first and collects late reviewer results; it prints `collected late: N` and never re-hands a slice that is finished.
|
|
848
875
|
2. **Validate** each collected reply (a `STATUS:` line and a `REVIEW_RESULT` block matching `reviewer-finding.schema.json`), **ingest** it, and rebuild `research.json` with `ledger build`; run `ingest --research` once it prints READY.
|
|
849
876
|
3. **Dispatch only what is missing:** the wave `retry-plan` prints. A wave whose results are on disk is never dispatched again.
|
|
850
877
|
4. **A second timeout of the same reviewer changes the task, not only the diff size:** fewer slices per dispatch, a narrower focus (one concern or one directory), or a lighter model tier for a mechanical slice. Two results in a row with nothing new are `Not run`, as `retry-plan` prints.
|
|
@@ -852,3 +879,41 @@ After a timeout, a crash or a resumed session, in this order:
|
|
|
852
879
|
## dispatch-check on every payload
|
|
853
880
|
|
|
854
881
|
Before any mass dispatch run `keryx review dispatch-check --payload <file> --manifest <dir>/manifest.json` on every payload, on every host. It fails `REVIEWER_INPUT_PATH_MISSING` when a `skill_path` or `context_doc` names a file that is not there, and still fails a payload that names no slice, exceeds the wave ceiling or breaks `reviewer-input.schema.json`. Fix the payload; a dead path costs a whole wave of refusals. Related: `review mutate` runs in a scratch copy under the repo and prints the baseline's tail when the baseline is red; `review start --graph-timeout <s>` bounds the graph build.
|
|
882
|
+
|
|
883
|
+
## Review Plan Preview — legacy groups
|
|
884
|
+
|
|
885
|
+
```text
|
|
886
|
+
Optional legacy/profile reviewers:
|
|
887
|
+
- code-ai-review: available via --code-ai or --legacy-profiles
|
|
888
|
+
- code-learned-review: available via --learned or --legacy-profiles
|
|
889
|
+
- code-style-review: available via --code-style or --legacy-profiles
|
|
890
|
+
- code-mobx-store-review: auto-suggest when *.store.ts or MobX patterns are present; available via --mobx-store or --legacy-profiles
|
|
891
|
+
|
|
892
|
+
Skipped reviewers:
|
|
893
|
+
- code-ai-review: profile reviewer, not selected unless --code-ai/--legacy-profiles
|
|
894
|
+
- code-learned-review: profile reviewer, not selected unless --learned/--legacy-profiles
|
|
895
|
+
- code-style-review: legacy style profile, not selected unless --code-style/--legacy-profiles
|
|
896
|
+
- code-mobx-store-review: not selected unless --mobx-store/--legacy-profiles or MobX store files are detected
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
## Token and context budget
|
|
900
|
+
|
|
901
|
+
The orchestrator owns the token budget. Sub-reviewers receive only the context their domain needs.
|
|
902
|
+
|
|
903
|
+
Budget rules:
|
|
904
|
+
- Compute a scope digest before dispatch: file list, diff stats, module map, and top risks.
|
|
905
|
+
- Send full diffs only for files relevant to each reviewer.
|
|
906
|
+
- For large files, send changed hunks plus nearby symbols first; include the full file only when path mode or the reviewer requires whole-file context.
|
|
907
|
+
- Never send generated files, lockfiles, snapshots, build output, or vendored code unless the reviewer is specifically about that file type.
|
|
908
|
+
- Cap each reviewer prompt with the `per_reviewer` budget when provided; otherwise use the smallest prompt that preserves evidence.
|
|
909
|
+
- Record omitted files and truncation in `review_context.token_policy.omissions`.
|
|
910
|
+
- If a reviewer returns `NEEDS_CONTEXT`, provide only the missing targeted context, not the entire repository.
|
|
911
|
+
|
|
912
|
+
Default budget guidance:
|
|
913
|
+
|
|
914
|
+
| Review size | Detection | Context mode | Dispatch style |
|
|
915
|
+
|---|---|---|---|
|
|
916
|
+
| small | <= 5 files and <= 300 changed lines | `light` | full relevant diff to selected reviewers |
|
|
917
|
+
| medium | <= 20 files or <= 2,000 changed lines | `light` | per-domain filtered diff |
|
|
918
|
+
| large | > 20 files or > 2,000 changed lines | ask `full` | staged waves by domain |
|
|
919
|
+
| high-risk | auth/API/core/security/data migrations | ask `full` | staged waves, verifier included |
|