@bridge_gpt/mcp-server 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -23,6 +23,8 @@ import { VERSION } from "./version.generated.js";
23
23
  import { checkForUpdate } from "./update-check.js";
24
24
  import { reconstructAgentMarkdown, translateAgentToCopilot } from "./agent-utils.js";
25
25
  import { resolveRecipe, loadCustomPipelines } from "./pipeline-utils.js";
26
+ import { runStartTicketsCli } from "./start-tickets.js";
27
+ import { runDoctorCli } from "./doctor.js";
26
28
  import { generateDecisionPageHtml } from "./decision-page-template.js";
27
29
  import { DecisionPageInputShape } from "./decision-page-schema.js";
28
30
  import { runPipeline, resumePipeline, listPipelineRuns, deletePipelineRun, } from "./pipeline-orchestrator.js";
@@ -610,41 +612,54 @@ body explicitly says to serialize structured output.
610
612
  }
611
613
  }
612
614
  // ---------------------------------------------------------------------------
613
- // CLI: --init
615
+ // CLI subcommand dispatch
614
616
  // ---------------------------------------------------------------------------
615
- if (process.argv.includes("--init")) {
617
+ //
618
+ // `--init`, `--upgrade`, and the positional `start-tickets` subcommand are all
619
+ // routed through a single ``dispatchCliSubcommand`` guard that runs and exits
620
+ // BEFORE the MCP server is constructed and connected. This keeps the single
621
+ // existing ``bridge-api-mcp-server`` bin and leaves a clean seam for future
622
+ // subcommands.
623
+ /**
624
+ * Ensure a ``package.json`` exists in ``cwd`` for CLI commands that scaffold
625
+ * into a project. Returns ``null`` on success, or the exact user-facing error
626
+ * string (preserved verbatim from the previous standalone guards).
627
+ */
628
+ async function ensurePackageJsonForCliCommand(flagName, cwd) {
616
629
  try {
617
- await stat(path.join(process.cwd(), "package.json"));
630
+ await stat(path.join(cwd, "package.json"));
631
+ return null;
618
632
  }
619
633
  catch {
620
- console.error("Error: No package.json found in current directory.\n" +
621
- "--init must be run from your project root (the directory containing package.json).");
622
- process.exit(1);
634
+ return ("Error: No package.json found in current directory.\n" +
635
+ `${flagName} must be run from your project root (the directory containing package.json).`);
636
+ }
637
+ }
638
+ /** Run the ``--init`` scaffolding flow. Returns a process exit code. */
639
+ async function runInitCli(cwd) {
640
+ const guardError = await ensurePackageJsonForCliCommand("--init", cwd);
641
+ if (guardError) {
642
+ console.error(guardError);
643
+ return 1;
623
644
  }
624
645
  try {
625
- await runInit(process.cwd());
626
- process.exit(0);
646
+ await runInit(cwd);
647
+ return 0;
627
648
  }
628
649
  catch (err) {
629
650
  const msg = err instanceof Error ? err.message : String(err);
630
651
  console.error(`Bridge API --init failed: ${msg}`);
631
- process.exit(1);
652
+ return 1;
632
653
  }
633
654
  }
634
- // ---------------------------------------------------------------------------
635
- // CLI: --upgrade
636
- // ---------------------------------------------------------------------------
637
- if (process.argv.includes("--upgrade")) {
638
- try {
639
- await stat(path.join(process.cwd(), "package.json"));
640
- }
641
- catch {
642
- console.error("Error: No package.json found in current directory.\n" +
643
- "--upgrade must be run from your project root (the directory containing package.json).");
644
- process.exit(1);
655
+ /** Run the ``--upgrade`` flow (npm install latest + re-scaffold). */
656
+ async function runUpgradeCli(cwd) {
657
+ const guardError = await ensurePackageJsonForCliCommand("--upgrade", cwd);
658
+ if (guardError) {
659
+ console.error(guardError);
660
+ return 1;
645
661
  }
646
662
  try {
647
- const cwd = process.cwd();
648
663
  const oldVersion = VERSION;
649
664
  console.log("Upgrading @bridge_gpt/mcp-server to latest...\n");
650
665
  execSync("npm i @bridge_gpt/mcp-server@latest", { stdio: "inherit" });
@@ -660,14 +675,52 @@ if (process.argv.includes("--upgrade")) {
660
675
  console.log("\nRefreshing scaffolded artifacts...\n");
661
676
  await runInit(cwd);
662
677
  console.log("\nUpgrade complete.");
663
- process.exit(0);
678
+ return 0;
664
679
  }
665
680
  catch (err) {
666
681
  const msg = err instanceof Error ? err.message : String(err);
667
682
  console.error(`Bridge API --upgrade failed: ${msg}`);
668
- process.exit(1);
683
+ return 1;
669
684
  }
670
685
  }
686
+ /**
687
+ * Route CLI subcommands before MCP server startup. Returns an exit code to
688
+ * exit the process with, or ``null`` to continue to normal MCP server startup.
689
+ *
690
+ * ``--init`` takes precedence over ``--upgrade`` (both are position-independent
691
+ * flags); ``start-tickets`` is a positional subcommand. Any other unknown,
692
+ * non-flag positional first token is rejected.
693
+ */
694
+ async function dispatchCliSubcommand(argv) {
695
+ const cwd = process.cwd();
696
+ // A positional subcommand owns the rest of argv, so e.g. `start-tickets --init`
697
+ // is a start-tickets invocation, not an --init one. Check it before the
698
+ // position-independent --init / --upgrade flag guards.
699
+ if (argv[0] === "start-tickets") {
700
+ return runStartTicketsCli(argv.slice(1));
701
+ }
702
+ // The read-only `doctor` subcommand is routed beside start-tickets, before the
703
+ // flag guards and well before MCP server construction (it never starts the server).
704
+ if (argv[0] === "doctor") {
705
+ return runDoctorCli(argv.slice(1));
706
+ }
707
+ // --init takes precedence over --upgrade; both are position-independent flags.
708
+ if (argv.includes("--init")) {
709
+ return runInitCli(cwd);
710
+ }
711
+ if (argv.includes("--upgrade")) {
712
+ return runUpgradeCli(cwd);
713
+ }
714
+ if (argv.length > 0 && !argv[0].startsWith("-")) {
715
+ console.error(`Error: Unknown subcommand '${argv[0]}'. Run with --help for usage, or omit subcommands to start the MCP server.`);
716
+ return 1;
717
+ }
718
+ return null;
719
+ }
720
+ const cliExitCode = await dispatchCliSubcommand(process.argv.slice(2));
721
+ if (cliExitCode !== null) {
722
+ process.exit(cliExitCode);
723
+ }
671
724
  // ---------------------------------------------------------------------------
672
725
  // Server
673
726
  // ---------------------------------------------------------------------------
@@ -849,7 +902,8 @@ registerTool("get_tickets", {
849
902
  registerTool("get_ticket", {
850
903
  description: "Retrieve full details for a single Jira ticket by its key. " +
851
904
  "Returns summary, status, type, assignee, reporter, description, and timestamps. " +
852
- "All data is fetched live from Jira. Use get_tickets to search/list multiple tickets.",
905
+ "All data is fetched live from Jira. Use get_tickets to search/list multiple tickets. " +
906
+ "Use get_comments to fetch comments on the ticket.",
853
907
  inputSchema: {
854
908
  ticket_number: z
855
909
  .string()
@@ -861,6 +915,23 @@ registerTool("get_ticket", {
861
915
  const text = await handleResponse(resp);
862
916
  return { content: [{ type: "text", text }] };
863
917
  });
918
+ registerTool("get_comments", {
919
+ description: "Retrieve all comments on a Jira ticket, oldest-first. " +
920
+ "Returns an array of {id, author, body, created, updated}. " +
921
+ "Comment bodies are Markdown (converted from Jira wiki markup). " +
922
+ "Use this to read what a developer or stakeholder has said on a ticket. " +
923
+ "Use add_comment to post a new comment.",
924
+ inputSchema: {
925
+ ticket_number: z
926
+ .string()
927
+ .describe("Jira ticket key in PROJECT-NUMBER format (e.g. PROJ-123)"),
928
+ },
929
+ }, async ({ ticket_number }) => {
930
+ const url = buildGetUrl(`/tickets/${encodeURIComponent(ticket_number)}/comments`, { repo_name: REPO_NAME });
931
+ const resp = await fetch(url, { headers: GET_HEADERS });
932
+ const text = await handleResponse(resp);
933
+ return { content: [{ type: "text", text }] };
934
+ });
864
935
  registerTool("create_ticket", {
865
936
  description: "Create a new Jira ticket in the configured project. Requires either description or file_path (or both — file_path takes precedence). " +
866
937
  "Returns JSON with {ticket_key: 'PROJ-123', url: 'https://...'}. " +
@@ -1971,6 +2042,8 @@ const VALID_CONFIG_FIELDS = [
1971
2042
  "template_correctness_standards", "style_correctness_standards",
1972
2043
  "design_principles",
1973
2044
  "post_pr_target_status", "ci_check_config", "ci_followup_config",
2045
+ "allow_mutating_smoke_ops",
2046
+ "selected_mcp_slugs",
1974
2047
  ].join(", ");
1975
2048
  registerTool("list_config_fields", {
1976
2049
  description: "List all configurable fields available for reading and updating via the Bridge API. " +
@@ -2016,18 +2089,101 @@ registerTool("update_config_field", {
2016
2089
  "Returns 400 if the field name is invalid, 404 if the repository has no configuration row yet.",
2017
2090
  inputSchema: {
2018
2091
  field_name: z.string().describe(`The configuration field to update. Valid options: ${VALID_CONFIG_FIELDS}`),
2019
- value: z.string().optional().describe("The new value for the configuration field. Provide either value or file_path, not both. " +
2020
- "Omit both value and file_path to set the field to NULL (clearing it)."),
2092
+ value: z.union([z.string(), z.boolean(), z.array(z.string())]).optional().describe("The new value for the configuration field. Provide either value or file_path, not both. " +
2093
+ "Most fields take a string; scalar boolean fields (e.g. allow_mutating_smoke_ops) take true/false. " +
2094
+ "The selected_mcp_slugs field takes a JSON array of supported MCP validation manual slug strings " +
2095
+ "(e.g. [\"b2c-commerce-developer\", \"playwright-mcp\", \"pwa-kit-mcp\"]) — pass an array of strings, " +
2096
+ "not a comma-delimited string; an empty array clears the selection. " +
2097
+ "For string fields, omit both value and file_path to set the field to NULL (clearing it). " +
2098
+ "Scalar boolean fields are NOT NULL and have no clear/null state: omitting the value writes false " +
2099
+ "(matching the API-layer coercion), so pass true/false explicitly."),
2021
2100
  file_path: z.string().optional().describe("Path to a local file whose contents will be used as the new value. " +
2022
2101
  "Useful for large configuration values like detailed review instructions. " +
2023
- "The file must be UTF-8 encoded and under 1MB."),
2102
+ "The file must be UTF-8 encoded and under 1MB. " +
2103
+ "Not supported for scalar boolean fields like allow_mutating_smoke_ops."),
2024
2104
  },
2025
2105
  }, async ({ field_name, value, file_path }) => {
2106
+ // JSONB array config fields (e.g. selected_mcp_slugs): forward the array value
2107
+ // as JSON. Never join into a comma-delimited string — the backend expects a
2108
+ // real JSON array and validates each slug against the mcp_docs allowlist.
2109
+ const ARRAY_CONFIG_FIELDS = ["selected_mcp_slugs"];
2110
+ if (ARRAY_CONFIG_FIELDS.includes(field_name)) {
2111
+ if (file_path) {
2112
+ return {
2113
+ isError: true,
2114
+ content: [{
2115
+ type: "text",
2116
+ text: JSON.stringify({
2117
+ error: `'${field_name}' is a JSON array field; file_path updates are not supported. Pass value as an array of slug strings.`,
2118
+ }),
2119
+ }],
2120
+ };
2121
+ }
2122
+ // An omitted value clears the selection (empty array). Any defined value is
2123
+ // forwarded verbatim as JSON so the backend can validate/reject it.
2124
+ const arrayValue = value === undefined ? [] : value;
2125
+ const resp = await fetch(buildUrl(`/config-field/${encodeURIComponent(field_name)}`), {
2126
+ method: "PUT",
2127
+ headers: POST_HEADERS,
2128
+ body: JSON.stringify({ repo_name: REPO_NAME, value: arrayValue }),
2129
+ });
2130
+ const text = await handleResponse(resp);
2131
+ return { content: [{ type: "text", text }] };
2132
+ }
2133
+ // Scalar boolean config fields: reject file-path updates and normalize boolean
2134
+ // true/false and string "true"/"false" to a real boolean before persisting.
2135
+ const BOOLEAN_CONFIG_FIELDS = ["allow_mutating_smoke_ops"];
2136
+ if (BOOLEAN_CONFIG_FIELDS.includes(field_name)) {
2137
+ if (file_path) {
2138
+ return {
2139
+ isError: true,
2140
+ content: [{
2141
+ type: "text",
2142
+ text: JSON.stringify({
2143
+ error: `'${field_name}' is a scalar boolean field; file_path updates are not supported. Pass value: true or value: false.`,
2144
+ }),
2145
+ }],
2146
+ };
2147
+ }
2148
+ // NOT NULL boolean column: an omitted value writes false (no clear/null state),
2149
+ // intentionally aligned with the API-layer coercion in update_config_field_endpoint.
2150
+ let boolValue = false;
2151
+ if (typeof value === "boolean") {
2152
+ boolValue = value;
2153
+ }
2154
+ else if (typeof value === "string") {
2155
+ const normalized = value.trim().toLowerCase();
2156
+ if (normalized === "true") {
2157
+ boolValue = true;
2158
+ }
2159
+ else if (normalized === "false" || normalized === "") {
2160
+ boolValue = false;
2161
+ }
2162
+ else {
2163
+ return {
2164
+ isError: true,
2165
+ content: [{
2166
+ type: "text",
2167
+ text: JSON.stringify({
2168
+ error: `Invalid value for '${field_name}': '${value}'. Expected true or false.`,
2169
+ }),
2170
+ }],
2171
+ };
2172
+ }
2173
+ }
2174
+ const resp = await fetch(buildUrl(`/config-field/${encodeURIComponent(field_name)}`), {
2175
+ method: "PUT",
2176
+ headers: POST_HEADERS,
2177
+ body: JSON.stringify({ repo_name: REPO_NAME, value: boolValue }),
2178
+ });
2179
+ const text = await handleResponse(resp);
2180
+ return { content: [{ type: "text", text }] };
2181
+ }
2026
2182
  // Allow omitting both value and file_path to set NULL
2027
2183
  let finalValue = null;
2028
2184
  let note = "";
2029
2185
  if (value || file_path) {
2030
- const resolved = await resolveTextOrFile(value, file_path, "value");
2186
+ const resolved = await resolveTextOrFile(typeof value === "string" ? value : undefined, file_path, "value");
2031
2187
  if (!resolved.ok)
2032
2188
  return resolved.errorResponse;
2033
2189
  finalValue = resolved.text;
@@ -511,7 +511,7 @@ export const INSTRUCTIONS = {
511
511
  "learn-documentation-instructions.md": "## Objective\n\nExplore the codebase to identify implementation documentation patterns — the markdown records that document what was built, why, and when — then draft `documentation_instructions` for the project config.\n\n## Instructions\n\n### Phase 1 — Explore Implementation Record Patterns\n\nFocus on how the project records what was built, why, and when. These records serve as persistent project memory. Code-level documentation (docstrings, inline comments) is handled by correctness standards, not here.\n\n1. **Implementation Record Discovery**: Search for:\n - Ticket-numbered documents matching `BAPI-*.md` or `PROJ-*.md` in `docs/` and subdirectories\n - Feature/migration documents in `docs/`, `documentation/`, or similar directories\n - Architecture Decision Records (ADRs) in `adr/`, `decisions/`, or similar\n - Changelogs (`CHANGELOG.md`, release notes)\n\n Count how many records exist and identify the naming convention.\n\n2. **Record Structure Analysis**: Read 3-5 representative implementation records (mix of early and recent). Document:\n - Sections present (Summary, Architecture, Database Changes, API Reference, etc.)\n - Level of detail provided\n - Types of information captured (motivation, design decisions, schema changes, file paths, API contracts)\n - How code examples and diagrams are used\n\n3. **Documentation Location and Organization**: Read the directory structure of `docs/` to identify where records are stored, the file naming convention, whether there is a table of contents or index, and whether subdirectories serve different purposes.\n\n### Phase 2 — Draft\n\nDraft `documentation_instructions` as clear, actionable instructions for an AI agent writing implementation documentation after completing a feature. Cover:\n- **Purpose**: Documents serve as persistent project memory for future agents and developers.\n- **When to write**: After completing any feature, refactor, migration, or significant bug fix.\n- **File naming convention**: Based on discovered patterns or sensible defaults.\n- **File location**: Where to place implementation records.\n- **Required sections**: Standard structure from analysis or sensible defaults.\n- **Content guidelines**: Level of detail — motivations, design decisions, database changes, file references, API contracts.\n- **Scope boundary**: Implementation records only; code-level docs belong in correctness standards.\n\nWrite the draft to `{docs_dir}/standards/documentation_instructions.md`.\n\n## Return\n\nReturn a brief summary of what was learned about the project's implementation-record conventions (naming, location, required sections), citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/documentation_instructions.md`.\n",
512
512
  "learn-e2e-testing.md": "## Objective\n\nDetect whether an E2E testing framework exists in the codebase, document how to run and write E2E tests, then draft `e2e_testing_instructions` for the project config.\n\n## Instructions\n\n### Phase 1 — Detect E2E Framework\n\nSearch for config files and indicators:\n- **Playwright**: Search for `playwright.config.ts`, `playwright.config.js`, `@playwright/test` in `package.json`\n- **Cypress**: Search for `cypress.json`, `cypress.config.*`, `cypress/` directory\n- **Selenium/WebDriver**: Search for `selenium` in `requirements.in` or `package.json`\n- **Puppeteer**: Search for `puppeteer` in `package.json`\n- **TestCafe**: Search for `.testcaferc.json`\n\nAlso read `package.json` for E2E-related scripts and search for test directories containing E2E tests.\n\nIf NO E2E testing framework is detected, write \"No E2E testing framework detected in this repository.\" to `{docs_dir}/standards/e2e_testing_instructions.md` and stop.\n\n### Phase 2 — Explore E2E Testing Conventions\n\n1. **Test Execution**: Read the E2E config file and `package.json` scripts to determine exact commands (all tests, single file, headed/headless), prerequisites (server running, database seeded), and environment requirements.\n\n2. **Test Patterns**: Read 2-3 representative E2E test files in `tests/playwright/` to identify structure (page objects, fixtures, helpers), login/auth flows, test data setup/teardown, async waiting strategies, and selector patterns.\n\n3. **Common Pitfalls**: Search for hard-coded waits (`setTimeout`, `page.waitForTimeout`), test isolation issues, and browser state management patterns across E2E test files.\n\n### Phase 3 — Draft\n\nDraft `e2e_testing_instructions` as clear, actionable instructions for an AI agent writing E2E tests. Cover:\n- How to run tests (exact commands, prerequisites)\n- Test structure and organization\n- Authentication and setup patterns\n- How to wait for async operations (never hard-coded sleeps)\n- Common pitfalls with browser automation\n- Guards against common AI weaknesses: flaky tests, brittle selectors, hard-coded waits\n\nWrite the draft to `{docs_dir}/standards/e2e_testing_instructions.md`.\n\n## Return\n\nReturn a brief summary of what was learned about the project's E2E testing setup (framework detected, run commands, test patterns) — or state that no framework was detected — citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/e2e_testing_instructions.md`.\n",
513
513
  "learn-frontend-correctness.md": "## Objective\n\nExplore the codebase to identify correctness standards for frontend code, then draft the corresponding correctness standards document.\n\n## Target Type\n\n- **Type**: `frontend_correctness`\n- **Field name**: `frontend_correctness_standards`\n- **Scope**: JS, TS, JSX, TSX files: React/Vue/Angular/Svelte components, client-side logic, state management.\n\n## Instructions\n\n### Phase 1 — Explore Correctness Patterns\n\nFocus on implementation correctness: how to write code that is correct, idiomatic, and robust within this project's conventions.\n\n1. **File Type Detection**: Search by filename pattern for files matching `**/*.js`, `**/*.ts`, `**/*.jsx`, `**/*.tsx` (excluding `node_modules/` and `build/`). If very few or no files exist, note this and draft minimal instructions.\n\n2. **Convention Analysis**: Read 3-5 representative frontend files to identify:\n - Structure patterns (imports, exports, class structure, function ordering)\n - Naming conventions (variables, functions, classes, files)\n - Framework conventions and idioms\n - Best practices followed\n - Issues and inconsistencies\n\n### Phase 2 — Draft\n\nDraft correctness standards as clear, actionable instructions for an AI code generation agent. Cover:\n- Code structure and organization requirements\n- Naming conventions to follow\n- Framework-specific patterns and idioms\n- Security requirements relevant to this code type\n- Performance considerations\n- Common mistakes to avoid\n- Guards against common AI weaknesses: duplicative code, verbose implementations, security vulnerabilities\n\nWrite the draft to `{docs_dir}/standards/frontend_correctness_standards.md`.\n\n## Return\n\nReturn a brief summary of what was learned about frontend correctness conventions (structure, naming, framework idioms), citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/frontend_correctness_standards.md`.\n",
514
- "learn-review-instructions.md": "## Objective\n\nExplore the codebase to identify self-verification patterns, downstream impact analysis techniques, and local validation tooling, then draft `review_instructions` for the project config.\n\n## Instructions\n\n### Phase 1 — Explore Self-Verification Patterns\n\nFocus on how an AI agent working in a code editor (with capabilities to search file contents by text pattern, search by filename pattern, read files, and call MCP tools) can verify its own code changes before requesting human review. Do NOT document test runners or CI/CD — focus on static analysis by reading code and searching for patterns.\n\n1. **Code Correctness Patterns**: Read 3-5 representative modules in `api/routes/` and `api/library/` to identify:\n - Function signature conventions (return types, parameter patterns)\n - Import conventions and layer boundaries (deprecated modules, import restrictions)\n - Return value handling (structured results, tuple unpacking)\n - Auth pattern compliance (required decorators, dependency injections, call order)\n - Naming conventions (files, functions, classes, variables)\n - Error handling patterns (try/except structure, ordering, logging)\n\n2. **Downstream Impact Analysis**: For each technique, demonstrate with a concrete codebase example:\n - Caller discovery (text-pattern search for finding all callers of utility functions)\n - Import graph analysis (finding all files importing from a module)\n - Route registration verification (checking new routes are properly included)\n - Database schema impact (finding queries referencing a given table/column)\n - Model/schema usage (verifying model changes don't break dependents)\n\n3. **Local Validation Tooling**: Discover available MCP tools and validation capabilities:\n - Database MCP tools (schema verification, query validation)\n - Project API MCP tools (config verification, health checks)\n - Hooks and guards (pre-commit hooks, pre-tool hooks)\n - Safety model (read-only vs. mutating operations)\n\n4. **Correctness Standards Integration**: Read files in `{docs_dir}/standards/` matching `*_correctness_standards.md`. Extract key verification checkpoints that can be statically verified.\n\n### Phase 2 — Draft\n\nDraft `review_instructions` with these required sections:\n1. **Self-Verification Checklist** — Concise, scannable checklist with concrete actions and tools.\n2. **Local Code Verification** — Detailed static analysis instructions (function calls, imports, auth, error handling, naming).\n3. **Downstream Effect Analysis** — Finding callers, checking signature compatibility, import tracking, schema impact, route registration.\n4. **Validation Using Local Tooling** — Database validation, project API validation, hooks and guards.\n5. **Correctness Standards Reference** — Distilled checkpoints from loaded standards, or placeholder paths.\n6. **Common AI Agent Mistakes** — Verification-framed guards against duplication, unnecessary abstraction, data leaks, edge cases.\n\nWrite the draft to `{docs_dir}/standards/review_instructions.md`.\n\n## Return\n\nReturn a brief summary of what was learned about the project's self-review and downstream-impact analysis patterns (verification checkpoints, local validation tooling), citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/review_instructions.md`.\n",
514
+ "learn-review-instructions.md": "## Objective\n\nExplore the codebase to identify self-verification patterns, downstream impact analysis techniques, and local validation tooling, then draft `review_instructions` for the project config.\n\n## Instructions\n\n### Phase 1 — Explore Self-Verification Patterns\n\nFocus on how an AI agent working in a code editor (with capabilities to search file contents by text pattern, search by filename pattern, read files, and call MCP tools) can verify its own code changes before requesting human review. Do NOT document test runners or CI/CD — focus on static analysis by reading code and searching for patterns.\n\n1. **Code Correctness Patterns**: Read 3-5 representative modules in `api/routes/` and `api/library/` to identify:\n - Function signature conventions (return types, parameter patterns)\n - Import conventions and layer boundaries (deprecated modules, import restrictions)\n - Return value handling (structured results, tuple unpacking)\n - Auth pattern compliance (required decorators, dependency injections, call order)\n - Naming conventions (files, functions, classes, variables)\n - Error handling patterns (try/except structure, ordering, logging)\n\n2. **Downstream Impact Analysis**: For each technique, demonstrate with a concrete codebase example:\n - Caller discovery (text-pattern search for finding all callers of utility functions)\n - Import graph analysis (finding all files importing from a module)\n - Route registration verification (checking new routes are properly included)\n - Database schema impact (finding queries referencing a given table/column)\n - Model/schema usage (verifying model changes don't break dependents)\n\n3. **Local Validation Tooling**: Discover available MCP tools and validation capabilities:\n - Database MCP tools (schema verification, query validation)\n - Project API MCP tools (config verification, health checks)\n - Hooks and guards (pre-commit hooks, pre-tool hooks)\n - Safety model (read-only vs. mutating operations)\n - Runtime smoke verification capability: Document which tools the executor can use to _run_ code safely (test runners, dbhub MCP, local dev servers, fixture loaders) and whether mutations are permitted against local/ephemeral state. The per-repo `allow_mutating_smoke_ops` flag (on `config_code_repositories`) controls whether the final reviewer is allowed to plan mutating verification steps.\n\n4. **Correctness Standards Integration**: Read files in `{docs_dir}/standards/` matching `*_correctness_standards.md`. Extract key verification checkpoints that can be statically verified.\n\n### Phase 2 — Draft\n\nDraft `review_instructions` with these required sections:\n1. **Self-Verification Checklist** — Concise, scannable checklist with concrete actions and tools.\n2. **Local Code Verification** — Detailed static analysis instructions (function calls, imports, auth, error handling, naming).\n3. **Downstream Effect Analysis** — Finding callers, checking signature compatibility, import tracking, schema impact, route registration.\n4. **Validation Using Local Tooling** — Database validation, project API validation, hooks and guards.\n5. **Correctness Standards Reference** — Distilled checkpoints from loaded standards, or placeholder paths.\n6. **Common AI Agent Mistakes** — Verification-framed guards against duplication, unnecessary abstraction, data leaks, edge cases.\n\nWrite the draft to `{docs_dir}/standards/review_instructions.md`.\n\n## Return\n\nReturn a brief summary of what was learned about the project's self-review and downstream-impact analysis patterns (verification checkpoints, local validation tooling), citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/review_instructions.md`.\n",
515
515
  "learn-style-correctness.md": "## Objective\n\nExplore the codebase to identify correctness standards for style files, then draft the corresponding correctness standards document.\n\n## Target Type\n\n- **Type**: `style_correctness`\n- **Field name**: `style_correctness_standards`\n- **Scope**: Style files: CSS, SCSS, SASS, LESS, Styled Components, Tailwind configs.\n\n## Instructions\n\n### Phase 1 — Explore Correctness Patterns\n\nFocus on implementation correctness: how to write code that is correct, idiomatic, and robust within this project's conventions.\n\n1. **File Type Detection**: Search by filename pattern for files matching `**/*.css`, `**/*.scss`, `**/*.sass`, `**/*.less` (excluding `node_modules/`). If very few or no files exist, note this and draft minimal instructions.\n\n2. **Convention Analysis**: Read 3-5 representative style files to identify:\n - Structure patterns (imports, exports, class structure, function ordering)\n - Naming conventions (variables, functions, classes, files)\n - Framework conventions and idioms\n - Best practices followed\n - Issues and inconsistencies\n\n### Phase 2 — Draft\n\nDraft correctness standards as clear, actionable instructions for an AI code generation agent. Cover:\n- Code structure and organization requirements\n- Naming conventions to follow\n- Framework-specific patterns and idioms\n- Security requirements relevant to this code type\n- Performance considerations\n- Common mistakes to avoid\n- Guards against common AI weaknesses: duplicative code, verbose implementations, security vulnerabilities\n\nWrite the draft to `{docs_dir}/standards/style_correctness_standards.md`.\n\n## Return\n\nReturn a brief summary of what was learned about style-file correctness conventions (structure, naming, methodology), citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/style_correctness_standards.md`.\n",
516
516
  "learn-template-correctness.md": "## Objective\n\nExplore the codebase to identify correctness standards for template files, then draft the corresponding correctness standards document.\n\n## Target Type\n\n- **Type**: `template_correctness`\n- **Field name**: `template_correctness_standards`\n- **Scope**: Template files: HTML, Jinja2, Handlebars, EJS, ERB, Blade, Pug, Twig.\n\n## Instructions\n\n### Phase 1 — Explore Correctness Patterns\n\nFocus on implementation correctness: how to write code that is correct, idiomatic, and robust within this project's conventions.\n\n1. **File Type Detection**: Search by filename pattern for files matching `**/*.html`, `**/*.jinja2`, `**/*.j2` in `templates/` and similar directories (excluding `node_modules/`). If very few or no files exist, note this and draft minimal instructions.\n\n2. **Convention Analysis**: Read 3-5 representative template files to identify:\n - Structure patterns (imports, exports, class structure, function ordering)\n - Naming conventions (variables, functions, classes, files)\n - Framework conventions and idioms\n - Best practices followed\n - Issues and inconsistencies\n\n### Phase 2 — Draft\n\nDraft correctness standards as clear, actionable instructions for an AI code generation agent. Cover:\n- Code structure and organization requirements\n- Naming conventions to follow\n- Framework-specific patterns and idioms\n- Security requirements relevant to this code type\n- Performance considerations\n- Common mistakes to avoid\n- Guards against common AI weaknesses: duplicative code, verbose implementations, security vulnerabilities\n\nWrite the draft to `{docs_dir}/standards/template_correctness_standards.md`.\n\n## Return\n\nReturn a brief summary of what was learned about template-file correctness conventions (structure, naming, framework idioms), citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/template_correctness_standards.md`.\n",
517
517
  "learn-unit-testing.md": "## Objective\n\nExplore the codebase to identify the test runner, assertion library, mocking framework, and testing patterns, then draft `unit_testing_instructions` for the project config.\n\n## Instructions\n\n### Phase 1 — Explore Testing Infrastructure\n\n1. **Test Runner and Framework Detection**: Search for test runner configs (`pytest.ini`, `pyproject.toml` `[tool.pytest]` section, `jest.config.*`) and read `package.json` test scripts. Read the `tests/` directory structure.\n\n2. **Testing Patterns**: Read 3-5 representative test files in `tests/pytest/` to identify:\n - Assertion library and style (`assert`, `expect`, custom matchers)\n - Mocking framework (`unittest.mock`, `jest.mock`, `sinon`, etc.)\n - Fixture patterns (setup/teardown)\n - Test organization (by module, feature, layer)\n - Exemplary tests vs. weak tests\n\n3. **How to Run Tests**: Read `pyproject.toml`, `package.json`, and `Makefile` (if present) to determine exact commands for: full suite, single file, by name pattern, with verbose output.\n\n4. **Mocking vs. Fidelity**: Read test helper files in `tests/pytest/helpers/` to document how external APIs are mocked, whether integration tests exist alongside unit tests, and patterns for avoiding third-party calls in tests.\n\n### Phase 2 — Draft\n\nDraft `unit_testing_instructions` as clear, actionable instructions for an AI agent writing unit tests. Cover:\n- How to run tests (exact commands)\n- Which test framework and assertion library to use\n- How to mock external dependencies without calling third parties\n- How to structure test files and test functions\n- What constitutes a thorough test (not just happy path)\n- How to avoid shallow tests that pass but don't verify meaningful behavior\n- Guards against common AI weaknesses: tests that mock the thing being tested, trivially passing assertions, overly complex setup\n\nWrite the draft to `{docs_dir}/standards/unit_testing_instructions.md`.\n\n## Return\n\nReturn a brief summary of what was learned about the project's unit testing setup (test runner, assertion library, mocking framework, run commands), citing the key files inspected, and confirm the draft was written to `{docs_dir}/standards/unit_testing_instructions.md`.\n",