holycodex 0.5.1 → 0.5.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "holycodex",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Lean Codex-only agent toolkit for ChatGPT Plus",
5
5
  "keywords": [
6
6
  "agents",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "holycodex",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Lean Codex workflows with routed skills, bounded subagents, scoped rules, Git Bash, and LSP.",
5
5
  "author": {
6
6
  "name": "David Basile Filho",
@@ -2,5 +2,5 @@ description = "Use for a narrow, read-only repository fact question with explici
2
2
  model = "gpt-5.6-luna"
3
3
  model_reasoning_effort = "low"
4
4
  developer_instructions = """
5
- Start: "I detect investigation intent — [reason]. [action]." Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Accept one task packet containing exact question; repository root; allowed paths and symbols; forbidden paths; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Reject incomplete or ambiguous packets. Inspect only assigned scope. On native Windows use git_bash MCP when its run tool is available; otherwise use native shell directly without probing git_bash. Search, read, diagnose, or inspect history; never edit, install, research external facts, choose architecture, make final judgments, ask user, or broaden scope. Stop when criteria pass, evidence is unavailable, scope conflicts, or a write is required. Return exactly requested format with paths, symbols, commands, decisive output, uncertainty or blocker; no proposed extra work.
5
+ Start: "I detect investigation intent — [reason]. [action]." Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Before any plan, skill routing, or task action, inspect the full callable tool registry, including deferred tools; treat only that registry as availability evidence. Accept one task packet containing exact question; repository root; allowed paths and symbols; forbidden paths; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Reject incomplete or ambiguous packets. Inspect only assigned scope. On native Windows, before any shell call resolve `mcp__git_bash__run` from the full callable registry, including deferred tools, and use it when available; otherwise use native shell directly. Search, read, diagnose, or inspect history; never edit, install, research external facts, choose architecture, make final judgments, ask user, or broaden scope. Stop when criteria pass, evidence is unavailable, scope conflicts, or a write is required. Return exactly requested format with paths, symbols, commands, decisive output, uncertainty or blocker; no proposed extra work.
6
6
  """
@@ -2,5 +2,5 @@ description = "Use for a narrow current external-fact question requiring primary
2
2
  model = "gpt-5.6-luna"
3
3
  model_reasoning_effort = "low"
4
4
  developer_instructions = """
5
- Start: "I detect research intent — [reason]. [action]." Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Accept one task packet containing exact question; repository root only as context; allowed paths and symbols, normally none; forbidden paths and sources; allowed external sources; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Reject incomplete or ambiguous packets. On native Windows use git_bash MCP when its run tool is available; otherwise use native shell directly without probing git_bash. Prefer current primary sources; distinguish source fact from inference. Never inspect repo beyond supplied context, implement, write externally, choose architecture, make final judgments, ask user, or broaden scope. Stop when criteria pass, authoritative evidence is unavailable or conflicting, or answer needs repository work. Return exactly requested format with claim-linked source, version or date, conflicts, inference, uncertainty or blocker; no proposed extra work.
5
+ Start: "I detect research intent — [reason]. [action]." Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Before any plan, skill routing, or task action, inspect the full callable tool registry, including deferred tools; treat only that registry as availability evidence. Accept one task packet containing exact question; repository root only as context; allowed paths and symbols, normally none; forbidden paths and sources; allowed external sources; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Reject incomplete or ambiguous packets. On native Windows, before any shell call resolve `mcp__git_bash__run` from the full callable registry, including deferred tools, and use it when available; otherwise use native shell directly. Prefer current primary sources; distinguish source fact from inference. Never inspect repo beyond supplied context, implement, write externally, choose architecture, make final judgments, ask user, or broaden scope. Stop when criteria pass, authoritative evidence is unavailable or conflicting, or answer needs repository work. Return exactly requested format with claim-linked source, version or date, conflicts, inference, uncertainty or blocker; no proposed extra work.
6
6
  """
@@ -2,5 +2,5 @@ description = "Use for an isolated implementation slice with fixed files and acc
2
2
  model = "gpt-5.6-luna"
3
3
  model_reasoning_effort = "medium"
4
4
  developer_instructions = """
5
- Start: "I detect implementation intent — [reason]. [action]." Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Accept one task packet containing exact implementation outcome; repository root; allowed paths and symbols; forbidden paths; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Reject or stop on ambiguity, overlap, architecture choice, coupled out-of-scope work, user-work conflict, or missing authority. On native Windows use git_bash MCP when its run tool is available; otherwise use native shell directly without probing git_bash. Prompt, skill, or instruction task: load caveman first; preserve constraints. Load required skills before governed action. Change only assigned files. Preserve architecture, API, behavior, naming, style, and user work. Add no speculative cleanup, abstraction, dependency, docs, or scope. Run specified proof; never claim integration or final verification. Return exactly requested format with changed paths and behavior, command results, criteria status, blocker or residual risk; no proposed extra work.
5
+ Start: "I detect implementation intent — [reason]. [action]." Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Before any plan, skill routing, or task action, inspect the full callable tool registry, including deferred tools; treat only that registry as availability evidence. Accept one task packet containing exact implementation outcome; repository root; allowed paths and symbols; forbidden paths; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Reject or stop on ambiguity, overlap, architecture choice, coupled out-of-scope work, user-work conflict, or missing authority. On native Windows, before any shell call resolve `mcp__git_bash__run` from the full callable registry, including deferred tools, and use it when available; otherwise use native shell directly. Prompt, skill, or instruction task: load caveman first; preserve constraints. Load required skills before governed action. Change only assigned files. Preserve architecture, API, behavior, naming, style, and user work. Add no speculative cleanup, abstraction, dependency, docs, or scope. Run specified proof; never claim integration or final verification. Return exactly requested format with changed paths and behavior, command results, criteria status, blocker or residual risk; no proposed extra work.
6
6
  """
@@ -122,7 +122,7 @@ function paths(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")) {
122
122
  config: join(home, "config.toml"),
123
123
  marketplaceCache,
124
124
  cacheRoot,
125
- cache: join(cacheRoot, "0.5.1"),
125
+ cache: join(cacheRoot, "0.5.3"),
126
126
  agents: join(home, "holycodex", "agents"),
127
127
  legacy: [
128
128
  join(home, "plugins", "cache", "sisyphuslabs", "omo"),
@@ -210,7 +210,7 @@ async function cleanup(_options) {
210
210
  }
211
211
  //#endregion
212
212
  //#region src/cli.ts
213
- var VERSION = "0.5.1";
213
+ var VERSION = "0.5.3";
214
214
  var HELP = `HolyCodex ${VERSION}\n\nUsage: holycodex <install|cleanup> [options]\n\nOptions:\n --help Show help\n --version Show version\n --no-tui Accepted; commands are noninteractive\n --codex-autonomous Set autonomous Codex permissions (default)\n --no-codex-autonomous Preserve existing Codex permissions\n --json Print machine-readable result\n`;
215
215
  async function main() {
216
216
  const args = process$1.argv.slice(2);
@@ -1,4 +1,4 @@
1
1
  //#region src/core-instructions.ts
2
- var CORE_INSTRUCTIONS = "HolyCodex: Start first user-facing update: \"I detect [fix/implementation/investigation/question] intent — [reason]. [action].\" Act. Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Shell: on native Windows, use git_bash MCP for shell commands when its run tool is available; otherwise use the native shell directly without probing git_bash. Prompt, skill, or instruction edit: load caveman; preserve constraints. Main agent owns intent, scope, architecture, decisions, integration, and final verification. Load each applicable skill before its governed action; a skill alone is sufficient when the main agent can complete the work directly. Delegate only a bounded, independent, unambiguous slice cheaper to integrate than local work and suitable for its Luna model: explorer=read-only exact repo facts; librarian=read-only current external facts from primary sources; worker=isolated fixed-scope implementation. Never delegate trivial or coupled work, architecture, user clarification, integration, final judgment, or final verification. Every packet states exact question or outcome; repository root; allowed paths and symbols; forbidden paths; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Use concrete names, paths, APIs, functions, tests, versions, and expected observations when known; include no unrelated transcript. Treat returns as input: inspect, reconcile, integrate, and verify. Stop when packet is satisfied or blocked; never recurse or create agent organizations. Use GPT 5.6 Luna low for explorer and librarian; use GPT 5.6 Luna medium for worker.";
2
+ var CORE_INSTRUCTIONS = "HolyCodex: Start first user-facing update: \"I detect [fix/implementation/investigation/question] intent — [reason]. [action].\" Act. Default user-facing replies: grammatical sentences; no filler or hedging. Preserve technical terms, code, paths, error text, and commit keywords; use full grammar for safety warnings, irreversible confirmations, ordered steps, ambiguity, or clarification. Before any plan, skill routing, delegation, or task action, inspect the full callable tool registry, including deferred tools; treat only that registry as availability evidence. Shell: on native Windows, before any shell call resolve `mcp__git_bash__run` from the full callable registry, including deferred tools, and use it when available; otherwise use the native shell directly. Prompt, skill, or instruction edit: load caveman; preserve constraints. Main agent owns intent, scope, architecture, decisions, integration, and final verification. Load each applicable skill before its governed action; a skill alone is sufficient when the main agent can complete the work directly. Delegate only a bounded, independent, unambiguous slice cheaper to integrate than local work and suitable for its Luna model: explorer=read-only exact repo facts; librarian=read-only current external facts from primary sources; worker=isolated fixed-scope implementation. Never delegate trivial or coupled work, architecture, user clarification, integration, final judgment, or final verification. Every packet states exact question or outcome; repository root; allowed paths and symbols; forbidden paths; relevant architecture and existing behavior; required skills; exact inputs; output format; acceptance criteria; required commands or evidence; unchanged constraints; prohibited expansion; known uncertainty; blocker behavior; exact stop condition. Use concrete names, paths, APIs, functions, tests, versions, and expected observations when known; include no unrelated transcript. Treat returns as input: inspect, reconcile, integrate, and verify. Stop when packet is satisfied or blocked; never recurse or create agent organizations. Use GPT 5.6 Luna low for explorer and librarian; use GPT 5.6 Luna medium for worker.";
3
3
  //#endregion
4
4
  export { CORE_INSTRUCTIONS as t };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as successResponse, n as errorResponse, o as isPlainRecord, r as jsonRpcId, t as runJsonRpcStdioServer } from "./mcp-stdio-core.js";
2
+ import { a as stackOrMessageFromError, i as messageFromError, n as errorResponse, o as successResponse, r as jsonRpcId, s as isPlainRecord, t as runJsonRpcStdioServer } from "./mcp-stdio-core.js";
3
3
  import { join } from "node:path";
4
4
  import { argv, stderr } from "node:process";
5
5
  import { tmpdir } from "node:os";
@@ -166,7 +166,7 @@ async function handleGitBashMcpRequest(input, options = {}) {
166
166
  capabilities: { tools: { listChanged: false } },
167
167
  serverInfo: {
168
168
  name: "git_bash",
169
- version: "0.5.1"
169
+ version: "0.5.3"
170
170
  },
171
171
  protocolVersion: protocolVersionFromInput(input) ?? "2024-11-05"
172
172
  });
@@ -216,7 +216,7 @@ async function runToolResponse(id, args, options) {
216
216
  });
217
217
  return toolResponse(id, JSON.stringify(result, null, 2));
218
218
  } catch (error) {
219
- return toolResponse(id, error instanceof Error ? error.message : String(error), true);
219
+ return toolResponse(id, messageFromError(error), true);
220
220
  }
221
221
  }
