Merge branch 'next' into fix/1477-surface-source-marker

This commit is contained in:
Joe
2026-06-27 06:16:16 -05:00
committed by GitHub
30 changed files with 835 additions and 66 deletions

View File

@@ -0,0 +1,5 @@
---
type: Added
pr: 1766
---
**`/gsd-review` now supports custom reviewer instances** — run one model-capable adapter (e.g. OpenCode) as several independent reviewer identities via a bounded `review.reviewer_instances` config, so two different models can review in a single pass without manually swapping config or hand-merging REVIEWS.md. (#1517)

View File

@@ -35,6 +35,12 @@ Phase number: extracted from $ARGUMENTS (required)
- `--cursor` — Include Cursor agent review - `--cursor` — Include Cursor agent review
- `--agy` / `--antigravity` — Include Antigravity CLI review - `--agy` / `--antigravity` — Include Antigravity CLI review
- `--all` — Include all available CLIs - `--all` — Include all available CLIs
**No flags** — if `review.default_reviewers` is set, review with only those configured
reviewers that are detected; otherwise review with all available CLIs. Configured
`review.reviewer_instances` names may appear in `review.default_reviewers`; each runs as an
independent reviewer identity backed by its configured adapter+model (see
`docs/CONFIGURATION.md`). Instance names are not valid as flags.
</context> </context>
<process> <process>

View File

@@ -224,6 +224,49 @@ Example:
} }
``` ```
### Reviewer instances for `/gsd-review` (#1517)
Use `review.reviewer_instances` to run one model-capable adapter as several independent
reviewer identities — e.g. two OpenCode-backed reviews with different models in a single
`/gsd-review` pass. Each entry maps an instance name to `{ cli, model?, agent? }`.
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `review.reviewer_instances.<name>.cli` | string | (required) | A known reviewer adapter the instance reuses (e.g. `opencode`). Must be a built-in slug; never an arbitrary shell command. |
| `review.reviewer_instances.<name>.model` | string | (adapter default) | Opaque `provider/model` id passed through verbatim to the adapter's `--model`. GSD does not parse it. |
| `review.reviewer_instances.<name>.agent` | string | (none) | Opaque agent name; honoured only by adapters with a native agent concept (OpenCode `--agent` in v1). |
Instance names must match `^[a-z0-9][a-z0-9-]*$` and must not equal a built-in reviewer slug.
Instances participate ONLY through `review.default_reviewers` (there are no per-instance CLI
flags). Instance references are expanded before built-in slugs; an instance is available iff
its `cli` is detected. An entry that is neither a defined instance nor a built-in slug is a
hard error (a typo'd instance name must be loud). When two or more selected instances share
the same `cli`, `REVIEWS.md` prints a one-line shared-adapter caveat so review consensus is
not silently overstated. See [ADR-1517](adr/1517-reviewer-instances-config-surface.md).
Example:
```json
{
"review": {
"reviewer_instances": {
"opencode-deepseek": { "cli": "opencode", "model": "deepseek/deepseek-v4-pro", "agent": "review" },
"opencode-mimo": { "cli": "opencode", "model": "xiaomi/mimo-v2.5-pro" }
},
"default_reviewers": ["opencode-deepseek", "opencode-mimo", "codex"]
}
}
```
Set each field via `config-set`:
```bash
gsd config-set review.reviewer_instances.opencode-deepseek.cli opencode
gsd config-set review.reviewer_instances.opencode-deepseek.model deepseek/deepseek-v4-pro
gsd config-set review.reviewer_instances.opencode-deepseek.agent review
gsd config-set review.default_reviewers '["opencode-deepseek","opencode-mimo","codex"]'
```
### Agent-skill injection (dynamic) ### Agent-skill injection (dynamic)
`agent_skills.<agent-type>` extends the `agent_skills` map documented below. Slug is validated against `[a-zA-Z0-9_-]+` — no path separators, no whitespace, no shell metacharacters. Configured interactively via `/gsd-config --integrations`. `agent_skills.<agent-type>` extends the `agent_skills` map documented below. Slug is validated against `[a-zA-Z0-9_-]+` — no path separators, no whitespace, no shell metacharacters. Configured interactively via `/gsd-config --integrations`.

View File

@@ -248,6 +248,7 @@
"research-documentation-lookup.md", "research-documentation-lookup.md",
"research-philosophy.md", "research-philosophy.md",
"research-verification-protocol.md", "research-verification-protocol.md",
"reviewer-instances.md",
"revision-loop.md", "revision-loop.md",
"scout-codebase.md", "scout-codebase.md",
"security-asvs-levels.md", "security-asvs-levels.md",

View File

@@ -312,6 +312,7 @@ Full roster at `gsd-core/references/*.md`. References are shared knowledge docum
| `loop-hook-dispatch.md` | Generic dispatch contract for consuming `gsd_run loop render-hooks <point> --raw` output in any host-loop workflow — envelope shape, per-kind dispatch rules (contribution/step/gate), and liveness banner. | | `loop-hook-dispatch.md` | Generic dispatch contract for consuming `gsd_run loop render-hooks <point> --raw` output in any host-loop workflow — envelope shape, per-kind dispatch rules (contribution/step/gate), and liveness banner. |
| `scout-codebase.md` | Phase-type→codebase-map selection table for discuss-phase scout step (extracted via the discuss-phase/modes progressive-disclosure split, #717). | | `scout-codebase.md` | Phase-type→codebase-map selection table for discuss-phase scout step (extracted via the discuss-phase/modes progressive-disclosure split, #717). |
| `revision-loop.md` | Plan revision iteration patterns. | | `revision-loop.md` | Plan revision iteration patterns. |
| `reviewer-instances.md` | Custom reviewer instances for `/gsd-review` (#1517) — same-adapter multi-model review: config shape, resolution rules, invocation, and the REVIEWS.md contract. Lazily loaded by `review.md` when `review.reviewer_instances` is configured. |
| `universal-anti-patterns.md` | Universal anti-patterns to detect and avoid. | | `universal-anti-patterns.md` | Universal anti-patterns to detect and avoid. |
| `worktree-branch-check.md` | Canonical spawn-time worktree HEAD/base guard (worktree_branch_check): verify-only and fail-closed — per-agent-branch assertion, protected-ref refusal (#2924), and an exact-base assertion that halts with `exit 42` on mismatch so the orchestrator (worktree lifecycle owner) performs recovery (#48). Embedded into worktree sub-agent prompts at dispatch. | | `worktree-branch-check.md` | Canonical spawn-time worktree HEAD/base guard (worktree_branch_check): verify-only and fail-closed — per-agent-branch assertion, protected-ref refusal (#2924), and an exact-base assertion that halts with `exit 42` on mismatch so the orchestrator (worktree lifecycle owner) performs recovery (#48). Embedded into worktree sub-agent prompts at dispatch. |
| `worktree-path-safety.md` | Worktree guard suite: HEAD assertion, cwd-drift sentinel (step 0a, #3097), and absolute-path guard (step 0b, #3099) — loaded into executor spawn prompts via `<execution_context>`. | | `worktree-path-safety.md` | Worktree guard suite: HEAD assertion, cwd-drift sentinel (step 0a, #3097), and absolute-path guard (step 0b, #3099) — loaded into executor spawn prompts via `<execution_context>`. |

View File

@@ -0,0 +1,104 @@
# ADR-1517: Reviewer instances — bounded config surface for same-adapter multi-model review
- **Status:** Accepted
- **Date:** 2026-06-26
- **Issue:** #1517
- **Builds on:** Review Reviewer Selection Module, config-schema manifest (ADR-457 generated single source)
## Context
`/gsd:review` exposes one reviewer identity per built-in slug (`KNOWN_REVIEWER_SLUGS`).
This works when reviewers are independent CLIs (`codex`, `gemini`), but breaks down when a
single model-capable CLI can route to several models. The motivating adapter is **OpenCode**:
a solo developer who wants two OpenCode-backed reviews with different models must manually
flip `review.models.opencode`, rerun, and hand-merge `REVIEWS.md`. That is easy to forget,
easy to overwrite, and does not participate in one review/convergence pass.
The feature (#1517, `approved-feature`) adds a **bounded config surface** so one adapter can
run as several independent reviewer identities. The maintainer's spec-of-record resolved the
three blocking design questions; this ADR pins the resulting contract (field names,
REVIEWS.md section-header format, frontmatter shape) because, once shipped, these become a
depended-on interface (Hyrum's Law).
## Decision
### Config shape
A new `review.reviewer_instances` object under the existing `review` top-level config
namespace. Each entry maps an instance name to `{ cli, model?, agent? }`:
```json
{
"review": {
"reviewer_instances": {
"opencode-deepseek": { "cli": "opencode", "model": "deepseek/deepseek-v4-pro", "agent": "review" },
"opencode-mimo": { "cli": "opencode", "model": "xiaomi/mimo-v2.5-pro" }
},
"default_reviewers": ["opencode-deepseek", "opencode-mimo", "codex"]
}
}
```
- **Instance name:** `^[a-z0-9][a-z0-9-]*$`, MUST NOT equal a built-in slug. Validated at
`config-set` time.
- **`cli`:** MUST be a known adapter from `KNOWN_REVIEWER_SLUGS` — never an arbitrary shell
command (Kerckhoffs / Postel: strict at the invocation boundary).
- **`model`:** a single opaque `provider/model` string (OpenCode's native format). GSD does
NOT parse model IDs; pass through verbatim.
- **`agent`:** opaque string; honoured only by adapters with a native agent concept
(OpenCode `--agent` in v1). Ignored by other adapters.
### Resolution contract (single source)
Instance→cli resolution lives in ONE place: `resolveReviewerSelection` /
`normalizeReviewerInstances` in `review-reviewer-selection.cjs`. The `/gsd:review` workflow
applies the SAME rules. A parity test (`tests/review-reviewer-instances.test.cjs`) asserts the
resolved mapping never diverges from the configured `cli` field — the
`DEFECT.GENERATIVE-FIX` guard against two surfaces drifting.
Rules:
1. Instances participate ONLY via `review.default_reviewers` (no per-instance CLI flags).
2. Instance references expand BEFORE the built-in-slug check.
3. An instance is available iff its base `cli` is detected.
4. An entry that is neither a defined instance nor a built-in slug is a **hard error** when
instances are configured (typo must be loud); legacy warn-and-drop when no instances are
configured (backward compatibility).
5. ≥2 selected instances sharing a base `cli` set `sharedAdapterCaveat` and emit a one-line
caveat in REVIEWS.md.
### REVIEWS.md contract
- **Frontmatter `reviewers:`** records actual identities: built-in slugs and instance names
(e.g. `[opencode-deepseek, opencode-mimo, codex]`).
- **Section headers:** each instance gets its own section,
`## <Adapter> Review (<instance-name>)`, e.g. `## OpenCode Review (opencode-deepseek)`.
Same-cli instances are never collapsed.
- **Shared-adapter caveat:** a one-line note after the frontmatter when ≥2 instances share
an adapter, so consensus is never silently overstated.
## Alternatives considered
1. **Per-instance CLI flags (`--opencode-1`/`--opencode-2`):** solves only one adapter, does
not scale, clutters the flag surface. Rejected (spec-of-record, non-blocking decision).
2. **Arbitrary shell commands as reviewers:** maximally flexible but reintroduces quoting,
portability, and injection risk. Rejected — bounded adapter config is safer.
3. **A parallel instance registry separate from the slug resolver:** rejected via Gall's Law
/ Choose Boring Technology — generalize the existing slug-resolution pattern rather than
bolting on a second mechanism.
## Consequences
- **Forward-compatibility:** the field names (`cli`, `model`, `agent`), the REVIEWS.md
section-header format, and the frontmatter identity list are now a depended-on contract.
Changing them requires a migration + a new ADR amendment.
- **Maintenance:** a per-adapter "supported fields" matrix emerges (OpenCode: model+agent;
others: model only). Bounded while the spec stays declarative.
- **Security:** the `cli` allow-list is the trust boundary. `model`/`agent`/instance-name
are opaque and never interpolated into shell strings by the resolver; the workflow passes
them as separate argv elements.
## Related
- #1517 — approved feature (spec-of-record in the triage comments)
- `src/review-reviewer-selection.cts` — `normalizeReviewerInstances`, `resolveReviewerSelection`
- `gsd-core/bin/shared/config-schema.manifest.json` — `review.reviewer_instances.*` dynamic pattern

View File

@@ -172,6 +172,11 @@
"source": "^review\\.max_prompt_tokens_per_reviewer\\.[a-zA-Z0-9_-]+$", "source": "^review\\.max_prompt_tokens_per_reviewer\\.[a-zA-Z0-9_-]+$",
"description": "review.max_prompt_tokens_per_reviewer.<reviewer-slug>" "description": "review.max_prompt_tokens_per_reviewer.<reviewer-slug>"
}, },
{
"topLevel": "review",
"source": "^review\\.reviewer_instances\\.[a-zA-Z0-9_-]+\\.(cli|model|agent)$",
"description": "review.reviewer_instances.<instance-name>.<cli|model|agent> (#1517)"
},
{ {
"topLevel": "model_policy", "topLevel": "model_policy",
"source": "^model_policy\\.runtime_tiers\\.[a-zA-Z0-9_-]+\\.(opus|sonnet|haiku)$", "source": "^model_policy\\.runtime_tiers\\.[a-zA-Z0-9_-]+\\.(opus|sonnet|haiku)$",

View File

@@ -0,0 +1,99 @@
# Reviewer Instances (#1517)
Custom reviewer instances for `/gsd:review`: run one model-capable adapter (e.g. OpenCode)
as several independent reviewer identities in a single review pass. Loaded lazily by
`gsd-core/workflows/review.md` when `review.reviewer_instances` is configured. See
[ADR-1517](../docs/adr/1517-reviewer-instances-config-surface.md) for the contract.
---
## Config shape
A `review.reviewer_instances` object under the `review` namespace. Each entry maps an
instance name to `{ cli, model?, agent? }`:
```json
{
"review": {
"reviewer_instances": {
"opencode-deepseek": { "cli": "opencode", "model": "deepseek/deepseek-v4-pro", "agent": "review" },
"opencode-mimo": { "cli": "opencode", "model": "xiaomi/mimo-v2.5-pro" }
},
"default_reviewers": ["opencode-deepseek", "opencode-mimo", "codex"]
}
}
```
- Instance name: `^[a-z0-9][a-z0-9-]*$`, must not equal a built-in slug. Validated at
`config-set` time.
- `cli`: MUST be a known adapter (`KNOWN_REVIEWER_SLUGS`) — never an arbitrary shell command.
- `model`: opaque `provider/model` string, passed through verbatim. GSD does not parse it.
- `agent`: opaque string; honoured only by adapters with a native agent concept (OpenCode
`--agent` in v1). Ignored by other adapters.
---
## Resolution rules (single source)
The canonical logic lives in `resolveReviewerSelection` / `normalizeReviewerInstances` in
`review-reviewer-selection.cjs`. Apply the SAME rules in the workflow so the two surfaces
cannot diverge (`DEFECT.GENERATIVE-FIX`; parity-locked in
`tests/review-reviewer-instances.test.cjs`).
1. Instances participate ONLY via `review.default_reviewers`. They never appear under `--all`
or explicit `--<cli>` flags, and there are no per-instance CLI flags.
2. Expand instance references BEFORE the built-in-slug check: an entry that is a key in
`review.reviewer_instances` is an **instance**; an entry that is a built-in slug is a
**builtin**.
3. An instance is **available** iff its base `cli` is detected (e.g. `opencode-deepseek` is
available iff `opencode` is available).
4. An entry that is NEITHER a defined instance NOR a built-in slug is a **hard error** (likely
a typo'd instance name) — stop and report it. Do NOT silently drop it. (When
`review.reviewer_instances` is absent entirely, fall back to the legacy unknown-slug
warn-and-drop behaviour for backward compatibility.)
5. `model`/`agent`/instance-name are opaque: pass them as separate argv elements. They are
NEVER interpolated into shell strings.
---
## Invocation
For each selected INSTANCE, invoke its base `cli` using the instance's own `model`/`agent` —
NOT the global `review.models.<cli>`. Each instance writes to its OWN per-instance output file
and runs as a distinct reviewer identity.
For an OpenCode-backed instance (the motivating adapter):
```bash
# $INSTANCE_MODEL / $INSTANCE_AGENT come from the instance spec; $INSTANCE_NAME is the
# reviewer identity (e.g. opencode-deepseek). --agent is OpenCode's native subagent flag;
# omit it when the instance has no agent.
if [ -n "$INSTANCE_AGENT" ] && [ "$INSTANCE_AGENT" != "null" ]; then
cat /tmp/gsd-review-prompt-{phase}.md | opencode run --model "$INSTANCE_MODEL" --agent "$INSTANCE_AGENT" - 2>/dev/null > /tmp/gsd-review-${INSTANCE_NAME}-{phase}.md
else
cat /tmp/gsd-review-prompt-{phase}.md | opencode run --model "$INSTANCE_MODEL" - 2>/dev/null > /tmp/gsd-review-${INSTANCE_NAME}-{phase}.md
fi
if [ ! -s /tmp/gsd-review-${INSTANCE_NAME}-{phase}.md ]; then
echo "OpenCode review ($INSTANCE_NAME) failed or returned empty output." > /tmp/gsd-review-${INSTANCE_NAME}-{phase}.md
fi
```
For an instance backed by a DIFFERENT cli, reuse that cli's invocation block with two
substitutions: use the instance's `model` in place of the global `review.models.<cli>` value,
and write to `/tmp/gsd-review-${INSTANCE_NAME}-{phase}.md`. Only `opencode` honours an
`agent` field in v1; ignore `agent` for other adapters.
---
## REVIEWS.md contract
- **Frontmatter `reviewers:`** records the actual identities invoked. For a built-in slug use
the slug (`opencode`); for an instance use the instance name (`opencode-deepseek`), so
frontmatter distinguishes the independent voices. Example:
`reviewers: [opencode-deepseek, opencode-mimo, codex]`.
- **Section headers:** each instance gets its OWN top-level section, headed with the base
adapter's display name plus the instance name in parentheses:
`## OpenCode Review (opencode-deepseek)`. Same-cli instances are never collapsed.
- **Shared-adapter caveat:** when ≥2 invoked instances share the same base `cli`, print a
one-line caveat immediately after the frontmatter (before the first section), e.g.:
`> Note: opencode-deepseek and opencode-mimo share the opencode adapter; their consensus is cross-model, not cross-tool.`

View File

@@ -66,6 +66,11 @@ Reviewer-selection precedence:
- Known-but-undetected slugs emit an info note and are ignored - Known-but-undetected slugs emit an info note and are ignored
- If all configured reviewers are unavailable, fail with an actionable message - If all configured reviewers are unavailable, fail with an actionable message
**Reviewer instances (#1517, optional):** if `review.reviewer_instances` is configured,
instance names in `review.default_reviewers` run as independent identities. Resolution rules
are in `gsd-core/references/reviewer-instances.md` — load it lazily only when instances are
configured. Unconfigured → default path unchanged.
If no CLIs are available: If no CLIs are available:
``` ```
No external AI CLIs found. Install at least one: No external AI CLIs found. Install at least one:
@@ -243,6 +248,10 @@ else
fi fi
``` ```
**Reviewer instances (#1517, optional):** when instances are configured, each selected
instance invokes its base `cli` with its own `model`/`agent` (opaque argv, never
shell-interpolated). Exact invocation in `gsd-core/references/reviewer-instances.md`.
For each selected CLI, invoke in sequence (not parallel — avoid rate limits): For each selected CLI, invoke in sequence (not parallel — avoid rate limits):
**Gemini:** **Gemini:**
@@ -634,6 +643,11 @@ Combine all review responses into `{phase_dir}/{padded_phase}-REVIEWS.md`:
After all reviewers complete, collect trim metadata files written during the run. For each reviewer that was trimmed (i.e. a `.metadata.json` file exists and `hardFailed` or `omitted` is non-empty, or `projectMdShrunk` is true, or `planTruncationPct > 0`), include a `trimmed_reviewers` block in the frontmatter. Omit the key entirely if no reviewer was trimmed. After all reviewers complete, collect trim metadata files written during the run. For each reviewer that was trimmed (i.e. a `.metadata.json` file exists and `hardFailed` or `omitted` is non-empty, or `projectMdShrunk` is true, or `planTruncationPct > 0`), include a `trimmed_reviewers` block in the frontmatter. Omit the key entirely if no reviewer was trimmed.
**Reviewer instances (#1517, optional):** when instances ran, frontmatter records their
names, each gets its own `## <Adapter> Review (<instance>)` section, and ≥2 same-cli
instances print a one-line shared-adapter caveat. Format in
`gsd-core/references/reviewer-instances.md`.
```markdown ```markdown
--- ---
phase: {N} phase: {N}
@@ -684,6 +698,18 @@ trimmed_reviewers: # only present if at least one reviewer was trimmed
--- ---
## OpenCode Review (opencode-deepseek)
{opencode-deepseek instance review content — only present when this instance was selected}
---
## OpenCode Review (opencode-mimo)
{opencode-mimo instance review content — only present when this instance was selected}
---
## Qwen Review ## Qwen Review
{qwen review content} {qwen review content}

View File

@@ -26,7 +26,7 @@ const { VALID_PROFILES, getAgentToModelMapForProfile, formatAgentToModelMapAsTab
import configSchema = require('./config-schema.cjs'); import configSchema = require('./config-schema.cjs');
const { VALID_CONFIG_KEYS, isValidConfigKey, getCapabilityConfigSchema } = configSchema; const { VALID_CONFIG_KEYS, isValidConfigKey, getCapabilityConfigSchema } = configSchema;
import { isSecretKey, maskSecret } from './secrets.cjs'; import { isSecretKey, maskSecret } from './secrets.cjs';
import { normalizeConfiguredDefaultReviewers } from './review-reviewer-selection.cjs'; import { normalizeConfiguredDefaultReviewers, INSTANCE_NAME_PATTERN, KNOWN_REVIEWER_SLUGS } from './review-reviewer-selection.cjs';
import { migrateOnDisk } from './configuration.cjs'; import { migrateOnDisk } from './configuration.cjs';
// ─── Types ──────────────────────────────────────────────────────────────────── // ─── Types ────────────────────────────────────────────────────────────────────
@@ -695,6 +695,33 @@ function cmdConfigSet(cwd: string, keyPath: string | undefined, value: string |
parsedValue = normalized.values; parsedValue = normalized.values;
} }
// #1517: validate review.reviewer_instances.<name>.<field> leaves at the
// invocation boundary (Postel/Kerckhoffs — strict at accept). The config
// schema dynamic pattern admits the path; this block validates the name + the
// field value so a misconfigured instance is rejected at config-set time, not
// silently at review time. Single-source validators live in
// review-reviewer-selection.cjs (INSTANCE_NAME_PATTERN, KNOWN_REVIEWER_SLUGS).
const instanceLeaf = kp.match(/^review\.reviewer_instances\.([a-zA-Z0-9_-]+)\.(cli|model|agent)$/);
if (instanceLeaf) {
const [, instanceName, field] = instanceLeaf;
if (!INSTANCE_NAME_PATTERN.test(instanceName)) {
error(`Invalid reviewer instance name '${instanceName}'. Must match ^[a-z0-9][a-z0-9-]*$.`);
}
if (KNOWN_REVIEWER_SLUGS.includes(instanceName)) {
error(`Reviewer instance name '${instanceName}' must not equal a built-in reviewer slug.`);
}
if (field === 'cli') {
if (typeof parsedValue !== 'string' || !KNOWN_REVIEWER_SLUGS.includes(parsedValue)) {
error(`Invalid reviewer_instances.${instanceName}.cli '${val}'. Must be a known reviewer adapter: ${KNOWN_REVIEWER_SLUGS.join(', ')}.`);
}
} else {
// model | agent — opaque pass-through strings (never interpolated into shell).
if (typeof parsedValue !== 'string') {
error(`Invalid reviewer_instances.${instanceName}.${field} '${val}'. Must be a string.`);
}
}
}
const setConfigValueResult = setConfigValue(cwd, kp, parsedValue); const setConfigValueResult = setConfigValue(cwd, kp, parsedValue);
// Mask secrets in both JSON and text output. The plaintext is written // Mask secrets in both JSON and text output. The plaintext is written

View File

@@ -6,6 +6,14 @@
* *
* Owns reviewer-selection policy projection for /gsd:review: * Owns reviewer-selection policy projection for /gsd:review:
* explicit flags > --all > review.default_reviewers > all detected. * explicit flags > --all > review.default_reviewers > all detected.
*
* Reviewer instances (#1517): a bounded config surface
* `review.reviewer_instances.<name> = {cli, model?, agent?}` lets one
* model-capable adapter (e.g. opencode) run as several independent reviewer
* identities. Instances participate ONLY in the config_default branch (no
* per-instance CLI flags). An instance is available iff its base `cli` is
* detected. The instance→cli mapping lives HERE (single source; see the parity
* test in tests/review-reviewer-instances.test.cjs — DEFECT.GENERATIVE-FIX).
*/ */
export const KNOWN_REVIEWER_SLUGS: ReadonlyArray<string> = [ export const KNOWN_REVIEWER_SLUGS: ReadonlyArray<string> = [
@@ -22,17 +30,41 @@ export const KNOWN_REVIEWER_SLUGS: ReadonlyArray<string> = [
'llama_cpp', 'llama_cpp',
]; ];
/** Instance names are lowercase slugs that must not shadow a built-in slug. */
export const INSTANCE_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
export interface NormalizedDefaultReviewers { export interface NormalizedDefaultReviewers {
absent: boolean; absent: boolean;
values: string[]; values: string[];
errors: string[]; errors: string[];
} }
export interface ReviewerInstance {
cli: string;
model?: string;
agent?: string;
}
export interface NormalizedReviewerInstances {
instances: Record<string, ReviewerInstance>;
errors: string[];
}
export interface ResolvedReviewer {
identity: string;
kind: 'builtin' | 'instance';
cli: string;
model?: string;
agent?: string;
}
export interface ReviewerSelectionInput { export interface ReviewerSelectionInput {
detected?: unknown[]; detected?: unknown[];
explicitFlags?: unknown[]; explicitFlags?: unknown[];
allFlag?: unknown; allFlag?: unknown;
configuredDefaultReviewers?: unknown; configuredDefaultReviewers?: unknown;
/** #1517: the `review.reviewer_instances` config object. */
reviewerInstances?: unknown;
} }
export interface ReviewerSelectionResult { export interface ReviewerSelectionResult {
@@ -41,6 +73,10 @@ export interface ReviewerSelectionResult {
warnings: string[]; warnings: string[];
infos: string[]; infos: string[];
errors: string[]; errors: string[];
/** #1517: per-identity resolution (builtin slug or expanded instance). */
resolvedInstances: ResolvedReviewer[];
/** #1517: true when ≥2 selected instances share a base cli (consensus caveat). */
sharedAdapterCaveat: boolean;
} }
export function normalizeConfiguredDefaultReviewers( export function normalizeConfiguredDefaultReviewers(
@@ -86,6 +122,76 @@ export function normalizeConfiguredDefaultReviewers(
return { absent: false, values: normalized, errors }; return { absent: false, values: normalized, errors };
} }
/**
* Validate the `review.reviewer_instances` config object (#1517).
* `cli` MUST be a known adapter (never an arbitrary shell command — Kerckhoffs /
* Postel: strict at the invocation boundary). `model`/`agent` are opaque
* pass-through strings; they are never interpolated into shell strings by this
* module. Instance names must not collide with a built-in slug.
*/
export function normalizeReviewerInstances(
rawValue: unknown,
): NormalizedReviewerInstances {
if (rawValue === undefined || rawValue === null) {
return { instances: {}, errors: [] };
}
if (typeof rawValue !== 'object' || Array.isArray(rawValue)) {
return {
instances: {},
errors: ['review.reviewer_instances must be a JSON object mapping instance names to {cli,model,agent}'],
};
}
const obj = rawValue as Record<string, unknown>;
const instances: Record<string, ReviewerInstance> = {};
const errors: string[] = [];
for (const [name, spec] of Object.entries(obj)) {
if (!INSTANCE_NAME_PATTERN.test(name)) {
errors.push(
`invalid reviewer instance name '${name}': must match ^[a-z0-9][a-z0-9-]*$`,
);
continue;
}
if (KNOWN_REVIEWER_SLUGS.includes(name)) {
errors.push(
`reviewer instance name '${name}' must not equal a built-in reviewer slug`,
);
continue;
}
if (spec === null || typeof spec !== 'object' || Array.isArray(spec)) {
errors.push(`reviewer_instances.${name} must be an object with at least {cli}`);
continue;
}
const s = spec as Record<string, unknown>;
const cli = s.cli;
if (typeof cli !== 'string' || !KNOWN_REVIEWER_SLUGS.includes(cli)) {
errors.push(
`reviewer_instances.${name}.cli must be a known reviewer adapter (got: ${JSON.stringify(cli)})`,
);
continue;
}
const instance: ReviewerInstance = { cli };
if (s.model !== undefined && s.model !== null) {
if (typeof s.model !== 'string') {
errors.push(`reviewer_instances.${name}.model must be a string`);
continue;
}
instance.model = s.model;
}
if (s.agent !== undefined && s.agent !== null) {
if (typeof s.agent !== 'string') {
errors.push(`reviewer_instances.${name}.agent must be a string`);
continue;
}
instance.agent = s.agent;
}
instances[name] = instance;
}
return { instances, errors };
}
export function resolveReviewerSelection( export function resolveReviewerSelection(
input: ReviewerSelectionInput, input: ReviewerSelectionInput,
): ReviewerSelectionResult { ): ReviewerSelectionResult {
@@ -99,10 +205,13 @@ export function resolveReviewerSelection(
const normalizedDefaults = normalizeConfiguredDefaultReviewers( const normalizedDefaults = normalizeConfiguredDefaultReviewers(
input.configuredDefaultReviewers, input.configuredDefaultReviewers,
); );
const normalizedInstances = normalizeReviewerInstances(input.reviewerInstances);
const instances = normalizedInstances.instances;
const instancesConfigured = Object.keys(instances).length > 0;
const warnings: string[] = []; const warnings: string[] = [];
const infos: string[] = []; const infos: string[] = [];
const errors: string[] = [...normalizedDefaults.errors]; const errors: string[] = [...normalizedDefaults.errors, ...normalizedInstances.errors];
let source = 'no_config_all_detected'; let source = 'no_config_all_detected';
let selected: string[] = []; let selected: string[] = [];
@@ -122,19 +231,37 @@ export function resolveReviewerSelection(
selected = [...detected]; selected = [...detected];
} else if (!normalizedDefaults.absent) { } else if (!normalizedDefaults.absent) {
source = 'config_default'; source = 'config_default';
const knownDefaults: string[] = []; // #1517: expand instance references BEFORE the built-in-slug check. An
for (const slug of normalizedDefaults.values) { // instance name and a built-in slug are the two legal kinds of entry.
if (!KNOWN_REVIEWER_SLUGS.includes(slug)) { for (const entry of normalizedDefaults.values) {
warnings.push(`unknown reviewer slug in review.default_reviewers: ${slug}`); if (instances[entry]) {
// Instance reference — available iff its base cli is detected.
const cli = instances[entry].cli;
if (!detected.has(cli)) {
infos.push(`configured instance ${entry} not detected (cli ${cli} missing on this host)`);
} else {
selected.push(entry);
}
} else if (KNOWN_REVIEWER_SLUGS.includes(entry)) {
if (!detected.has(entry)) {
infos.push(`configured reviewers not detected on this host: ${entry}`);
} else {
selected.push(entry);
}
} else { } else {
knownDefaults.push(slug); // Neither a defined instance nor a built-in slug.
if (instancesConfigured) {
// Most likely a typo'd instance name — must be loud (#1517 design Q2).
errors.push(
`reviewer instance '${entry}' referenced in review.default_reviewers is not defined in review.reviewer_instances`,
);
} else {
// Backward-compatible behaviour: unknown slug with no instances
// configured warns and is dropped.
warnings.push(`unknown reviewer slug in review.default_reviewers: ${entry}`);
}
} }
} }
const undetected = knownDefaults.filter((slug) => !detected.has(slug));
if (undetected.length > 0) {
infos.push(`configured reviewers not detected on this host: ${undetected.join(', ')}`);
}
selected = knownDefaults.filter((slug) => detected.has(slug));
if (selected.length === 0 && errors.length === 0) { if (selected.length === 0 && errors.length === 0) {
errors.push('all configured default reviewers are unavailable on this host'); errors.push('all configured default reviewers are unavailable on this host');
} }
@@ -142,11 +269,38 @@ export function resolveReviewerSelection(
selected = [...detected]; selected = [...detected];
} }
const selectedSorted = selected.sort();
// Single-source instance→cli resolution projected onto the selected set.
const resolvedInstances: ResolvedReviewer[] = selectedSorted.map((identity) => {
const inst = instances[identity];
if (inst) {
return {
identity,
kind: 'instance' as const,
cli: inst.cli,
model: inst.model,
agent: inst.agent,
};
}
return { identity, kind: 'builtin' as const, cli: identity };
});
const cliCounts: Record<string, number> = {};
for (const r of resolvedInstances) {
if (r.kind === 'instance') {
cliCounts[r.cli] = (cliCounts[r.cli] ?? 0) + 1;
}
}
const sharedAdapterCaveat = Object.values(cliCounts).some((c) => c >= 2);
return { return {
source, source,
selected: selected.sort(), selected: selectedSorted,
warnings, warnings,
infos, infos,
errors, errors,
resolvedInstances,
sharedAdapterCaveat,
}; };
} }

View File

@@ -41,7 +41,7 @@
"gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd", "gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "8bc541aabc2e143c", "gsd-core/bin/verify-reapply-patches.cjs": "8bc541aabc2e143c",
@@ -115,6 +115,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf", "gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -273,7 +274,7 @@
"gsd-core/workflows/remove-phase.md": "6b9947fba1a97f46", "gsd-core/workflows/remove-phase.md": "6b9947fba1a97f46",
"gsd-core/workflows/remove-workspace.md": "95f05defffe6754e", "gsd-core/workflows/remove-workspace.md": "95f05defffe6754e",
"gsd-core/workflows/resume-project.md": "cadf390bae95fc76", "gsd-core/workflows/resume-project.md": "cadf390bae95fc76",
"gsd-core/workflows/review.md": "439d0088fbc29350", "gsd-core/workflows/review.md": "4d1ea3f9785044b3",
"gsd-core/workflows/scan.md": "f2754f3e3ea528ff", "gsd-core/workflows/scan.md": "f2754f3e3ea528ff",
"gsd-core/workflows/secure-phase.md": "78705b7f09612464", "gsd-core/workflows/secure-phase.md": "78705b7f09612464",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -381,7 +382,7 @@
"skills/gsd-quick/SKILL.md": "c18b11b12ba134fa", "skills/gsd-quick/SKILL.md": "c18b11b12ba134fa",
"skills/gsd-resume-work/SKILL.md": "fa2ee37470c6ae07", "skills/gsd-resume-work/SKILL.md": "fa2ee37470c6ae07",
"skills/gsd-review-backlog/SKILL.md": "d8a150558cc9326a", "skills/gsd-review-backlog/SKILL.md": "d8a150558cc9326a",
"skills/gsd-review/SKILL.md": "f9b5e25043b667ac", "skills/gsd-review/SKILL.md": "1abcf1f6a7b73ab2",
"skills/gsd-secure-phase/SKILL.md": "47a4ecd2aa680fda", "skills/gsd-secure-phase/SKILL.md": "47a4ecd2aa680fda",
"skills/gsd-settings/SKILL.md": "fda7af8331acd352", "skills/gsd-settings/SKILL.md": "fda7af8331acd352",
"skills/gsd-ship/SKILL.md": "4529b04a357cdacd", "skills/gsd-ship/SKILL.md": "4529b04a357cdacd",

View File

@@ -85,7 +85,7 @@
"commands/gsd-quick.md": "a6124a2443394092", "commands/gsd-quick.md": "a6124a2443394092",
"commands/gsd-resume-work.md": "e54b929de88b11ce", "commands/gsd-resume-work.md": "e54b929de88b11ce",
"commands/gsd-review-backlog.md": "6e8a0417fab95cd3", "commands/gsd-review-backlog.md": "6e8a0417fab95cd3",
"commands/gsd-review.md": "4403de207a9c2582", "commands/gsd-review.md": "87d9b3f0705afb5e",
"commands/gsd-secure-phase.md": "a2320ecca4cb160b", "commands/gsd-secure-phase.md": "a2320ecca4cb160b",
"commands/gsd-settings.md": "53b90624a70fd530", "commands/gsd-settings.md": "53b90624a70fd530",
"commands/gsd-ship.md": "81136d903d261b33", "commands/gsd-ship.md": "81136d903d261b33",
@@ -110,7 +110,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -184,6 +184,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -342,7 +343,7 @@
"gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9", "gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9",
"gsd-core/workflows/remove-workspace.md": "b8817a3a5907f5bc", "gsd-core/workflows/remove-workspace.md": "b8817a3a5907f5bc",
"gsd-core/workflows/resume-project.md": "b18b51fd15cbce95", "gsd-core/workflows/resume-project.md": "b18b51fd15cbce95",
"gsd-core/workflows/review.md": "18ab093986814bb3", "gsd-core/workflows/review.md": "fc23a807c6c3d6d9",
"gsd-core/workflows/scan.md": "54ff1ff60041d065", "gsd-core/workflows/scan.md": "54ff1ff60041d065",
"gsd-core/workflows/secure-phase.md": "1d1c66ad9ea01bd2", "gsd-core/workflows/secure-phase.md": "1d1c66ad9ea01bd2",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -449,7 +450,7 @@
"skills/gsd-ns-review/skills/debug/SKILL.md": "4b9bde6d213185f0", "skills/gsd-ns-review/skills/debug/SKILL.md": "4b9bde6d213185f0",
"skills/gsd-ns-review/skills/eval-review/SKILL.md": "61d28536af6794c9", "skills/gsd-ns-review/skills/eval-review/SKILL.md": "61d28536af6794c9",
"skills/gsd-ns-review/skills/forensics/SKILL.md": "e68fc285c39dad5e", "skills/gsd-ns-review/skills/forensics/SKILL.md": "e68fc285c39dad5e",
"skills/gsd-ns-review/skills/review/SKILL.md": "022745ee2379823c", "skills/gsd-ns-review/skills/review/SKILL.md": "3d1cbf005e02c948",
"skills/gsd-ns-review/skills/secure-phase/SKILL.md": "ff7949b3261c09fa", "skills/gsd-ns-review/skills/secure-phase/SKILL.md": "ff7949b3261c09fa",
"skills/gsd-ns-review/skills/ui-phase/SKILL.md": "d0e75ee06eaa0165", "skills/gsd-ns-review/skills/ui-phase/SKILL.md": "d0e75ee06eaa0165",
"skills/gsd-ns-review/skills/ui-review/SKILL.md": "bdab072171d79877", "skills/gsd-ns-review/skills/ui-review/SKILL.md": "bdab072171d79877",

View File

@@ -40,7 +40,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -114,6 +114,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -272,7 +273,7 @@
"gsd-core/workflows/remove-phase.md": "f76e1c2a4dd31a09", "gsd-core/workflows/remove-phase.md": "f76e1c2a4dd31a09",
"gsd-core/workflows/remove-workspace.md": "0e73844f0f41cbc3", "gsd-core/workflows/remove-workspace.md": "0e73844f0f41cbc3",
"gsd-core/workflows/resume-project.md": "3dcaa7abe1800d35", "gsd-core/workflows/resume-project.md": "3dcaa7abe1800d35",
"gsd-core/workflows/review.md": "c32eac3c18b11691", "gsd-core/workflows/review.md": "1660ff860e79f9b7",
"gsd-core/workflows/scan.md": "8e1bbf2eed1752ca", "gsd-core/workflows/scan.md": "8e1bbf2eed1752ca",
"gsd-core/workflows/secure-phase.md": "b2b9100ff79d6017", "gsd-core/workflows/secure-phase.md": "b2b9100ff79d6017",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -380,7 +381,7 @@
"skills/gsd-quick/SKILL.md": "bd5e4cb79bc41611", "skills/gsd-quick/SKILL.md": "bd5e4cb79bc41611",
"skills/gsd-resume-work/SKILL.md": "e23d2fb963d47d04", "skills/gsd-resume-work/SKILL.md": "e23d2fb963d47d04",
"skills/gsd-review-backlog/SKILL.md": "1708aab6cb919223", "skills/gsd-review-backlog/SKILL.md": "1708aab6cb919223",
"skills/gsd-review/SKILL.md": "b2fe23d7725c19f4", "skills/gsd-review/SKILL.md": "17cf20dd9a4796ff",
"skills/gsd-secure-phase/SKILL.md": "a6adf4729b606d5a", "skills/gsd-secure-phase/SKILL.md": "a6adf4729b606d5a",
"skills/gsd-settings/SKILL.md": "6d9fbddb0b00fd46", "skills/gsd-settings/SKILL.md": "6d9fbddb0b00fd46",
"skills/gsd-ship/SKILL.md": "9f7929947aac3c27", "skills/gsd-ship/SKILL.md": "9f7929947aac3c27",

View File

@@ -44,7 +44,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -118,6 +118,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -276,7 +277,7 @@
"gsd-core/workflows/remove-phase.md": "61b68a4af414e3c2", "gsd-core/workflows/remove-phase.md": "61b68a4af414e3c2",
"gsd-core/workflows/remove-workspace.md": "411bfff942216185", "gsd-core/workflows/remove-workspace.md": "411bfff942216185",
"gsd-core/workflows/resume-project.md": "f8f71b5a98374b85", "gsd-core/workflows/resume-project.md": "f8f71b5a98374b85",
"gsd-core/workflows/review.md": "897a4c72a97178f8", "gsd-core/workflows/review.md": "a74ae666e01ceebb",
"gsd-core/workflows/scan.md": "db0c48c3963f9a8b", "gsd-core/workflows/scan.md": "db0c48c3963f9a8b",
"gsd-core/workflows/secure-phase.md": "c51b86e369574195", "gsd-core/workflows/secure-phase.md": "c51b86e369574195",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -361,7 +362,7 @@
"skills/gsd-ns-review/skills/debug/SKILL.md": "2017ee8a5c39357a", "skills/gsd-ns-review/skills/debug/SKILL.md": "2017ee8a5c39357a",
"skills/gsd-ns-review/skills/eval-review/SKILL.md": "c76022e94ee30cb1", "skills/gsd-ns-review/skills/eval-review/SKILL.md": "c76022e94ee30cb1",
"skills/gsd-ns-review/skills/forensics/SKILL.md": "bbab359eaa388d34", "skills/gsd-ns-review/skills/forensics/SKILL.md": "bbab359eaa388d34",
"skills/gsd-ns-review/skills/review/SKILL.md": "04c7f2a8515d97a2", "skills/gsd-ns-review/skills/review/SKILL.md": "befdc84f5a0acf03",
"skills/gsd-ns-review/skills/secure-phase/SKILL.md": "ceded474164b4e2d", "skills/gsd-ns-review/skills/secure-phase/SKILL.md": "ceded474164b4e2d",
"skills/gsd-ns-review/skills/ui-phase/SKILL.md": "c35f175ccc747d56", "skills/gsd-ns-review/skills/ui-phase/SKILL.md": "c35f175ccc747d56",
"skills/gsd-ns-review/skills/ui-review/SKILL.md": "48267dc071481a89", "skills/gsd-ns-review/skills/ui-review/SKILL.md": "48267dc071481a89",

View File

@@ -85,7 +85,7 @@
"commands/gsd-quick.md": "8585535a111660d1", "commands/gsd-quick.md": "8585535a111660d1",
"commands/gsd-resume-work.md": "9c4ee571a15fefae", "commands/gsd-resume-work.md": "9c4ee571a15fefae",
"commands/gsd-review-backlog.md": "41ee0337839b8e9d", "commands/gsd-review-backlog.md": "41ee0337839b8e9d",
"commands/gsd-review.md": "4d1b7eaef1560fb4", "commands/gsd-review.md": "763f91f5f823fa3a",
"commands/gsd-secure-phase.md": "6daf0c899069ab74", "commands/gsd-secure-phase.md": "6daf0c899069ab74",
"commands/gsd-settings.md": "57edae813aae049c", "commands/gsd-settings.md": "57edae813aae049c",
"commands/gsd-ship.md": "9190bbab8119a365", "commands/gsd-ship.md": "9190bbab8119a365",
@@ -110,7 +110,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -184,6 +184,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -342,7 +343,7 @@
"gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9", "gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9",
"gsd-core/workflows/remove-workspace.md": "b8817a3a5907f5bc", "gsd-core/workflows/remove-workspace.md": "b8817a3a5907f5bc",
"gsd-core/workflows/resume-project.md": "b18b51fd15cbce95", "gsd-core/workflows/resume-project.md": "b18b51fd15cbce95",
"gsd-core/workflows/review.md": "18ab093986814bb3", "gsd-core/workflows/review.md": "fc23a807c6c3d6d9",
"gsd-core/workflows/scan.md": "54ff1ff60041d065", "gsd-core/workflows/scan.md": "54ff1ff60041d065",
"gsd-core/workflows/secure-phase.md": "1d1c66ad9ea01bd2", "gsd-core/workflows/secure-phase.md": "1d1c66ad9ea01bd2",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -450,7 +451,7 @@
"skills/gsd-quick/SKILL.md": "b895cb9835f3fc0e", "skills/gsd-quick/SKILL.md": "b895cb9835f3fc0e",
"skills/gsd-resume-work/SKILL.md": "f8bc8b92dffd07b7", "skills/gsd-resume-work/SKILL.md": "f8bc8b92dffd07b7",
"skills/gsd-review-backlog/SKILL.md": "c0c743e1376c2eff", "skills/gsd-review-backlog/SKILL.md": "c0c743e1376c2eff",
"skills/gsd-review/SKILL.md": "7f8c2adde7ec94ba", "skills/gsd-review/SKILL.md": "e47c285346aaba06",
"skills/gsd-secure-phase/SKILL.md": "bd36a3157c28df37", "skills/gsd-secure-phase/SKILL.md": "bd36a3157c28df37",
"skills/gsd-settings/SKILL.md": "fbe736decd04a85d", "skills/gsd-settings/SKILL.md": "fbe736decd04a85d",
"skills/gsd-ship/SKILL.md": "8d40fc9f9436d2c3", "skills/gsd-ship/SKILL.md": "8d40fc9f9436d2c3",

View File

@@ -76,7 +76,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -150,6 +150,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf", "gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "335a974ea98d5d83",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -308,7 +309,7 @@
"gsd-core/workflows/remove-phase.md": "75c8ca0dbd1ce404", "gsd-core/workflows/remove-phase.md": "75c8ca0dbd1ce404",
"gsd-core/workflows/remove-workspace.md": "a9d1dcda7755b6c9", "gsd-core/workflows/remove-workspace.md": "a9d1dcda7755b6c9",
"gsd-core/workflows/resume-project.md": "94ac2cac4c562557", "gsd-core/workflows/resume-project.md": "94ac2cac4c562557",
"gsd-core/workflows/review.md": "8c7288479748235f", "gsd-core/workflows/review.md": "014d2f4d7c892e58",
"gsd-core/workflows/scan.md": "29f3b65f5d9de885", "gsd-core/workflows/scan.md": "29f3b65f5d9de885",
"gsd-core/workflows/secure-phase.md": "858b5e1152b569ed", "gsd-core/workflows/secure-phase.md": "858b5e1152b569ed",
"gsd-core/workflows/session-report.md": "dd8fa011c9394075", "gsd-core/workflows/session-report.md": "dd8fa011c9394075",
@@ -396,7 +397,7 @@
"skills/gsd-quick/SKILL.md": "b4f4e711ba664aa0", "skills/gsd-quick/SKILL.md": "b4f4e711ba664aa0",
"skills/gsd-resume-work/SKILL.md": "04f6c2e5b579e8c4", "skills/gsd-resume-work/SKILL.md": "04f6c2e5b579e8c4",
"skills/gsd-review-backlog/SKILL.md": "469696b944c4e7b5", "skills/gsd-review-backlog/SKILL.md": "469696b944c4e7b5",
"skills/gsd-review/SKILL.md": "06044af5335989dc", "skills/gsd-review/SKILL.md": "a45ab2fdca06793b",
"skills/gsd-secure-phase/SKILL.md": "e64ad269c1e6e319", "skills/gsd-secure-phase/SKILL.md": "e64ad269c1e6e319",
"skills/gsd-settings/SKILL.md": "fcdda8dd545622ae", "skills/gsd-settings/SKILL.md": "fcdda8dd545622ae",
"skills/gsd-ship/SKILL.md": "9615cc4c8f6de060", "skills/gsd-ship/SKILL.md": "9615cc4c8f6de060",

View File

@@ -42,7 +42,7 @@
"gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd", "gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "10226e9512dd44bf", "gsd-core/bin/verify-reapply-patches.cjs": "10226e9512dd44bf",
@@ -116,6 +116,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf", "gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -274,7 +275,7 @@
"gsd-core/workflows/remove-phase.md": "e94ddfe4eabc0e08", "gsd-core/workflows/remove-phase.md": "e94ddfe4eabc0e08",
"gsd-core/workflows/remove-workspace.md": "f28be7f32249f0d4", "gsd-core/workflows/remove-workspace.md": "f28be7f32249f0d4",
"gsd-core/workflows/resume-project.md": "4ebcb4acd3c29302", "gsd-core/workflows/resume-project.md": "4ebcb4acd3c29302",
"gsd-core/workflows/review.md": "58557fe552b6ff89", "gsd-core/workflows/review.md": "7c04ed635c7e1c56",
"gsd-core/workflows/scan.md": "28a2847b8d04156e", "gsd-core/workflows/scan.md": "28a2847b8d04156e",
"gsd-core/workflows/secure-phase.md": "bae509fa254fe435", "gsd-core/workflows/secure-phase.md": "bae509fa254fe435",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -361,7 +362,7 @@
"skills/gsd-quick/SKILL.md": "d66072399c0aa371", "skills/gsd-quick/SKILL.md": "d66072399c0aa371",
"skills/gsd-resume-work/SKILL.md": "e3ab06060bdd9df0", "skills/gsd-resume-work/SKILL.md": "e3ab06060bdd9df0",
"skills/gsd-review-backlog/SKILL.md": "2af20161e555fb42", "skills/gsd-review-backlog/SKILL.md": "2af20161e555fb42",
"skills/gsd-review/SKILL.md": "980080d635e66afe", "skills/gsd-review/SKILL.md": "948c44f78429cb97",
"skills/gsd-secure-phase/SKILL.md": "8666d8933e02c74f", "skills/gsd-secure-phase/SKILL.md": "8666d8933e02c74f",
"skills/gsd-settings/SKILL.md": "4ef66b6dc3a2b8ff", "skills/gsd-settings/SKILL.md": "4ef66b6dc3a2b8ff",
"skills/gsd-ship/SKILL.md": "ea26e3a839afb372", "skills/gsd-ship/SKILL.md": "ea26e3a839afb372",

View File

@@ -85,7 +85,7 @@
"commands/gsd-quick.md": "0061e478a896265d", "commands/gsd-quick.md": "0061e478a896265d",
"commands/gsd-resume-work.md": "a98b447fffe07e1e", "commands/gsd-resume-work.md": "a98b447fffe07e1e",
"commands/gsd-review-backlog.md": "347abbe2fdad79c9", "commands/gsd-review-backlog.md": "347abbe2fdad79c9",
"commands/gsd-review.md": "473b5a21ef15d510", "commands/gsd-review.md": "14369ea01aff093f",
"commands/gsd-secure-phase.md": "1631b1ecedbee373", "commands/gsd-secure-phase.md": "1631b1ecedbee373",
"commands/gsd-settings.md": "8e4a2673e7c96cad", "commands/gsd-settings.md": "8e4a2673e7c96cad",
"commands/gsd-ship.md": "de9d81fe35184ae2", "commands/gsd-ship.md": "de9d81fe35184ae2",
@@ -110,7 +110,7 @@
"gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd", "gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -184,6 +184,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -342,7 +343,7 @@
"gsd-core/workflows/remove-phase.md": "f76e1c2a4dd31a09", "gsd-core/workflows/remove-phase.md": "f76e1c2a4dd31a09",
"gsd-core/workflows/remove-workspace.md": "dadbb14d9033ea3f", "gsd-core/workflows/remove-workspace.md": "dadbb14d9033ea3f",
"gsd-core/workflows/resume-project.md": "3dcaa7abe1800d35", "gsd-core/workflows/resume-project.md": "3dcaa7abe1800d35",
"gsd-core/workflows/review.md": "c12c3029d8640d31", "gsd-core/workflows/review.md": "28d673b6267b12c2",
"gsd-core/workflows/scan.md": "8e1bbf2eed1752ca", "gsd-core/workflows/scan.md": "8e1bbf2eed1752ca",
"gsd-core/workflows/secure-phase.md": "7bd4c335484fd121", "gsd-core/workflows/secure-phase.md": "7bd4c335484fd121",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -430,7 +431,7 @@
"skills/gsd-quick/SKILL.md": "0fdc1838759e2d25", "skills/gsd-quick/SKILL.md": "0fdc1838759e2d25",
"skills/gsd-resume-work/SKILL.md": "492e402cb66b1fcf", "skills/gsd-resume-work/SKILL.md": "492e402cb66b1fcf",
"skills/gsd-review-backlog/SKILL.md": "cf7ff999c96d2f76", "skills/gsd-review-backlog/SKILL.md": "cf7ff999c96d2f76",
"skills/gsd-review/SKILL.md": "8f6496868bb60e10", "skills/gsd-review/SKILL.md": "f5ebef9d2d12b2ad",
"skills/gsd-secure-phase/SKILL.md": "970f53251c7adff7", "skills/gsd-secure-phase/SKILL.md": "970f53251c7adff7",
"skills/gsd-settings/SKILL.md": "c06a8c93de64314e", "skills/gsd-settings/SKILL.md": "c06a8c93de64314e",
"skills/gsd-ship/SKILL.md": "c7eeb21a15c66189", "skills/gsd-ship/SKILL.md": "c7eeb21a15c66189",

View File

@@ -85,7 +85,7 @@
"commands/gsd/quick.toml": "b1f6d47488560def", "commands/gsd/quick.toml": "b1f6d47488560def",
"commands/gsd/resume-work.toml": "5d1e36d643573d4c", "commands/gsd/resume-work.toml": "5d1e36d643573d4c",
"commands/gsd/review-backlog.toml": "19461ca74224422c", "commands/gsd/review-backlog.toml": "19461ca74224422c",
"commands/gsd/review.toml": "b8097bb984942e8e", "commands/gsd/review.toml": "8ce97adf16aec351",
"commands/gsd/secure-phase.toml": "bbf0dc4d648f11fa", "commands/gsd/secure-phase.toml": "bbf0dc4d648f11fa",
"commands/gsd/settings.toml": "5369a6fbdce65ea9", "commands/gsd/settings.toml": "5369a6fbdce65ea9",
"commands/gsd/ship.toml": "fa360f1f63c8adec", "commands/gsd/ship.toml": "fa360f1f63c8adec",
@@ -110,7 +110,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -184,6 +184,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -342,7 +343,7 @@
"gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9", "gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9",
"gsd-core/workflows/remove-workspace.md": "9f5589b4b3a0639a", "gsd-core/workflows/remove-workspace.md": "9f5589b4b3a0639a",
"gsd-core/workflows/resume-project.md": "b18b51fd15cbce95", "gsd-core/workflows/resume-project.md": "b18b51fd15cbce95",
"gsd-core/workflows/review.md": "18ab093986814bb3", "gsd-core/workflows/review.md": "fc23a807c6c3d6d9",
"gsd-core/workflows/scan.md": "54ff1ff60041d065", "gsd-core/workflows/scan.md": "54ff1ff60041d065",
"gsd-core/workflows/secure-phase.md": "a2f6a03034444f14", "gsd-core/workflows/secure-phase.md": "a2f6a03034444f14",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -41,7 +41,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -115,6 +115,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -273,7 +274,7 @@
"gsd-core/workflows/remove-phase.md": "f27cecd8c78008ae", "gsd-core/workflows/remove-phase.md": "f27cecd8c78008ae",
"gsd-core/workflows/remove-workspace.md": "977155e18b9df623", "gsd-core/workflows/remove-workspace.md": "977155e18b9df623",
"gsd-core/workflows/resume-project.md": "849f3d49d366ff13", "gsd-core/workflows/resume-project.md": "849f3d49d366ff13",
"gsd-core/workflows/review.md": "7dd0a479d2595ff0", "gsd-core/workflows/review.md": "d6c1c729a2627b2b",
"gsd-core/workflows/scan.md": "cbde2b8b2b5fa5dd", "gsd-core/workflows/scan.md": "cbde2b8b2b5fa5dd",
"gsd-core/workflows/secure-phase.md": "5fc8fbd5e217e48d", "gsd-core/workflows/secure-phase.md": "5fc8fbd5e217e48d",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -381,7 +382,7 @@
"skills/gsd/gsd-ns-review/skills/debug/SKILL.md": "014bf3421ade2813", "skills/gsd/gsd-ns-review/skills/debug/SKILL.md": "014bf3421ade2813",
"skills/gsd/gsd-ns-review/skills/eval-review/SKILL.md": "609ee9ace8cd424c", "skills/gsd/gsd-ns-review/skills/eval-review/SKILL.md": "609ee9ace8cd424c",
"skills/gsd/gsd-ns-review/skills/forensics/SKILL.md": "d31dc39e02abc929", "skills/gsd/gsd-ns-review/skills/forensics/SKILL.md": "d31dc39e02abc929",
"skills/gsd/gsd-ns-review/skills/review/SKILL.md": "0629aeccf352b059", "skills/gsd/gsd-ns-review/skills/review/SKILL.md": "ace83e30ef7f9060",
"skills/gsd/gsd-ns-review/skills/secure-phase/SKILL.md": "f615390f01694378", "skills/gsd/gsd-ns-review/skills/secure-phase/SKILL.md": "f615390f01694378",
"skills/gsd/gsd-ns-review/skills/ui-phase/SKILL.md": "aac4a77d61281591", "skills/gsd/gsd-ns-review/skills/ui-phase/SKILL.md": "aac4a77d61281591",
"skills/gsd/gsd-ns-review/skills/ui-review/SKILL.md": "ebe37a6d521dba62", "skills/gsd/gsd-ns-review/skills/ui-review/SKILL.md": "ebe37a6d521dba62",

View File

@@ -85,7 +85,7 @@
"command/gsd-quick.md": "704662b2172df14d", "command/gsd-quick.md": "704662b2172df14d",
"command/gsd-resume-work.md": "e4bb44fb2e8076c0", "command/gsd-resume-work.md": "e4bb44fb2e8076c0",
"command/gsd-review-backlog.md": "1e99d6a7a3806fa5", "command/gsd-review-backlog.md": "1e99d6a7a3806fa5",
"command/gsd-review.md": "5f6efc83706fec9b", "command/gsd-review.md": "1e14af38d6d421b3",
"command/gsd-secure-phase.md": "65eb1cd3fa6430a5", "command/gsd-secure-phase.md": "65eb1cd3fa6430a5",
"command/gsd-settings.md": "9bf5d13f13f7d49c", "command/gsd-settings.md": "9bf5d13f13f7d49c",
"command/gsd-ship.md": "c0ae46a2cbc7a2b4", "command/gsd-ship.md": "c0ae46a2cbc7a2b4",
@@ -110,7 +110,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -184,6 +184,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf", "gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -342,7 +343,7 @@
"gsd-core/workflows/remove-phase.md": "f76e1c2a4dd31a09", "gsd-core/workflows/remove-phase.md": "f76e1c2a4dd31a09",
"gsd-core/workflows/remove-workspace.md": "7bd5d1b63ef091a8", "gsd-core/workflows/remove-workspace.md": "7bd5d1b63ef091a8",
"gsd-core/workflows/resume-project.md": "3dcaa7abe1800d35", "gsd-core/workflows/resume-project.md": "3dcaa7abe1800d35",
"gsd-core/workflows/review.md": "268745662d5f5df7", "gsd-core/workflows/review.md": "50e945dade0a5a67",
"gsd-core/workflows/scan.md": "8e1bbf2eed1752ca", "gsd-core/workflows/scan.md": "8e1bbf2eed1752ca",
"gsd-core/workflows/secure-phase.md": "87fdcb37a8610e58", "gsd-core/workflows/secure-phase.md": "87fdcb37a8610e58",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -451,7 +452,7 @@
"skills/gsd-quick/SKILL.md": "605e596c680cbb1c", "skills/gsd-quick/SKILL.md": "605e596c680cbb1c",
"skills/gsd-resume-work/SKILL.md": "0c92e4a51d1b6d94", "skills/gsd-resume-work/SKILL.md": "0c92e4a51d1b6d94",
"skills/gsd-review-backlog/SKILL.md": "27a9dbfe92e5d04c", "skills/gsd-review-backlog/SKILL.md": "27a9dbfe92e5d04c",
"skills/gsd-review/SKILL.md": "7309817dc0d54cef", "skills/gsd-review/SKILL.md": "a967b30f10269e15",
"skills/gsd-secure-phase/SKILL.md": "ceded474164b4e2d", "skills/gsd-secure-phase/SKILL.md": "ceded474164b4e2d",
"skills/gsd-settings/SKILL.md": "4587e4bef7b8942c", "skills/gsd-settings/SKILL.md": "4587e4bef7b8942c",
"skills/gsd-ship/SKILL.md": "4ad9695934e069ee", "skills/gsd-ship/SKILL.md": "4ad9695934e069ee",

View File

@@ -77,7 +77,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -151,6 +151,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -309,7 +310,7 @@
"gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9", "gsd-core/workflows/remove-phase.md": "d030f80ca0df4fa9",
"gsd-core/workflows/remove-workspace.md": "b8817a3a5907f5bc", "gsd-core/workflows/remove-workspace.md": "b8817a3a5907f5bc",
"gsd-core/workflows/resume-project.md": "b18b51fd15cbce95", "gsd-core/workflows/resume-project.md": "b18b51fd15cbce95",
"gsd-core/workflows/review.md": "18ab093986814bb3", "gsd-core/workflows/review.md": "fc23a807c6c3d6d9",
"gsd-core/workflows/scan.md": "54ff1ff60041d065", "gsd-core/workflows/scan.md": "54ff1ff60041d065",
"gsd-core/workflows/secure-phase.md": "1d1c66ad9ea01bd2", "gsd-core/workflows/secure-phase.md": "1d1c66ad9ea01bd2",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -395,7 +396,7 @@
"skills/gsd-quick/SKILL.md": "e6aa7d96326fc874", "skills/gsd-quick/SKILL.md": "e6aa7d96326fc874",
"skills/gsd-resume-work/SKILL.md": "6e83a416db8253e1", "skills/gsd-resume-work/SKILL.md": "6e83a416db8253e1",
"skills/gsd-review-backlog/SKILL.md": "ffc6216cfb6c3002", "skills/gsd-review-backlog/SKILL.md": "ffc6216cfb6c3002",
"skills/gsd-review/SKILL.md": "c248b415238b49ee", "skills/gsd-review/SKILL.md": "9cb8c2bc78c9bc51",
"skills/gsd-secure-phase/SKILL.md": "9aa4378c6371e5e4", "skills/gsd-secure-phase/SKILL.md": "9aa4378c6371e5e4",
"skills/gsd-settings/SKILL.md": "dee7f5011c9a46f4", "skills/gsd-settings/SKILL.md": "dee7f5011c9a46f4",
"skills/gsd-ship/SKILL.md": "b2e10966b6781b95", "skills/gsd-ship/SKILL.md": "b2e10966b6781b95",

View File

@@ -85,7 +85,7 @@
"command/gsd-quick.md": "07c02ab7547aec8e", "command/gsd-quick.md": "07c02ab7547aec8e",
"command/gsd-resume-work.md": "3ac18b2a8cc41066", "command/gsd-resume-work.md": "3ac18b2a8cc41066",
"command/gsd-review-backlog.md": "1e99d6a7a3806fa5", "command/gsd-review-backlog.md": "1e99d6a7a3806fa5",
"command/gsd-review.md": "e1aee41cc2d736b5", "command/gsd-review.md": "97bf8bc6ffff9475",
"command/gsd-secure-phase.md": "b536ad6e68af3a26", "command/gsd-secure-phase.md": "b536ad6e68af3a26",
"command/gsd-settings.md": "a3d2cb48b06c9b90", "command/gsd-settings.md": "a3d2cb48b06c9b90",
"command/gsd-ship.md": "062d0bb5656fa31b", "command/gsd-ship.md": "062d0bb5656fa31b",
@@ -110,7 +110,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -184,6 +184,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf", "gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -342,7 +343,7 @@
"gsd-core/workflows/remove-phase.md": "863c58e99e9d630d", "gsd-core/workflows/remove-phase.md": "863c58e99e9d630d",
"gsd-core/workflows/remove-workspace.md": "4ed03c52e5c7bd4d", "gsd-core/workflows/remove-workspace.md": "4ed03c52e5c7bd4d",
"gsd-core/workflows/resume-project.md": "15153ce5a4c38674", "gsd-core/workflows/resume-project.md": "15153ce5a4c38674",
"gsd-core/workflows/review.md": "dd336f71a0b8f228", "gsd-core/workflows/review.md": "544103be3247bbd1",
"gsd-core/workflows/scan.md": "4634caefa32a7307", "gsd-core/workflows/scan.md": "4634caefa32a7307",
"gsd-core/workflows/secure-phase.md": "9616682fe23cf042", "gsd-core/workflows/secure-phase.md": "9616682fe23cf042",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -451,7 +452,7 @@
"skills/gsd-quick/SKILL.md": "a9a971a0d471b64f", "skills/gsd-quick/SKILL.md": "a9a971a0d471b64f",
"skills/gsd-resume-work/SKILL.md": "aa6a7d9e88fe26b6", "skills/gsd-resume-work/SKILL.md": "aa6a7d9e88fe26b6",
"skills/gsd-review-backlog/SKILL.md": "27a9dbfe92e5d04c", "skills/gsd-review-backlog/SKILL.md": "27a9dbfe92e5d04c",
"skills/gsd-review/SKILL.md": "9fe549f07cf4da07", "skills/gsd-review/SKILL.md": "4d1897f8d2c65bdf",
"skills/gsd-secure-phase/SKILL.md": "b37a0dbae84dd74a", "skills/gsd-secure-phase/SKILL.md": "b37a0dbae84dd74a",
"skills/gsd-settings/SKILL.md": "d72a537765bf690a", "skills/gsd-settings/SKILL.md": "d72a537765bf690a",
"skills/gsd-ship/SKILL.md": "fc88192bae429756", "skills/gsd-ship/SKILL.md": "fc88192bae429756",

View File

@@ -41,7 +41,7 @@
"gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249", "gsd-core/bin/gsd-tools.cjs": "b7968e3e3af00249",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -115,6 +115,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -273,7 +274,7 @@
"gsd-core/workflows/remove-phase.md": "17c46fdcef27df2d", "gsd-core/workflows/remove-phase.md": "17c46fdcef27df2d",
"gsd-core/workflows/remove-workspace.md": "1d34788a9b2272d2", "gsd-core/workflows/remove-workspace.md": "1d34788a9b2272d2",
"gsd-core/workflows/resume-project.md": "bba3250afbea8f09", "gsd-core/workflows/resume-project.md": "bba3250afbea8f09",
"gsd-core/workflows/review.md": "3d7c8df929053b79", "gsd-core/workflows/review.md": "926f2f15676a21cc",
"gsd-core/workflows/scan.md": "514d3eba81565193", "gsd-core/workflows/scan.md": "514d3eba81565193",
"gsd-core/workflows/secure-phase.md": "a7e8edb0e5f48256", "gsd-core/workflows/secure-phase.md": "a7e8edb0e5f48256",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -380,7 +381,7 @@
"skills/gsd-ns-review/skills/debug/SKILL.md": "42de44884d97d86d", "skills/gsd-ns-review/skills/debug/SKILL.md": "42de44884d97d86d",
"skills/gsd-ns-review/skills/eval-review/SKILL.md": "b6b6059061388363", "skills/gsd-ns-review/skills/eval-review/SKILL.md": "b6b6059061388363",
"skills/gsd-ns-review/skills/forensics/SKILL.md": "4ef11f4cf902186f", "skills/gsd-ns-review/skills/forensics/SKILL.md": "4ef11f4cf902186f",
"skills/gsd-ns-review/skills/review/SKILL.md": "a17c6ffbcde6071a", "skills/gsd-ns-review/skills/review/SKILL.md": "3202c2f3f3ba6759",
"skills/gsd-ns-review/skills/secure-phase/SKILL.md": "a6adf4729b606d5a", "skills/gsd-ns-review/skills/secure-phase/SKILL.md": "a6adf4729b606d5a",
"skills/gsd-ns-review/skills/ui-phase/SKILL.md": "7c9404102a9b9d74", "skills/gsd-ns-review/skills/ui-phase/SKILL.md": "7c9404102a9b9d74",
"skills/gsd-ns-review/skills/ui-review/SKILL.md": "ef8f643abff1486b", "skills/gsd-ns-review/skills/ui-review/SKILL.md": "ef8f643abff1486b",

View File

@@ -41,7 +41,7 @@
"gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd", "gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -115,6 +115,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -273,7 +274,7 @@
"gsd-core/workflows/remove-phase.md": "5a2521695edd486b", "gsd-core/workflows/remove-phase.md": "5a2521695edd486b",
"gsd-core/workflows/remove-workspace.md": "ed8e5e30c33f1bfd", "gsd-core/workflows/remove-workspace.md": "ed8e5e30c33f1bfd",
"gsd-core/workflows/resume-project.md": "ee9dcc4e3dd3e32c", "gsd-core/workflows/resume-project.md": "ee9dcc4e3dd3e32c",
"gsd-core/workflows/review.md": "402fcc0b4b6a2794", "gsd-core/workflows/review.md": "6529c2ee9b33f1fc",
"gsd-core/workflows/scan.md": "afc48f3339293b30", "gsd-core/workflows/scan.md": "afc48f3339293b30",
"gsd-core/workflows/secure-phase.md": "882886f04d3b7e82", "gsd-core/workflows/secure-phase.md": "882886f04d3b7e82",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
@@ -358,7 +359,7 @@
"skills/gsd-ns-review/skills/debug/SKILL.md": "9d814fba870c538e", "skills/gsd-ns-review/skills/debug/SKILL.md": "9d814fba870c538e",
"skills/gsd-ns-review/skills/eval-review/SKILL.md": "d42b504c0ca2dc69", "skills/gsd-ns-review/skills/eval-review/SKILL.md": "d42b504c0ca2dc69",
"skills/gsd-ns-review/skills/forensics/SKILL.md": "250f476c4c547a0f", "skills/gsd-ns-review/skills/forensics/SKILL.md": "250f476c4c547a0f",
"skills/gsd-ns-review/skills/review/SKILL.md": "ace2ad1db5c625c6", "skills/gsd-ns-review/skills/review/SKILL.md": "c89722cb096066d4",
"skills/gsd-ns-review/skills/secure-phase/SKILL.md": "b35ac9da51635368", "skills/gsd-ns-review/skills/secure-phase/SKILL.md": "b35ac9da51635368",
"skills/gsd-ns-review/skills/ui-phase/SKILL.md": "89a29a2fa62b177e", "skills/gsd-ns-review/skills/ui-phase/SKILL.md": "89a29a2fa62b177e",
"skills/gsd-ns-review/skills/ui-review/SKILL.md": "3e23efe03dafd691", "skills/gsd-ns-review/skills/ui-review/SKILL.md": "3e23efe03dafd691",

View File

@@ -41,7 +41,7 @@
"gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd", "gsd-core/bin/gsd-tools.cjs": "46deb2174be356dd",
"gsd-core/bin/gsd_run": "62d9b647ede212e6", "gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16", "gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "67e4addbfd248a7c", "gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6", "gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4", "gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904", "gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
@@ -115,6 +115,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71", "gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a", "gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679", "gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df", "gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172", "gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8", "gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -273,7 +274,7 @@
"gsd-core/workflows/remove-phase.md": "24559d23e008c9c3", "gsd-core/workflows/remove-phase.md": "24559d23e008c9c3",
"gsd-core/workflows/remove-workspace.md": "e958c1e932aef492", "gsd-core/workflows/remove-workspace.md": "e958c1e932aef492",
"gsd-core/workflows/resume-project.md": "c5731b8aabed70f9", "gsd-core/workflows/resume-project.md": "c5731b8aabed70f9",
"gsd-core/workflows/review.md": "77124fdbb3e3bc7e", "gsd-core/workflows/review.md": "21152d6ce0c4efa8",
"gsd-core/workflows/scan.md": "8aa95448b1ba4a4a", "gsd-core/workflows/scan.md": "8aa95448b1ba4a4a",
"gsd-core/workflows/secure-phase.md": "550152cd82c25c00", "gsd-core/workflows/secure-phase.md": "550152cd82c25c00",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -0,0 +1,48 @@
'use strict';
/**
* Config whitelist gate for review.reviewer_instances (#1517).
*
* Behavioral test (not source-grep): proves `config-set` accepts the
* review.reviewer_instances.<name>.{cli,model,agent} paths. Without the
* dynamicKeyPatterns entry in config-schema.manifest.json, config-set rejects
* the key and this test fails — that is the regression-must-fail-first signal.
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const path = require('node:path');
const fs = require('node:fs');
const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs');
describe('config-set review.reviewer_instances (#1517)', () => {
test('accepts a known-adapter cli for an instance', (t) => {
const tmpDir = createTempProject('reviewer-instances-cli');
t.after(() => cleanup(tmpDir));
const result = runGsdTools('config-set review.reviewer_instances.opencode-deepseek.cli opencode', tmpDir);
assert.ok(result.success, `config-set should accept the instance cli path: ${result.error || JSON.stringify(result)}`);
const configPath = path.join(tmpDir, '.planning', 'config.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
assert.strictEqual(
config.review?.reviewer_instances?.['opencode-deepseek']?.cli,
'opencode',
'instance cli must persist',
);
});
test('accepts model and agent fields for an instance', (t) => {
const tmpDir = createTempProject('reviewer-instances-model');
t.after(() => cleanup(tmpDir));
const modelRes = runGsdTools('config-set review.reviewer_instances.opencode-deepseek.model deepseek/deepseek-v4-pro', tmpDir);
assert.ok(modelRes.success, `model set failed: ${modelRes.error}`);
const agentRes = runGsdTools('config-set review.reviewer_instances.opencode-deepseek.agent review', tmpDir);
assert.ok(agentRes.success, `agent set failed: ${agentRes.error}`);
const configPath = path.join(tmpDir, '.planning', 'config.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
assert.strictEqual(config.review.reviewer_instances['opencode-deepseek'].model, 'deepseek/deepseek-v4-pro');
assert.strictEqual(config.review.reviewer_instances['opencode-deepseek'].agent, 'review');
});
});

View File

@@ -0,0 +1,234 @@
'use strict';
/**
* Reviewer Instances feature (#1517) — custom reviewer instances for /gsd:review.
*
* Locks the instance-resolution contract:
* - normalizeReviewerInstances (config-set validation surface)
* - resolveReviewerSelection instance expansion (config_default branch only)
* - single-source instance→cli resolution parity (DEFECT.GENERATIVE-FIX)
*
* Regression-must-fail-first: these tests are written before the implementation
* and must demonstrate the failure (missing export / missing behaviour) before
* the resolver is extended.
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const {
KNOWN_REVIEWER_SLUGS,
normalizeReviewerInstances,
resolveReviewerSelection,
} = require('../gsd-core/bin/lib/review-reviewer-selection.cjs');
describe('normalizeReviewerInstances (#1517)', () => {
test('accepts a valid instance map and normalizes fields', () => {
const r = normalizeReviewerInstances({
'opencode-deepseek': { cli: 'opencode', model: 'deepseek/deepseek-v4-pro', agent: 'review' },
'codex-fast': { cli: 'codex', model: 'gpt-5-mini' },
});
assert.deepStrictEqual(r.errors, []);
assert.ok(r.instances['opencode-deepseek']);
assert.strictEqual(r.instances['opencode-deepseek'].cli, 'opencode');
assert.strictEqual(r.instances['opencode-deepseek'].model, 'deepseek/deepseek-v4-pro');
assert.strictEqual(r.instances['opencode-deepseek'].agent, 'review');
assert.strictEqual(r.instances['codex-fast'].agent, undefined);
});
test('absent (undefined/null) yields an empty instance set with no errors', () => {
assert.deepStrictEqual(normalizeReviewerInstances(undefined), { instances: {}, errors: [] });
assert.deepStrictEqual(normalizeReviewerInstances(null), { instances: {}, errors: [] });
});
test('rejects a non-object value', () => {
const r = normalizeReviewerInstances('nope');
assert.ok(r.errors.length > 0);
assert.deepStrictEqual(r.instances, {});
});
test('rejects an instance name that does not match the slug pattern', () => {
const r = normalizeReviewerInstances({
'Opencode_Bad': { cli: 'opencode' }, // uppercase + underscore
'opencode deepseek': { cli: 'opencode' }, // space
'9lead': { cli: 'opencode' }, // leading digit is allowed; sanity below
});
// ^[a-z0-9][a-z0-9-]*$ → '9lead' is valid; the other two are not.
assert.ok(r.errors.some((e) => e.includes('Opencode_Bad')), `got: ${JSON.stringify(r.errors)}`);
assert.ok(r.errors.some((e) => e.includes('opencode deepseek')), `got: ${JSON.stringify(r.errors)}`);
assert.ok(r.instances['9lead'], 'leading-digit names are permitted by the pattern');
});
test('rejects an instance name that collides with a built-in reviewer slug', () => {
const r = normalizeReviewerInstances({
opencode: { cli: 'opencode' }, // shadows a built-in slug
});
assert.ok(
r.errors.some((e) => /must not equal a built-in reviewer slug/i.test(e) && e.includes('opencode')),
`got: ${JSON.stringify(r.errors)}`,
);
assert.ok(!r.instances['opencode']);
});
test('rejects an instance whose cli is not a known adapter', () => {
const r = normalizeReviewerInstances({
'evil-instance': { cli: 'rm -rf /' }, // not a known slug; must not become a shell command
'weird-instance': { cli: 'totally-made-up' },
});
assert.ok(r.errors.some((e) => e.includes('evil-instance')), `got: ${JSON.stringify(r.errors)}`);
assert.ok(r.errors.some((e) => e.includes('weird-instance')), `got: ${JSON.stringify(r.errors)}`);
});
test('rejects an instance with a missing cli', () => {
const r = normalizeReviewerInstances({
'no-cli': { model: 'some/model' },
});
assert.ok(r.errors.some((e) => e.includes('no-cli') && /cli/i.test(e)), `got: ${JSON.stringify(r.errors)}`);
});
test('rejects non-string model / agent values', () => {
const r = normalizeReviewerInstances({
'bad-model': { cli: 'opencode', model: 42 },
'bad-agent': { cli: 'opencode', agent: { x: 1 } },
});
assert.ok(r.errors.some((e) => e.includes('bad-model')), `got: ${JSON.stringify(r.errors)}`);
assert.ok(r.errors.some((e) => e.includes('bad-agent')), `got: ${JSON.stringify(r.errors)}`);
});
});
describe('resolveReviewerSelection — instance expansion (#1517)', () => {
const INSTANCES = {
'opencode-deepseek': { cli: 'opencode', model: 'deepseek/deepseek-v4-pro', agent: 'review' },
'opencode-mimo': { cli: 'opencode', model: 'xiaomi/mimo-v2.5-pro' },
};
test('two same-cli instances in default_reviewers resolve as independent identities and flag the shared adapter', () => {
const r = resolveReviewerSelection({
detected: ['opencode', 'codex'],
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: ['opencode-deepseek', 'opencode-mimo', 'codex'],
reviewerInstances: INSTANCES,
});
assert.strictEqual(r.source, 'config_default');
// selected carries all three identities (codex is a builtin slug)
assert.ok(r.selected.includes('opencode-deepseek'));
assert.ok(r.selected.includes('opencode-mimo'));
assert.ok(r.selected.includes('codex'));
// resolvedInstances carries the instance→cli mapping (single-source parity anchor)
const ds = r.resolvedInstances.find((x) => x.identity === 'opencode-deepseek');
const mimo = r.resolvedInstances.find((x) => x.identity === 'opencode-mimo');
assert.ok(ds, 'opencode-deepseek must be resolved');
assert.ok(mimo, 'opencode-mimo must be resolved');
assert.strictEqual(ds.kind, 'instance');
assert.strictEqual(ds.cli, 'opencode');
assert.strictEqual(ds.model, 'deepseek/deepseek-v4-pro');
assert.strictEqual(ds.agent, 'review');
assert.strictEqual(mimo.cli, 'opencode');
// ≥2 selected instances share a cli → caveat flag set
assert.ok(r.sharedAdapterCaveat, 'two opencode instances must set sharedAdapterCaveat');
assert.deepStrictEqual(r.errors, []);
});
test('a single same-cli instance does not trip the shared-adapter caveat', () => {
const r = resolveReviewerSelection({
detected: ['opencode', 'codex'],
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: ['opencode-deepseek', 'codex'],
reviewerInstances: INSTANCES,
});
assert.ok(!r.sharedAdapterCaveat);
});
test('an instance referenced in default_reviewers with no definition is a HARD error when instances are configured', () => {
const r = resolveReviewerSelection({
detected: ['opencode'],
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: ['opencode-deepseek', 'typo-instance'],
reviewerInstances: INSTANCES,
});
assert.ok(
r.errors.some((e) => e.includes('typo-instance')),
`expected a hard error naming the undefined instance, got: ${JSON.stringify(r.errors)}`,
);
assert.ok(!r.selected.includes('typo-instance'));
});
test('backward compat: with no instances configured, an unknown slug still warns + drops (not a hard error)', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: ['unknown_slug', 'codex'],
});
assert.ok(
r.warnings.some((w) => w.includes('unknown_slug')),
`expected warn+drop for unknown slug when no instances configured, got: ${JSON.stringify(r.warnings)}`,
);
assert.ok(
!r.errors.some((e) => e.includes('unknown_slug')),
'unknown slug must NOT be a hard error when no instances are configured',
);
});
test('an instance whose base cli is not detected is excluded with an info note', () => {
const r = resolveReviewerSelection({
detected: ['codex'], // opencode not installed
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: ['opencode-deepseek', 'codex'],
reviewerInstances: INSTANCES,
});
assert.ok(!r.selected.includes('opencode-deepseek'));
assert.ok(
r.infos.some((i) => i.includes('opencode-deepseek')),
`expected an info note for the undetected instance, got: ${JSON.stringify(r.infos)}`,
);
assert.ok(r.selected.includes('codex'));
});
test('instances do NOT participate in the explicit_flags or all_flag branches', () => {
const explicit = resolveReviewerSelection({
detected: ['opencode'],
explicitFlags: ['opencode'],
allFlag: false,
configuredDefaultReviewers: ['opencode-deepseek'],
reviewerInstances: INSTANCES,
});
assert.strictEqual(explicit.source, 'explicit_flags');
assert.ok(!explicit.selected.includes('opencode-deepseek'), 'instances must not leak into explicit_flags');
const all = resolveReviewerSelection({
detected: ['opencode'],
explicitFlags: [],
allFlag: true,
configuredDefaultReviewers: ['opencode-deepseek'],
reviewerInstances: INSTANCES,
});
assert.strictEqual(all.source, 'all_flag');
assert.ok(!all.selected.includes('opencode-deepseek'), 'instances must not leak into all_flag');
});
test('parity (DEFECT.GENERATIVE-FIX): every resolved instance cli equals its configured cli field', () => {
const r = resolveReviewerSelection({
detected: ['opencode', 'codex'],
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: ['opencode-deepseek', 'opencode-mimo', 'codex'],
reviewerInstances: INSTANCES,
});
for (const res of r.resolvedInstances) {
if (res.kind === 'instance') {
const configured = INSTANCES[res.identity];
assert.ok(configured, `resolved instance ${res.identity} has no configured definition`);
assert.strictEqual(res.cli, configured.cli, `cli mapping diverged for ${res.identity}`);
assert.strictEqual(res.model, configured.model, `model diverged for ${res.identity}`);
assert.strictEqual(res.agent, configured.agent, `agent diverged for ${res.identity}`);
} else {
assert.ok(KNOWN_REVIEWER_SLUGS.includes(res.identity), `builtin identity ${res.identity} is not a known slug`);
}
}
});
});

View File

@@ -63,7 +63,7 @@
"remove-phase.md": 8469, "remove-phase.md": 8469,
"remove-workspace.md": 7507, "remove-workspace.md": 7507,
"resume-project.md": 17226, "resume-project.md": 17226,
"review.md": 39404, "review.md": 40539,
"scan.md": 7688, "scan.md": 7688,
"secure-phase.md": 13476, "secure-phase.md": 13476,
"session-report.md": 4044, "session-report.md": 4044,