222
222
  function toolsForOptions(options) {
@@ -349,7 +349,7 @@ async function main() {
349
349
  process.exitCode = 2;
350
350
  }
351
351
  main().catch((error) => {
352
- stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
352
+ stderr.write(`${stackOrMessageFromError(error)}\n`);
353
353
  process.exitCode = 1;
354
354
  });
355
355
  //#endregion
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as successResponse, i as messageFromError, n as errorResponse, o as isPlainRecord, r as jsonRpcId, t as runJsonRpcStdioServer } from "./mcp-stdio-core.js";
2
+ import { a as stackOrMessageFromError, i as messageFromError, n as errorResponse, o as successResponse, r as jsonRpcId, s as isPlainRecord, t as runJsonRpcStdioServer } from "./mcp-stdio-core.js";
3
3
  import { basename, delimiter, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { argv, execPath, stderr } from "node:process";
5
5
  import { homedir, tmpdir } from "node:os";
@@ -94,7 +94,7 @@ function isLspDeadConnectionError(err) {
94
94
  //#region packages/lsp-core/src/lsp/cleanup-errors.ts
95
95
  function reportBestEffortCleanupError(operation, error) {
96
96
  if (process.env["CODEX_LSP_DEBUG_CLEANUP"] !== "1") return;
97
- const message = error instanceof Error ? error.message : String(error);
97
+ const message = messageFromError(error);
98
98
  console.error(`[codex-lsp] ignored ${operation} failure during cleanup: ${message}`);
99
99
  }
100
100
  var STOP_HARD_KILL_TIMEOUT_MS = 5e3;
@@ -328,15 +328,12 @@ function parseContentLength(headers) {
328
328
  }
329
329
  return null;
330
330
  }
331
- function isJsonRpcObject(value) {
332
- return typeof value === "object" && value !== null && !Array.isArray(value);
333
- }
334
331
  function getMessageId(message) {
335
332
  const id = message["id"];
336
333
  if (typeof id === "number" || typeof id === "string" || id === null) return id;
337
334
  }
338
335
  function jsonRpcErrorToError(value) {
339
- if (!isJsonRpcObject(value)) return /* @__PURE__ */ new Error("JSON-RPC request failed");
336
+ if (!isPlainRecord(value)) return /* @__PURE__ */ new Error("JSON-RPC request failed");
340
337
  const message = typeof value["message"] === "string" ? value["message"] : "JSON-RPC request failed";
341
338
  const error = new Error(message);
342
339
  if (typeof value["code"] === "number") error.name = `JsonRpcError(${value["code"]})`;
@@ -499,21 +496,18 @@ function spawnProcess(command, options) {
499
496
  }
500
497
  //#endregion
501
498
  //#region packages/lsp-core/src/lsp/transport.ts
502
- function isRecord$3(value) {
503
- return typeof value === "object" && value !== null && !Array.isArray(value);
504
- }
505
499
  function parseConfigurationItems(params) {
506
- if (!isRecord$3(params) || !Array.isArray(params["items"])) return [];
500
+ if (!isPlainRecord(params) || !Array.isArray(params["items"])) return [];
507
501
  const items = [];
508
502
  for (const item of params["items"]) {
509
- if (!isRecord$3(item)) continue;
503
+ if (!isPlainRecord(item)) continue;
510
504
  const section = item["section"];
511
505
  items.push(section === void 0 || typeof section !== "string" ? {} : { section });
512
506
  }
513
507
  return items;
514
508
  }
515
509
  function parseDiagnosticsParams(params) {
516
- if (!isRecord$3(params) || typeof params["uri"] !== "string") return null;
510
+ if (!isPlainRecord(params) || typeof params["uri"] !== "string") return null;
517
511
  const diagnostics = Array.isArray(params["diagnostics"]) ? params["diagnostics"].filter(isDiagnostic) : [];
518
512
  return {
519
513
  uri: params["uri"],
@@ -680,13 +674,13 @@ function createLspSpawnEnv(_root, input) {
680
674
  return { ...input };
681
675
  }
682
676
  function isDiagnostic(value) {
683
- return isRecord$3(value) && isRange(value["range"]) && typeof value["message"] === "string";
677
+ return isPlainRecord(value) && isRange(value["range"]) && typeof value["message"] === "string";
684
678
  }
685
679
  function isRange(value) {
686
- return isRecord$3(value) && isPosition(value["start"]) && isPosition(value["end"]);
680
+ return isPlainRecord(value) && isPosition(value["start"]) && isPosition(value["end"]);
687
681
  }
688
682
  function isPosition(value) {
689
- return isRecord$3(value) && typeof value["line"] === "number" && typeof value["character"] === "number";
683
+ return isPlainRecord(value) && typeof value["line"] === "number" && typeof value["character"] === "number";
690
684
  }
691
685
  //#endregion
692
686
  //#region packages/lsp-core/src/lsp/connection.ts
@@ -969,10 +963,9 @@ var LspClient = class extends LspClientConnection {
969
963
  });
970
964
  }
971
965
  async definition(filePath, line, character) {
972
- const absPath = resolve(contextCwd(), filePath);
973
- await this.openFile(absPath);
966
+ const textDocument = await this.openTextDocument(filePath);
974
967
  return this.sendRequest("textDocument/definition", {
975
- textDocument: { uri: pathToFileURL(absPath).href },
968
+ textDocument,
976
969
  position: {
977
970
  line: line - 1,
978
971
  character
@@ -980,10 +973,9 @@ var LspClient = class extends LspClientConnection {
980
973
  });
981
974
  }
982
975
  async references(filePath, line, character, includeDeclaration = true) {
983
- const absPath = resolve(contextCwd(), filePath);
984
- await this.openFile(absPath);
976
+ const textDocument = await this.openTextDocument(filePath);
985
977
  return this.sendRequest("textDocument/references", {
986
- textDocument: { uri: pathToFileURL(absPath).href },
978
+ textDocument,
987
979
  position: {
988
980
  line: line - 1,
989
981
  character
@@ -992,9 +984,8 @@ var LspClient = class extends LspClientConnection {
992
984
  });
993
985
  }
994
986
  async documentSymbols(filePath) {
995
- const absPath = resolve(contextCwd(), filePath);
996
- await this.openFile(absPath);
997
- return this.sendRequest("textDocument/documentSymbol", { textDocument: { uri: pathToFileURL(absPath).href } });
987
+ const textDocument = await this.openTextDocument(filePath);
988
+ return this.sendRequest("textDocument/documentSymbol", { textDocument });
998
989
  }
999
990
  async workspaceSymbols(query) {
1000
991
  return this.sendRequest("workspace/symbol", { query });
@@ -1005,9 +996,7 @@ var LspClient = class extends LspClientConnection {
1005
996
  return /unsupported|not supported|method not found|unknown request/i.test(error.message);
1006
997
  }
1007
998
  async diagnostics(filePath) {
1008
- const absPath = resolve(contextCwd(), filePath);
1009
- const uri = pathToFileURL(absPath).href;
1010
- await this.openFile(absPath);
999
+ const { uri } = await this.openTextDocument(filePath);
1011
1000
  await new Promise((r) => setTimeout(r, POST_DIAGNOSTICS_WAIT_MS));
1012
1001
  try {
1013
1002
  const result = await this.sendRequest("textDocument/diagnostic", { textDocument: { uri } });
@@ -1018,10 +1007,9 @@ var LspClient = class extends LspClientConnection {
1018
1007
  return { items: this.getStoredDiagnostics(uri) };
1019
1008
  }
1020
1009
  async prepareRename(filePath, line, character) {
1021
- const absPath = resolve(contextCwd(), filePath);
1022
- await this.openFile(absPath);
1010
+ const textDocument = await this.openTextDocument(filePath);
1023
1011
  return this.sendRequest("textDocument/prepareRename", {
1024
- textDocument: { uri: pathToFileURL(absPath).href },
1012
+ textDocument,
1025
1013
  position: {
1026
1014
  line: line - 1,
1027
1015
  character
@@ -1029,10 +1017,9 @@ var LspClient = class extends LspClientConnection {
1029
1017
  });
1030
1018
  }
1031
1019
  async rename(filePath, line, character, newName) {
1032
- const absPath = resolve(contextCwd(), filePath);
1033
- await this.openFile(absPath);
1020
+ const textDocument = await this.openTextDocument(filePath);
1034
1021
  return this.sendRequest("textDocument/rename", {
1035
- textDocument: { uri: pathToFileURL(absPath).href },
1022
+ textDocument,
1036
1023
  position: {
1037
1024
  line: line - 1,
1038
1025
  character
@@ -1040,6 +1027,11 @@ var LspClient = class extends LspClientConnection {
1040
1027
  newName
1041
1028
  });
1042
1029
  }
1030
+ async openTextDocument(filePath) {
1031
+ const absPath = resolve(contextCwd(), filePath);
1032
+ await this.openFile(absPath);
1033
+ return { uri: pathToFileURL(absPath).href };
1034
+ }
1043
1035
  };
1044
1036
  //#endregion
1045
1037
  //#region packages/lsp-core/src/lsp/process-signal-cleanup.ts
@@ -1352,15 +1344,12 @@ function writeInstallDecisions(decisions) {
1352
1344
  renameSync(tmpPath, path);
1353
1345
  }
1354
1346
  function isInstallDecisions(value) {
1355
- return isRecord$2(value) && Object.values(value).every(isInstallDecisionRecord);
1347
+ return isPlainRecord(value) && Object.values(value).every(isInstallDecisionRecord);
1356
1348
  }
1357
1349
  function isInstallDecisionRecord(value) {
1358
- if (!isRecord$2(value)) return false;
1350
+ if (!isPlainRecord(value)) return false;
1359
1351
  return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
1360
1352
  }
1361
- function isRecord$2(value) {
1362
- return typeof value === "object" && value !== null && !Array.isArray(value);
1363
- }
1364
1353
  //#endregion
1365
1354
  //#region packages/lsp-core/src/lsp/server-definitions.ts
1366
1355
  var LSP_INSTALL_HINTS = {
@@ -1826,31 +1815,28 @@ function applyOptionalServerFields(server, entry) {
1826
1815
  if (entry.initialization !== void 0) server.initialization = entry.initialization;
1827
1816
  }
1828
1817
  function isConfigJson(value) {
1829
- if (!isRecord$1(value)) return false;
1818
+ if (!isPlainRecord(value)) return false;
1830
1819
  const lsp = value["lsp"];
1831
- return lsp === void 0 || isRecord$1(lsp);
1820
+ return lsp === void 0 || isPlainRecord(lsp);
1832
1821
  }
1833
1822
  function parseLspEntry(value) {
1834
1823
  return isLspEntry(value) ? value : null;
1835
1824
  }
1836
1825
  function isLspEntry(value) {
1837
- if (!isRecord$1(value)) return false;
1826
+ if (!isPlainRecord(value)) return false;
1838
1827
  const disabled = value["disabled"];
1839
1828
  const command = value["command"];
1840
1829
  const extensions = value["extensions"];
1841
1830
  const priority = value["priority"];
1842
1831
  const env = value["env"];
1843
1832
  const initialization = value["initialization"];
1844
- return (disabled === void 0 || typeof disabled === "boolean") && (command === void 0 || isStringArray(command)) && (extensions === void 0 || isStringArray(extensions)) && (priority === void 0 || typeof priority === "number") && (env === void 0 || isStringRecord$1(env)) && (initialization === void 0 || isRecord$1(initialization));
1833
+ return (disabled === void 0 || typeof disabled === "boolean") && (command === void 0 || isStringArray(command)) && (extensions === void 0 || isStringArray(extensions)) && (priority === void 0 || typeof priority === "number") && (env === void 0 || isStringRecord$1(env)) && (initialization === void 0 || isPlainRecord(initialization));
1845
1834
  }
1846
1835
  function isStringArray(value) {
1847
1836
  return Array.isArray(value) && value.every((item) => typeof item === "string");
1848
1837
  }
1849
1838
  function isStringRecord$1(value) {
1850
- return isRecord$1(value) && Object.values(value).every((item) => typeof item === "string");
1851
- }
1852
- function isRecord$1(value) {
1853
- return typeof value === "object" && value !== null && !Array.isArray(value);
1839
+ return isPlainRecord(value) && Object.values(value).every((item) => typeof item === "string");
1854
1840
  }
1855
1841
  function getDisabledServerIds() {
1856
1842
  const configs = loadAllConfigs();
@@ -2311,9 +2297,7 @@ var RUST_SRC_REPAIR_MESSAGE = [
2311
2297
  " rustup component remove rust-src",
2312
2298
  " rustup component add rust-src"
2313
2299
  ];
2314
- function errorMessage$1(error) {
2315
- return error instanceof Error ? error.message : String(error);
2316
- }
2300
+ var errorMessage = messageFromError;
2317
2301
  function formatKnownLspStartupFailure(error) {
2318
2302
  if (!(error instanceof LspProcessExitedError)) return null;
2319
2303
  if (error.serverId !== "rust") return null;
@@ -2330,7 +2314,7 @@ function formatKnownLspStartupFailure(error) {
2330
2314
  function handleMissingDependencyError(error) {
2331
2315
  const knownStartupFailure = formatKnownLspStartupFailure(error);
2332
2316
  if (knownStartupFailure) return knownStartupFailure;
2333
- const message = errorMessage$1(error);
2317
+ const message = errorMessage(error);
2334
2318
  return message.includes("NOT INSTALLED") || message.includes("No LSP server configured") ? message : null;
2335
2319
  }
2336
2320
  //#endregion
@@ -2350,10 +2334,20 @@ function missingDependencyResult(error, details) {
2350
2334
  }
2351
2335
  };
2352
2336
  }
2337
+ function missingDependencyResultOrThrow(error, details) {
2338
+ const result = missingDependencyResult(error, details);
2339
+ if (result !== null) return result;
2340
+ throw error;
2341
+ }
2353
2342
  //#endregion
2354
2343
  //#region packages/lsp-core/src/tools/parameters.ts
2355
- function isRecord(value) {
2356
- return typeof value === "object" && value !== null && !Array.isArray(value);
2344
+ var isRecord = isPlainRecord;
2345
+ function sourcePosition(params) {
2346
+ return {
2347
+ filePath: requireString(params, "filePath"),
2348
+ line: requireNumber(params, "line"),
2349
+ character: requireNumber(params, "character")
2350
+ };
2357
2351
  }
2358
2352
  function requireString(params, key) {
2359
2353
  const value = params[key];
@@ -2449,7 +2443,7 @@ async function executeLspDiagnostics(params, signal) {
2449
2443
  truncated
2450
2444
  });
2451
2445
  } catch (error) {
2452
- const missingDependency = missingDependencyResult(error, {
2446
+ return missingDependencyResultOrThrow(error, {
2453
2447
  filePath,
2454
2448
  severity,
2455
2449
  mode: "file",
@@ -2457,8 +2451,6 @@ async function executeLspDiagnostics(params, signal) {
2457
2451
  totalDiagnostics: 0,
2458
2452
  truncated: false
2459
2453
  });
2460
- if (missingDependency) return missingDependency;
2461
- throw error;
2462
2454
  }
2463
2455
  }
2464
2456
  //#endregion
@@ -2484,9 +2476,7 @@ async function executeLspInstallDecision(params) {
2484
2476
  //#endregion
2485
2477
  //#region packages/lsp-core/src/tools/navigation.ts
2486
2478
  async function executeLspGotoDefinition(params, signal) {
2487
- const filePath = requireString(params, "filePath");
2488
- const line = requireNumber(params, "line");
2489
- const character = requireNumber(params, "character");
2479
+ const { filePath, line, character } = sourcePosition(params);
2490
2480
  try {
2491
2481
  const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character), "definition", clientOptions(signal));
2492
2482
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
@@ -2499,20 +2489,16 @@ async function executeLspGotoDefinition(params, signal) {
2499
2489
  if (locations.length === 0) return text("No definition found", details);
2500
2490
  return text(locations.map(formatLocation).join("\n"), details);
2501
2491
  } catch (error) {
2502
- const missingDependency = missingDependencyResult(error, {
2492
+ return missingDependencyResultOrThrow(error, {
2503
2493
  filePath,
2504
2494
  line,
2505
2495
  character,
2506
2496
  locations: []
2507
2497
  });
2508
- if (missingDependency) return missingDependency;
2509
- throw error;
2510
2498
  }
2511
2499
  }
2512
2500
  async function executeLspFindReferences(params, signal) {
2513
- const filePath = requireString(params, "filePath");
2514
- const line = requireNumber(params, "line");
2515
- const character = requireNumber(params, "character");
2501
+ const { filePath, line, character } = sourcePosition(params);
2516
2502
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
2517
2503
  try {
2518
2504
  const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration), "references", clientOptions(signal));
@@ -2531,7 +2517,7 @@ async function executeLspFindReferences(params, signal) {
2531
2517
  if (total === 0) return text("No references found", details);
2532
2518
  return text([...truncated ? [`Found ${total} references (showing first 200):`] : [], ...limited.map(formatLocation)].join("\n"), details);
2533
2519
  } catch (error) {
2534
- const missingDependency = missingDependencyResult(error, {
2520
+ return missingDependencyResultOrThrow(error, {
2535
2521
  filePath,
2536
2522
  line,
2537
2523
  character,
@@ -2539,15 +2525,10 @@ async function executeLspFindReferences(params, signal) {
2539
2525
  totalReferences: 0,
2540
2526
  truncated: false
2541
2527
  });
2542
- if (missingDependency) return missingDependency;
2543
- throw error;
2544
2528
  }
2545
2529
  }
2546
2530
  //#endregion
2547
2531
  //#region packages/lsp-core/src/lsp/workspace-edit.ts
2548
- function errorMessage(error) {
2549
- return error instanceof Error ? error.message : String(error);
2550
- }
2551
2532
  function isPathInsideWorkspace(filePath, workspaceRoot) {
2552
2533
  const relativePath = relative(workspaceRoot, filePath);
2553
2534
  return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute(relativePath);
@@ -2564,7 +2545,7 @@ function uriToWorkspacePath(uri, workspaceRoot) {
2564
2545
  } catch (error) {
2565
2546
  return {
2566
2547
  success: false,
2567
- error: `non-file URI ${uri}: ${errorMessage(error)}`
2548
+ error: `non-file URI ${uri}: ${messageFromError(error)}`
2568
2549
  };
2569
2550
  }
2570
2551
  let validatedPath;
@@ -2573,7 +2554,7 @@ function uriToWorkspacePath(uri, workspaceRoot) {
2573
2554
  } catch (error) {
2574
2555
  return {
2575
2556
  success: false,
2576
- error: `${filePath}: ${errorMessage(error)}`
2557
+ error: `${filePath}: ${messageFromError(error)}`
2577
2558
  };
2578
2559
  }
2579
2560
  if (!isPathInsideWorkspace(validatedPath, workspaceRoot)) return {
@@ -2717,9 +2698,7 @@ function applyWorkspaceEdit(edit, options = {}) {
2717
2698
  //#endregion
2718
2699
  //#region packages/lsp-core/src/tools/rename.ts
2719
2700
  async function executeLspPrepareRename(params, signal) {
2720
- const filePath = requireString(params, "filePath");
2721
- const line = requireNumber(params, "line");
2722
- const character = requireNumber(params, "character");
2701
+ const { filePath, line, character } = sourcePosition(params);
2723
2702
  try {
2724
2703
  const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character), "prepareRename", clientOptions(signal));
2725
2704
  const details = {
@@ -2730,20 +2709,16 @@ async function executeLspPrepareRename(params, signal) {
2730
2709
  };
2731
2710
  return text(formatPrepareRenameResult(result), details);
2732
2711
  } catch (error) {
2733
- const missingDependency = missingDependencyResult(error, {
2712
+ return missingDependencyResultOrThrow(error, {
2734
2713
  filePath,
2735
2714
  line,
2736
2715
  character,
2737
2716
  result: null
2738
2717
  });
2739
- if (missingDependency) return missingDependency;
2740
- throw error;
2741
2718
  }
2742
2719
  }
2743
2720
  async function executeLspRename(params, signal) {
2744
- const filePath = requireString(params, "filePath");
2745
- const line = requireNumber(params, "line");
2746
- const character = requireNumber(params, "character");
2721
+ const { filePath, line, character } = sourcePosition(params);
2747
2722
  const newName = requireString(params, "newName");
2748
2723
  try {
2749
2724
  const edit = await withLspClient(filePath, async (client, workspaceRoot) => ({
@@ -2761,7 +2736,7 @@ async function executeLspRename(params, signal) {
2761
2736
  };
2762
2737
  return text(formatApplyResult(apply), details, !apply.success);
2763
2738
  } catch (error) {
2764
- const missingDependency = missingDependencyResult(error, {
2739
+ return missingDependencyResultOrThrow(error, {
2765
2740
  filePath,
2766
2741
  line,
2767
2742
  character,
@@ -2769,8 +2744,6 @@ async function executeLspRename(params, signal) {
2769
2744
  apply: null,
2770
2745
  edit: null
2771
2746
  });
2772
- if (missingDependency) return missingDependency;
2773
- throw error;
2774
2747
  }
2775
2748
  }
2776
2749
  //#endregion
@@ -2838,7 +2811,7 @@ async function executeLspSymbols(params, signal) {
2838
2811
  return formatSymbolsResult(filePath, scope, await withLspClient(filePath, async (client) => client.documentSymbols(filePath), "documentSymbols", clientOptions(signal)), limit);
2839
2812
  } catch (error) {
2840
2813
  const query = optionalString(params, "query");
2841
- const missingDependency = missingDependencyResult(error, {
2814
+ return missingDependencyResultOrThrow(error, {
2842
2815
  filePath,
2843
2816
  scope,
2844
2817
  symbols: [],
@@ -2846,8 +2819,6 @@ async function executeLspSymbols(params, signal) {
2846
2819
  truncated: false,
2847
2820
  ...query === void 0 ? {} : { query }
2848
2821
  });
2849
- if (missingDependency) return missingDependency;
2850
- throw error;
2851
2822
  }
2852
2823
  }
2853
2824
  function formatSymbolsResult(filePath, scope, symbols, limit, query) {
@@ -2872,6 +2843,21 @@ function formatSymbolsResult(filePath, scope, symbols, limit, query) {
2872
2843
  }
2873
2844
  //#endregion
2874
2845
  //#region packages/lsp-core/src/tools/definitions.ts
2846
+ var POSITION_PROPERTIES = {
2847
+ line: {
2848
+ type: "number",
2849
+ description: "1-based line number."
2850
+ },
2851
+ character: {
2852
+ type: "number",
2853
+ description: "0-based column."
2854
+ }
2855
+ };
2856
+ var POSITION_REQUIRED = [
2857
+ "filePath",
2858
+ "line",
2859
+ "character"
2860
+ ];
2875
2861
  var LSP_MCP_TOOLS = [
2876
2862
  {
2877
2863
  name: "status",
@@ -2915,19 +2901,8 @@ var LSP_MCP_TOOLS = [
2915
2901
  type: "string",
2916
2902
  description: "Source file containing the symbol."
2917
2903
  },
2918
- line: {
2919
- type: "number",
2920
- description: "1-based line number."
2921
- },
2922
- character: {
2923
- type: "number",
2924
- description: "0-based column."
2925
- }
2926
- }, [
2927
- "filePath",
2928
- "line",
2929
- "character"
2930
- ]),
2904
+ ...POSITION_PROPERTIES
2905
+ }, POSITION_REQUIRED),
2931
2906
  execute: executeLspGotoDefinition
2932
2907
  },
2933
2908
  {
@@ -2940,23 +2915,12 @@ var LSP_MCP_TOOLS = [
2940
2915
  type: "string",
2941
2916
  description: "Source file containing the symbol."
2942
2917
  },
2943
- line: {
2944
- type: "number",
2945
- description: "1-based line number."
2946
- },
2947
- character: {
2948
- type: "number",
2949
- description: "0-based column."
2950
- },
2918
+ ...POSITION_PROPERTIES,
2951
2919
  includeDeclaration: {
2952
2920
  type: "boolean",
2953
2921
  description: "Include the declaration. Defaults to true."
2954
2922
  }
2955
- }, [
2956
- "filePath",
2957
- "line",
2958
- "character"
2959
- ]),
2923
+ }, POSITION_REQUIRED),
2960
2924
  execute: executeLspFindReferences
2961
2925
  },
2962
2926
  {
@@ -2995,19 +2959,8 @@ var LSP_MCP_TOOLS = [
2995
2959
  type: "string",
2996
2960
  description: "Source file path."
2997
2961
  },
2998
- line: {
2999
- type: "number",
3000
- description: "1-based line number."
3001
- },
3002
- character: {
3003
- type: "number",
3004
- description: "0-based column."
3005
- }
3006
- }, [
3007
- "filePath",
3008
- "line",
3009
- "character"
3010
- ]),
2962
+ ...POSITION_PROPERTIES
2963
+ }, POSITION_REQUIRED),
3011
2964
  execute: executeLspPrepareRename
3012
2965
  },
3013
2966
  {
@@ -3020,14 +2973,7 @@ var LSP_MCP_TOOLS = [
3020
2973
  type: "string",
3021
2974
  description: "Source file path."
3022
2975
  },
3023
- line: {
3024
- type: "number",
3025
- description: "1-based line number."
3026
- },
3027
- character: {
3028
- type: "number",
3029
- description: "0-based column."
3030
- },
2976
+ ...POSITION_PROPERTIES,
3031
2977
  newName: {
3032
2978
  type: "string",
3033
2979
  description: "New symbol name."
@@ -3072,7 +3018,7 @@ function coerceToolArguments(value) {
3072
3018
  //#endregion
3073
3019
  //#region packages/lsp-core/src/mcp.ts
3074
3020
  var SERVER_NAME = "lsp";
3075
- var SERVER_VERSION = "0.5.1";
3021
+ var SERVER_VERSION = "0.5.3";
3076
3022
  async function handleLspMcpRequest(input) {
3077
3023
  if (!isPlainRecord(input)) return errorResponse(null, -32600, "Invalid Request");
3078
3024
  const id = jsonRpcId(input["id"]);
@@ -3439,7 +3385,7 @@ function daemonUnreachableResult(paths, error) {
3439
3385
  content: [{
3440
3386
  type: "text",
3441
3387
  text: [
3442
- `LSP daemon unreachable: ${error instanceof Error ? error.message : String(error)}.`,
3388
+ `LSP daemon unreachable: ${messageFromError(error)}.`,
3443
3389
  "The MCP server is a thin proxy and never runs language servers in-process.",
3444
3390
  `Socket: ${paths.socket}`,
3445
3391
  `Logs: ${paths.log}`,
@@ -3509,7 +3455,7 @@ async function runMcpStdioProxy(options = {}) {
3509
3455
  ...options.ensure ? { ensure: options.ensure } : {}
3510
3456
  },
3511
3457
  onHandlerError: (error) => {
3512
- process.stderr.write(`[lsp-daemon] proxy error: ${error instanceof Error ? error.message : String(error)}\n`);
3458
+ process.stderr.write(`[lsp-daemon] proxy error: ${messageFromError(error)}\n`);
3513
3459
  }
3514
3460
  });
3515
3461
  }
@@ -3659,7 +3605,7 @@ async function main() {
3659
3605
  process.exitCode = 2;
3660
3606
  }
3661
3607
  main().catch((error) => {
3662
- stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
3608
+ stderr.write(`${stackOrMessageFromError(error)}\n`);
3663
3609
  process.exitCode = 1;
3664
3610
  });
3665
3611
  //#endregion
@@ -31,6 +31,9 @@ function jsonRpcId(value) {
31
31
  function messageFromError(error) {
32
32
  return error instanceof Error ? error.message : String(error);
33
33
  }
34
+ function stackOrMessageFromError(error) {
35
+ return error instanceof Error ? error.stack ?? error.message : String(error);
36
+ }
34
37
  //#endregion
35
38
  //#region packages/mcp-stdio-core/src/transport.ts
36
39
  var HEADER_SEPARATOR = Buffer.from("\r\n\r\n");
@@ -118,7 +121,7 @@ function parseJsonPayload(payload, responseMode) {
118
121
  } catch (error) {
119
122
  return {
120
123
  kind: "parse_error",
121
- message: error instanceof Error ? error.message : String(error),
124
+ message: messageFromError(error),
122
125
  responseMode
123
126
  };
124
127
  }
@@ -206,4 +209,4 @@ function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
206
209
  };
207
210
  }
208
211
  //#endregion
209
- export { successResponse as a, messageFromError as i, errorResponse as n, isPlainRecord as o, jsonRpcId as r, runJsonRpcStdioServer as t };
212
+ export { stackOrMessageFromError as a, messageFromError as i, errorResponse as n, successResponse as o, jsonRpcId as r, isPlainRecord as s, runJsonRpcStdioServer as t };
@@ -13,15 +13,15 @@ Create one bounded, verifiable objective; no plan, log, snapshot, ledger, handof
13
13
 
14
14
  ## Flow
15
15
 
16
- 1. State concrete desired outcome, target, completion criteria, acceptable proof, scope, exclusions, input blocker, and explicit stop condition.
16
+ 1. State concrete outcome, target, completion criteria, proof, scope, exclusions, input blocker, and stop condition.
17
17
  2. Add useful checks, paths, environments, counts, or limits; no fake precision or quality ratchet.
18
- 3. Replace activity goals like “improve” with observable state. Bound subjective quality by the approved task and named validator.
18
+ 3. Replace activity goals such as “improve” with observable state. Bound subjective quality by approved task and named validator.
19
19
  4. Ask one short question only if missing scope or proof would materially change intent.
20
20
  5. Call `get_goal`.
21
21
  - No goal: quality-check, then `create_goal`.
22
22
  - Same active goal: reuse.
23
23
  - Conflicting goal: ask whether to finish it or use another task.
24
- 6. Call `create_goal` with one concise objective. Set token budget only when user explicitly asks. Stop once the objective's criteria pass; do not extend it for polishing, speculative expansion, repeated review, adjacent work, or newly noticed opportunities.
24
+ 6. Call `create_goal` with one concise objective. Set token budget only when explicitly requested. Stop when criteria pass; do not extend for polish, speculation, repeated review, adjacent work, or new opportunities.
25
25
 
26
26
  ## Quality gate
27
27
 
@@ -5,46 +5,46 @@ description: Use when a task needs frontend, web UI, UX, visual design, interact
5
5
 
6
6
  # Frontend
7
7
 
8
- Preserve stack, behavior, tokens, patterns, supplied visual contract, and product identity. Keep scope small. Avoid generic AI styling. Do not force `DESIGN.md`, research, dependencies, GSAP, or heavy QA.
8
+ Preserve stack, behavior, tokens, patterns, visual contract, and identity. Keep scope small; avoid generic AI styling. Do not force `DESIGN.md`, research, dependencies, GSAP, or heavy QA.
9
9
 
10
10
  ## Approval sequence
11
11
 
12
12
  1. Load `frontend`; inspect the request, product shell, target surface, design tokens, nearest pattern, responsive contract, supplied references, and relevant states.
13
- 2. Select only material design decisions: visual direction, typography, layout and density, color and surfaces, assets, responsive behavior, applicable states, plus a motion system and accessibility treatment for every task. Define how motion communicates hierarchy, state, interaction, continuity, or navigation; keep it proportional. Define `prefers-reduced-motion`, keyboard operation, focus visibility, semantics, contrast, and labels. Preserve established decisions unless change is requested.
13
+ 2. Select only material decisions: direction, type, layout/density, color/surfaces, assets, responsiveness, applicable states, plus a motion system and accessibility treatment for every task. Give motion a proportional hierarchy, state, interaction, continuity, or navigation purpose. Define `prefers-reduced-motion`, keyboard operation, focus visibility, semantics, contrast, and labels. Preserve established decisions unless change is requested.
14
14
  3. Present the compact decision set with existing constraints and ask for approval before implementation. For a fix, audit, accessibility, or performance task, include only decisions that alter user-visible design; diagnosis and technical implementation details need no approval.
15
15
  4. After approval, ask whether the user wants to define a goal. Only after explicit agreement load `define-goal`; otherwise implement.
16
16
 
17
- Approval owns visible direction and material interaction changes. Existing component APIs, code structure, exact CSS values, breakpoint mechanics, libraries already required by the approved route, and other reversible implementation details remain implementation decisions.
17
+ Approval owns visible direction and material interaction. Component APIs, code structure, exact CSS, breakpoint mechanics, route-required libraries, and other reversible implementation details remain implementation decisions.
18
18
 
19
19
  ## Route
20
20
 
21
- - Build/redesign: inspect shell, tokens, target component, responsive contract.
22
- - Visual reference: use it first; measure layout, type, color, spacing, surface, and motion.
21
+ - Build/redesign: inspect shell, tokens, component, responsive contract.
22
+ - Visual reference: use first; measure layout, type, color, spacing, surface, motion.
23
23
  - Performance: load `references/perfection/README.md` only for real audit or regression.
24
24
  - Palette/type/style: load only relevant `references/ui-ux-db` data.
25
25
  - Motion-rich premium React/Tailwind page creation or redesign: mandatory GPT Taste route below. Ordinary fixes, debugging, accessibility, and performance work stay on normal route.
26
26
 
27
27
  ## GPT Taste route
28
28
 
29
- - During approval, emit `<design_plan>` with prompt-derived visual direction, type, layout, motion, responsive, accessibility, and state choices. Established contracts win.
29
+ - During approval, emit `<design_plan>` with prompt-derived direction, type, layout, motion, responsive, accessibility, and state choices. Established contracts win.
30
30
  - Treat AIDA, bento layouts, font shortlists, GSAP, Picsum, component counts, and named motion patterns as options only when they fit product, task, and stack.
31
- - For each chosen pattern, state its user-facing purpose and containment. Do not add dependencies or remote assets unless approved and required.
31
+ - State each chosen pattern's user-facing purpose and containment. Add no dependency or remote asset unless approved and required.
32
32
  - Motion is required but may be subtle. Avoid gratuitous, blocking, performance-heavy, or reduced-motion-unsafe effects.
33
33
  - Prevent horizontal overflow, clipped content, dead layouts, empty cards, fake dashboards, copied text, and inaccessible interaction.
34
34
 
35
35
  Ban emojis; cheap/generic meta-labels (`SECTION 01`, `QUESTION 05`, `ABOUT US`); invisible button text; empty bento cells/cards; narrow multi-line/centered heroes; repeated left/right or flat sections/backgrounds; stock-feeling imagery; fake dashboards; meaningless gradients; copied reference text.
36
36
 
37
- Required `<design_plan>`: visible direction; layout and responsive contract; asset role; motion purpose and reduced-motion fallback; accessibility treatment; applicable loading, error, and empty states. Include only chosen patterns, not a fixed architecture count.
37
+ Required `<design_plan>`: visible direction; layout/responsive contract; asset role; motion purpose/reduced-motion fallback; accessibility treatment; applicable loading, error, and empty states. Include only chosen patterns, never a fixed architecture count.
38
38
 
39
39
  Only after approval and optional goal choice may implementation begin.
40
40
 
41
41
  ## Implementation
42
42
 
43
- 1. Inspect target and nearest established pattern.
44
- 2. Lock visual direction: type, spacing, surfaces, color, asset role, motion role.
45
- 3. Implement smallest coherent slice with purposeful motion, reduced-motion behavior, keyboard operation, visible focus, semantic structure, contrast, and labels.
46
- 4. Test narrow/mobile/wide containment. No horizontal leak, clipped text, overlap, or unreadable measure.
43
+ 1. Inspect target and nearest pattern.
44
+ 2. Lock type, spacing, surfaces, color, asset role, and motion role.
45
+ 3. Implement smallest coherent slice with purposeful motion, reduced motion, keyboard operation, visible focus, semantics, contrast, and labels.
46
+ 4. Test narrow/mobile/wide containment: no horizontal leak, clipped text, overlap, or unreadable measure.
47
47
  5. Check loading, error, and empty states when applicable.
48
- 6. Check interaction and performance proportional to change. Avoid layout shift, oversized media, needless client work.
48
+ 6. Check proportional interaction/performance. Avoid layout shift, oversized media, needless client work.
49
49
 
50
50
  Use real assets when supplied. Never invent research or claim screenshot parity without visual comparison.
@@ -5,28 +5,37 @@ description: Use when a task edits Python, Rust, TypeScript, Go, or their matchi
5
5
 
6
6
  # Programming
7
7
 
8
- Before editing `.py`, `.pyi`, `.rs`, `.ts`, `.tsx`, `.mts`, `.cts`, `.go`, or matching manifests, read `references/<language>/README.md`. Load `references/logging.md` only for logs and all `references/rust-ub/` for Rust unsafe or FFI.
8
+ Before editing `.py`, `.pyi`, `.rs`, `.ts`, `.tsx`, `.mts`, `.cts`, `.go`, or matching manifests, read `references/<language>/README.md`. Load `references/logging.md` only for logs; load all `references/rust-ub/` for Rust unsafe/FFI.
9
9
 
10
10
  ## Core
11
11
 
12
- - Best code: none, existing helper, standard API, native feature, installed dependency, one line, then new code.
12
+ - Prefer, in order: no code, existing helper, standard API, native feature, installed dependency, one line, new code.
13
13
  - Trace real flow and callers. Fix shared root seam once.
14
14
  - Parse untrusted input once at boundary. Interior stays typed.
15
- - Make illegal states unrepresentable. Distinct primitives get distinct types.
16
- - Immutable default. No parameter mutation without explicit purpose.
15
+ - Make illegal states unrepresentable; give distinct primitives distinct types.
16
+ - Default immutable; mutate parameters only with explicit purpose.
17
17
  - Exhaustive variant handling.
18
18
  - No untyped escape, ignored diagnostics, non-null assertion, unchecked cast, panic/unwrap in library path.
19
19
  - Typed errors. Catch only expected errors; unknown errors propagate to boundary.
20
20
  - Existing project stack and logger win.
21
- - No helper for one caller. No speculative abstraction.
21
+ - No one-caller helper or speculative abstraction.
22
+
23
+ ## Reuse
24
+
25
+ - One behavior, one implementation.
26
+ - Search before writing; reuse or extend the existing implementation.
27
+ - Never copy-paste logic or maintain parallel variants.
28
+ - Put shared behavior in the smallest stable function, method, type, or module at its common ownership seam. Callers pass data, not reimplement policy.
29
+ - Extract repetition when a second caller or copy exists. Keep one-caller mechanics local unless they form a stable domain abstraction.
30
+ - Reusable code needs cohesive names, explicit typed I/O, and public-seam tests. Parameterize real variation; reject caller branches and boolean modes.
22
31
 
23
32
  ## Test
24
33
 
25
- Defect: add a public-seam regression test first and confirm the intended failure. Explicit test-first request or clearly defined new behavior without adequate proof: test public seam first, confirm failure, implement minimum green, then refactor. Existing tests may lock small covered changes. Do not force red-green for prose, configuration-only work, trivial mechanical edits, or behavior already adequately covered. Use real object or fake before mock. Deterministic fixture; no sleep. Add an end-to-end user outcome for new behavior when proportional. Run smallest test in loop.
34
+ Defect: add a public-seam regression test first and confirm the intended failure. Explicit test-first request or clearly defined new behavior without adequate proof: test public seam, confirm failure, implement minimum green, refactor. Existing tests may lock small covered changes. Do not force red-green for prose, configuration-only work, trivial mechanical edits, or behavior already adequately covered. Prefer real object or fake to mock; use deterministic fixtures, never sleep. Add a proportional end-to-end user outcome for new behavior. Run smallest test in loop.
26
35
 
27
36
  ## Size
28
37
 
29
- After write, measure pure LOC. Under 200 healthy; 200–250 warn; over 250 split unless generated table or documented indivisible state machine. Function over three independent parameters needs named domain input or specific reason.
38
+ After writing, measure pure LOC: under 200 healthy; 200–250 warn; over 250 split unless generated table or documented indivisible state machine. Over three independent parameters requires named domain input or a specific reason.
30
39
 
31
40
  ## Finish
32
41
 
@@ -5,17 +5,17 @@ description: Use when an authorized task needs repository security review, threa
5
5
 
6
6
  # Security Research
7
7
 
8
- Main agent owns scope, threat surface, dedupe, proof, severity, report. No Team Mode. At most two independent lanes when useful: `explorer` for one internal surface; `librarian` for named standards or dependency facts. No duplicate hunters, recursive delegation, reviewer loop, or full-history fork.
8
+ Main agent owns scope, threat surface, dedupe, proof, severity, report. No Team Mode. When useful, at most two independent lanes: `explorer` for one internal surface; `librarian` for named standards/dependency facts. No duplicate hunters, recursive delegation, reviewer loop, or full-history fork.
9
9
 
10
10
  ## Rules
11
11
 
12
12
  - Name target: repo, diff, path, release, or threat surface.
13
- - Map entry points, attacker input, trust boundaries, sensitive assets, sinks, privilege transitions.
13
+ - Map entry points, attacker input, trust boundaries, assets, sinks, privilege transitions.
14
14
  - No severity without reachable attack path.
15
- - High or critical needs safe local PoC or decisive static proof plus concrete preconditions and impact.
15
+ - High/critical needs safe local PoC or decisive static proof with concrete preconditions and impact.
16
16
  - CWE classifies weakness. Severity measures exploitability and impact. Keep separate.
17
17
  - Generic hardening is not finding.
18
- - Never attack real or third-party systems. Use local fixture, toy payload, dry run, or static proof.
18
+ - Never attack real/third-party systems; use local fixture, toy payload, dry run, or static proof.
19
19
 
20
20
  ## Flow
21
21
 
@@ -23,16 +23,16 @@ Main agent owns scope, threat surface, dedupe, proof, severity, report. No Team
23
23
  2. Threat surface: attacker capability, controlled input, boundary, sink, asset.
24
24
  3. Candidates: title, path/function, attack path, impact, CWE candidate, evidence, safe proof idea.
25
25
  4. Deduplicate by root cause and attack path.
26
- 5. Validate strongest candidate. Reproduce, falsify, or downgrade. Record exact command and observed output.
27
- 6. Calibrate severity from proven preconditions, reachability, privilege, user action, scope, confidentiality, integrity, availability.
26
+ 5. Validate strongest candidate: reproduce, falsify, or downgrade. Record exact command/output.
27
+ 6. Calibrate severity from proven preconditions, reachability, privilege, user action, scope, confidentiality, integrity, and availability.
28
28
  7. Give minimum fix and public-seam regression test.
29
29
 
30
30
  ## Report
31
31
 
32
32
  Lead with `PASS`, `PASS WITH FINDINGS`, or `BLOCK`.
33
33
 
34
- For each surviving finding: severity, title, CWE, affected path/function, attacker capability, attack path, proof, impact, minimum fix, regression check.
34
+ Each finding: severity, title, CWE, affected path/function, attacker capability, attack path, proof, impact, minimum fix, regression check.
35
35
 
36
- Also list downgraded and rejected candidates with reason. End with residual risk: untested surfaces and why.
36
+ List downgraded/rejected candidates with reasons. End with residual risk: untested surfaces and why.
37
37
 
38
38
  Use CWE, OWASP WSTG/ASVS, and CVSS v4 only when relevant. Cite exact source. Do not claim precise CVSS score without scoring every metric.