knowns 0.10.5 → 0.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9108,7 +9108,7 @@ var require_dist = __commonJS({
9108
9108
  });
9109
9109
  };
9110
9110
  }
9111
- var prompts4 = require_prompts();
9111
+ var prompts3 = require_prompts();
9112
9112
  var passOn = ["suggest", "format", "onState", "validate", "onRender", "type"];
9113
9113
  var noop = () => {
9114
9114
  };
@@ -9159,7 +9159,7 @@ var require_dist = __commonJS({
9159
9159
  var _question2 = question;
9160
9160
  name = _question2.name;
9161
9161
  type = _question2.type;
9162
- if (prompts4[type] === void 0) {
9162
+ if (prompts3[type] === void 0) {
9163
9163
  throw new Error(`prompt type (${type}) is not defined`);
9164
9164
  }
9165
9165
  if (override2[question.name] !== void 0) {
@@ -9170,7 +9170,7 @@ var require_dist = __commonJS({
9170
9170
  }
9171
9171
  }
9172
9172
  try {
9173
- answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : yield prompts4[type](question);
9173
+ answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : yield prompts3[type](question);
9174
9174
  answers[name] = answer = yield getFormattedAnswer(question, answer, true);
9175
9175
  quit = yield onSubmit(question, answer, answers);
9176
9176
  } catch (err) {
@@ -9202,7 +9202,7 @@ var require_dist = __commonJS({
9202
9202
  }
9203
9203
  module2.exports = Object.assign(prompt, {
9204
9204
  prompt,
9205
- prompts: prompts4,
9205
+ prompts: prompts3,
9206
9206
  inject,
9207
9207
  override
9208
9208
  });
@@ -11285,7 +11285,7 @@ var require_prompts2 = __commonJS({
11285
11285
  var require_lib = __commonJS({
11286
11286
  "node_modules/prompts/lib/index.js"(exports2, module2) {
11287
11287
  "use strict";
11288
- var prompts4 = require_prompts2();
11288
+ var prompts3 = require_prompts2();
11289
11289
  var passOn = ["suggest", "format", "onState", "validate", "onRender", "type"];
11290
11290
  var noop = () => {
11291
11291
  };
@@ -11317,7 +11317,7 @@ var require_lib = __commonJS({
11317
11317
  throw new Error("prompt message is required");
11318
11318
  }
11319
11319
  ({ name, type } = question);
11320
- if (prompts4[type] === void 0) {
11320
+ if (prompts3[type] === void 0) {
11321
11321
  throw new Error(`prompt type (${type}) is not defined`);
11322
11322
  }
11323
11323
  if (override2[question.name] !== void 0) {
@@ -11328,7 +11328,7 @@ var require_lib = __commonJS({
11328
11328
  }
11329
11329
  }
11330
11330
  try {
11331
- answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : await prompts4[type](question);
11331
+ answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : await prompts3[type](question);
11332
11332
  answers[name] = answer = await getFormattedAnswer(question, answer, true);
11333
11333
  quit = await onSubmit(question, answer, answers);
11334
11334
  } catch (err) {
@@ -11351,7 +11351,7 @@ var require_lib = __commonJS({
11351
11351
  function override(answers) {
11352
11352
  prompt._override = Object.assign({}, answers);
11353
11353
  }
11354
- module2.exports = Object.assign(prompt, { prompt, prompts: prompts4, inject, override });
11354
+ module2.exports = Object.assign(prompt, { prompt, prompts: prompts3, inject, override });
11355
11355
  }
11356
11356
  });
11357
11357
 
@@ -14378,7 +14378,7 @@ var require_util3 = __commonJS({
14378
14378
  return path3;
14379
14379
  }
14380
14380
  exports2.normalize = normalize3;
14381
- function join42(aRoot, aPath) {
14381
+ function join43(aRoot, aPath) {
14382
14382
  if (aRoot === "") {
14383
14383
  aRoot = ".";
14384
14384
  }
@@ -14410,7 +14410,7 @@ var require_util3 = __commonJS({
14410
14410
  }
14411
14411
  return joined;
14412
14412
  }
14413
- exports2.join = join42;
14413
+ exports2.join = join43;
14414
14414
  exports2.isAbsolute = function(aPath) {
14415
14415
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
14416
14416
  };
@@ -14583,7 +14583,7 @@ var require_util3 = __commonJS({
14583
14583
  parsed.path = parsed.path.substring(0, index + 1);
14584
14584
  }
14585
14585
  }
14586
- sourceURL = join42(urlGenerate(parsed), sourceURL);
14586
+ sourceURL = join43(urlGenerate(parsed), sourceURL);
14587
14587
  }
14588
14588
  return normalize3(sourceURL);
14589
14589
  }
@@ -36815,9 +36815,9 @@ var require_view = __commonJS({
36815
36815
  var path3 = __require("node:path");
36816
36816
  var fs = __require("node:fs");
36817
36817
  var dirname9 = path3.dirname;
36818
- var basename4 = path3.basename;
36818
+ var basename5 = path3.basename;
36819
36819
  var extname = path3.extname;
36820
- var join42 = path3.join;
36820
+ var join43 = path3.join;
36821
36821
  var resolve3 = path3.resolve;
36822
36822
  module2.exports = View;
36823
36823
  function View(name, options2) {
@@ -36854,7 +36854,7 @@ var require_view = __commonJS({
36854
36854
  var root = roots[i];
36855
36855
  var loc = resolve3(root, name);
36856
36856
  var dir = dirname9(loc);
36857
- var file3 = basename4(loc);
36857
+ var file3 = basename5(loc);
36858
36858
  path4 = this.resolve(dir, file3);
36859
36859
  }
36860
36860
  return path4;
@@ -36879,12 +36879,12 @@ var require_view = __commonJS({
36879
36879
  };
36880
36880
  View.prototype.resolve = function resolve4(dir, file3) {
36881
36881
  var ext2 = this.ext;
36882
- var path4 = join42(dir, file3);
36882
+ var path4 = join43(dir, file3);
36883
36883
  var stat5 = tryStat(path4);
36884
36884
  if (stat5 && stat5.isFile()) {
36885
36885
  return path4;
36886
36886
  }
36887
- path4 = join42(dir, basename4(file3, ext2), "index" + ext2);
36887
+ path4 = join43(dir, basename5(file3, ext2), "index" + ext2);
36888
36888
  stat5 = tryStat(path4);
36889
36889
  if (stat5 && stat5.isFile()) {
36890
36890
  return path4;
@@ -40168,7 +40168,7 @@ var require_content_disposition = __commonJS({
40168
40168
  "use strict";
40169
40169
  module2.exports = contentDisposition;
40170
40170
  module2.exports.parse = parse4;
40171
- var basename4 = __require("path").basename;
40171
+ var basename5 = __require("path").basename;
40172
40172
  var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
40173
40173
  var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
40174
40174
  var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g;
@@ -40203,9 +40203,9 @@ var require_content_disposition = __commonJS({
40203
40203
  if (typeof fallback === "string" && NON_LATIN1_REGEXP.test(fallback)) {
40204
40204
  throw new TypeError("fallback must be ISO-8859-1 string");
40205
40205
  }
40206
- var name = basename4(filename);
40206
+ var name = basename5(filename);
40207
40207
  var isQuotedString = TEXT_REGEXP.test(name);
40208
- var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename4(fallback);
40208
+ var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename5(fallback);
40209
40209
  var hasFallback = typeof fallbackName === "string" && fallbackName !== name;
40210
40210
  if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) {
40211
40211
  params["filename*"] = name;
@@ -40529,7 +40529,7 @@ var require_send = __commonJS({
40529
40529
  var Stream2 = __require("stream");
40530
40530
  var util2 = __require("util");
40531
40531
  var extname = path3.extname;
40532
- var join42 = path3.join;
40532
+ var join43 = path3.join;
40533
40533
  var normalize3 = path3.normalize;
40534
40534
  var resolve3 = path3.resolve;
40535
40535
  var sep3 = path3.sep;
@@ -40701,7 +40701,7 @@ var require_send = __commonJS({
40701
40701
  return res;
40702
40702
  }
40703
40703
  parts = path4.split(sep3);
40704
- path4 = normalize3(join42(root, path4));
40704
+ path4 = normalize3(join43(root, path4));
40705
40705
  } else {
40706
40706
  if (UP_PATH_REGEXP.test(path4)) {
40707
40707
  debug('malicious path "%s"', path4);
@@ -40834,7 +40834,7 @@ var require_send = __commonJS({
40834
40834
  if (err) return self.onStatError(err);
40835
40835
  return self.error(404);
40836
40836
  }
40837
- var p = join42(path4, self._index[i]);
40837
+ var p = join43(path4, self._index[i]);
40838
40838
  debug('stat "%s"', p);
40839
40839
  fs.stat(p, function(err2, stat5) {
40840
40840
  if (err2) return next(err2);
@@ -58796,7 +58796,7 @@ var {
58796
58796
  } = import_index.default;
58797
58797
 
58798
58798
  // src/commands/init.ts
58799
- var import_prompts2 = __toESM(require_prompts3(), 1);
58799
+ var import_prompts = __toESM(require_prompts3(), 1);
58800
58800
 
58801
58801
  // src/codegen/skill-sync.ts
58802
58802
  import { existsSync as existsSync2 } from "node:fs";
@@ -59407,7 +59407,7 @@ function detectPlatforms(projectRoot) {
59407
59407
  }
59408
59408
 
59409
59409
  // src/instructions/guidelines/unified/commands-reference.md
59410
- var commands_reference_default = '{{#if mcp}}\n# MCP Tools Reference\n\n## Task Tools\n\n### mcp__knowns__create_task\n\n```json\n{\n "title": "Task title",\n "description": "Task description",\n "status": "todo",\n "priority": "medium",\n "labels": ["label1"],\n "assignee": "@me",\n "parent": "parent-id"\n}\n```\n\n### mcp__knowns__update_task\n\n```json\n{\n "taskId": "<id>",\n "status": "in-progress",\n "assignee": "@me",\n "addAc": ["Criterion 1", "Criterion 2"],\n "checkAc": [1, 2],\n "uncheckAc": [3],\n "removeAc": [4],\n "plan": "1. Step one\\n2. Step two",\n "notes": "Implementation notes",\n "appendNotes": "Additional notes"\n}\n```\n\n| Field | Purpose |\n|-------|---------|\n| `addAc` | Add new acceptance criteria |\n| `checkAc` | Mark AC done (1-based index) |\n| `uncheckAc` | Unmark AC (1-based index) |\n| `removeAc` | Remove AC (1-based index) |\n| `plan` | Set implementation plan |\n| `notes` | Replace implementation notes |\n| `appendNotes` | Append to notes |\n\n### mcp__knowns__get_task\n\n```json\n{ "taskId": "<id>" }\n```\n\n### mcp__knowns__list_tasks\n\n```json\n{ "status": "in-progress", "assignee": "@me" }\n```\n\n### mcp__knowns__search_tasks\n\n```json\n{ "query": "keyword" }\n```\n\n---\n\n## Doc Tools\n\n### mcp__knowns__get_doc\n\n**ALWAYS use `smart: true`** - auto-handles small/large docs:\n\n```json\n{ "path": "readme", "smart": true }\n```\n\nIf large, returns TOC. Then read section:\n```json\n{ "path": "readme", "section": "3" }\n```\n\n### mcp__knowns__list_docs\n\n```json\n{ "tag": "api" }\n```\n\n### mcp__knowns__create_doc\n\n```json\n{\n "title": "Doc Title",\n "description": "Description",\n "tags": ["tag1"],\n "folder": "guides",\n "content": "Initial content"\n}\n```\n\n### mcp__knowns__update_doc\n\n```json\n{\n "path": "readme",\n "content": "Replace content",\n "section": "2"\n}\n```\n\n### mcp__knowns__search_docs\n\n```json\n{ "query": "keyword", "tag": "api" }\n```\n\n### mcp__knowns__search (Unified)\n\n```json\n{\n "query": "keyword",\n "type": "all",\n "status": "in-progress",\n "priority": "high",\n "assignee": "@me",\n "label": "feature",\n "tag": "api",\n "limit": 20\n}\n```\n\n| Field | Purpose |\n|-------|---------|\n| `type` | "all", "task", or "doc" |\n| `status/priority/assignee/label` | Task filters |\n| `tag` | Doc filter |\n| `limit` | Max results (default: 20) |\n\n---\n\n## Time Tools\n\n### mcp__knowns__start_time\n\n```json\n{ "taskId": "<id>" }\n```\n\n### mcp__knowns__stop_time\n\n```json\n{ "taskId": "<id>" }\n```\n\n### mcp__knowns__add_time\n\n```json\n{\n "taskId": "<id>",\n "duration": "2h30m",\n "note": "Note",\n "date": "2025-01-15"\n}\n```\n\n### mcp__knowns__get_time_report\n\n```json\n{ "from": "2025-01-01", "to": "2025-01-31", "groupBy": "task" }\n```\n\n---\n\n## Template Tools\n\n### mcp__knowns__list_templates\n\n```json\n{}\n```\n\n### mcp__knowns__get_template\n\n```json\n{ "name": "template-name" }\n```\n\n### mcp__knowns__run_template\n\n```json\n{\n "name": "template-name",\n "variables": { "name": "MyComponent" },\n "dryRun": true\n}\n```\n\n### mcp__knowns__create_template\n\n```json\n{\n "name": "my-template",\n "description": "Description",\n "doc": "patterns/my-pattern"\n}\n```\n\n---\n\n## Other\n\n### mcp__knowns__get_board\n\n```json\n{}\n```\n\n{{/if}}\n{{#if cli}}\n# CLI Commands Reference\n\n## task create\n\n```bash\nknowns task create <title> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--description` | `-d` | Task description |\n| `--ac` | | Acceptance criterion (repeatable) |\n| `--labels` | `-l` | Comma-separated labels |\n| `--assignee` | `-a` | Assign to user |\n| `--priority` | | low/medium/high |\n| `--parent` | | Parent task ID (raw ID only!) |\n\n**`-a` = assignee, NOT acceptance criteria! Use `--ac` for AC.**\n\n---\n\n## task edit\n\n```bash\nknowns task edit <id> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--status` | `-s` | Change status |\n| `--assignee` | `-a` | Assign user |\n| `--ac` | | Add acceptance criterion |\n| `--check-ac` | | Mark AC done (1-indexed) |\n| `--uncheck-ac` | | Unmark AC |\n| `--plan` | | Set implementation plan |\n| `--notes` | | Replace notes |\n| `--append-notes` | | Add to notes |\n\n---\n\n## task view/list\n\n```bash\nknowns task <id> --plain\nknowns task list --plain\nknowns task list --status in-progress --plain\nknowns task list --tree --plain\n```\n\n---\n\n## doc create\n\n```bash\nknowns doc create <title> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--description` | `-d` | Description |\n| `--tags` | `-t` | Comma-separated tags |\n| `--folder` | `-f` | Folder path |\n\n---\n\n## doc edit\n\n```bash\nknowns doc edit <name> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--content` | `-c` | Replace content |\n| `--append` | `-a` | Append content |\n| `--section` | | Target section (use with -c) |\n\n**In doc edit, `-a` = append content, NOT assignee!**\n\n---\n\n## doc view/list\n\n**ALWAYS use `--smart`** - auto-handles small/large docs:\n\n```bash\nknowns doc <path> --plain --smart\n```\n\nIf large, returns TOC. Then read section:\n```bash\nknowns doc <path> --plain --section 3\n```\n\n```bash\nknowns doc list --plain\nknowns doc list --tag api --plain\n```\n\n---\n\n## time\n\n```bash\nknowns time start <id> # REQUIRED when taking task\nknowns time stop # REQUIRED when completing\nknowns time status\nknowns time add <id> <duration> -n "Note"\n```\n\n---\n\n## search\n\n```bash\nknowns search "query" --plain\nknowns search "auth" --type task --plain\nknowns search "api" --type doc --plain\n```\n\n---\n\n## template\n\n```bash\nknowns template list\nknowns template info <name>\nknowns template run <name> --name "X" --dry-run\nknowns template create <name>\n```\n\n---\n\n## Multi-line Input\n\n```bash\nknowns task edit <id> --plan $\'1. Step\\n2. Step\\n3. Step\'\n```\n{{/if}}\n';
59410
+ var commands_reference_default = '{{#if mcp}}\n# MCP Tools Reference\n\n## Project Tools (Session Init)\n\n**CRITICAL: Call these at session start to initialize the project.**\n\n### mcp__knowns__detect_projects\n\nScan for all Knowns projects on the system:\n\n```json\n{}\n```\n\nReturns: `{ projects: [{ path, name }], currentProject, note }`\n\n### mcp__knowns__set_project\n\nSet the active project for all operations:\n\n```json\n{ "projectRoot": "/absolute/path/to/project" }\n```\n\n### mcp__knowns__get_current_project\n\nCheck current project status:\n\n```json\n{}\n```\n\nReturns: `{ projectRoot, isExplicitlySet, isValid, source }`\n\n---\n\n## Task Tools\n\n### mcp__knowns__create_task\n\n```json\n{\n "title": "Task title",\n "description": "Task description",\n "status": "todo",\n "priority": "medium",\n "labels": ["label1"],\n "assignee": "@me",\n "parent": "parent-id"\n}\n```\n\n### mcp__knowns__update_task\n\n```json\n{\n "taskId": "<id>",\n "status": "in-progress",\n "assignee": "@me",\n "addAc": ["Criterion 1", "Criterion 2"],\n "checkAc": [1, 2],\n "uncheckAc": [3],\n "removeAc": [4],\n "plan": "1. Step one\\n2. Step two",\n "notes": "Implementation notes",\n "appendNotes": "Additional notes"\n}\n```\n\n| Field | Purpose |\n|-------|---------|\n| `addAc` | Add new acceptance criteria |\n| `checkAc` | Mark AC done (1-based index) |\n| `uncheckAc` | Unmark AC (1-based index) |\n| `removeAc` | Remove AC (1-based index) |\n| `plan` | Set implementation plan |\n| `notes` | Replace implementation notes |\n| `appendNotes` | Append to notes |\n\n### mcp__knowns__get_task\n\n```json\n{ "taskId": "<id>" }\n```\n\n### mcp__knowns__list_tasks\n\n```json\n{ "status": "in-progress", "assignee": "@me" }\n```\n\n### mcp__knowns__search_tasks\n\n```json\n{ "query": "keyword" }\n```\n\n---\n\n## Doc Tools\n\n### mcp__knowns__get_doc\n\n**ALWAYS use `smart: true`** - auto-handles small/large docs:\n\n```json\n{ "path": "readme", "smart": true }\n```\n\nIf large, returns TOC. Then read section:\n```json\n{ "path": "readme", "section": "3" }\n```\n\n### mcp__knowns__list_docs\n\n```json\n{ "tag": "api" }\n```\n\n### mcp__knowns__create_doc\n\n```json\n{\n "title": "Doc Title",\n "description": "Description",\n "tags": ["tag1"],\n "folder": "guides",\n "content": "Initial content"\n}\n```\n\n### mcp__knowns__update_doc\n\n```json\n{\n "path": "readme",\n "content": "Replace content",\n "section": "2"\n}\n```\n\n### mcp__knowns__search_docs\n\n```json\n{ "query": "keyword", "tag": "api" }\n```\n\n### mcp__knowns__search (Unified)\n\n```json\n{\n "query": "keyword",\n "type": "all",\n "status": "in-progress",\n "priority": "high",\n "assignee": "@me",\n "label": "feature",\n "tag": "api",\n "limit": 20\n}\n```\n\n| Field | Purpose |\n|-------|---------|\n| `type` | "all", "task", or "doc" |\n| `status/priority/assignee/label` | Task filters |\n| `tag` | Doc filter |\n| `limit` | Max results (default: 20) |\n\n---\n\n## Time Tools\n\n### mcp__knowns__start_time\n\n```json\n{ "taskId": "<id>" }\n```\n\n### mcp__knowns__stop_time\n\n```json\n{ "taskId": "<id>" }\n```\n\n### mcp__knowns__add_time\n\n```json\n{\n "taskId": "<id>",\n "duration": "2h30m",\n "note": "Note",\n "date": "2025-01-15"\n}\n```\n\n### mcp__knowns__get_time_report\n\n```json\n{ "from": "2025-01-01", "to": "2025-01-31", "groupBy": "task" }\n```\n\n---\n\n## Template Tools\n\n### mcp__knowns__list_templates\n\n```json\n{}\n```\n\n### mcp__knowns__get_template\n\n```json\n{ "name": "template-name" }\n```\n\n### mcp__knowns__run_template\n\n```json\n{\n "name": "template-name",\n "variables": { "name": "MyComponent" },\n "dryRun": true\n}\n```\n\n### mcp__knowns__create_template\n\n```json\n{\n "name": "my-template",\n "description": "Description",\n "doc": "patterns/my-pattern"\n}\n```\n\n---\n\n## Other\n\n### mcp__knowns__get_board\n\n```json\n{}\n```\n\n{{/if}}\n{{#if cli}}\n# CLI Commands Reference\n\n## task create\n\n```bash\nknowns task create <title> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--description` | `-d` | Task description |\n| `--ac` | | Acceptance criterion (repeatable) |\n| `--labels` | `-l` | Comma-separated labels |\n| `--assignee` | `-a` | Assign to user |\n| `--priority` | | low/medium/high |\n| `--parent` | | Parent task ID (raw ID only!) |\n\n**`-a` = assignee, NOT acceptance criteria! Use `--ac` for AC.**\n\n---\n\n## task edit\n\n```bash\nknowns task edit <id> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--status` | `-s` | Change status |\n| `--assignee` | `-a` | Assign user |\n| `--ac` | | Add acceptance criterion |\n| `--check-ac` | | Mark AC done (1-indexed) |\n| `--uncheck-ac` | | Unmark AC |\n| `--plan` | | Set implementation plan |\n| `--notes` | | Replace notes |\n| `--append-notes` | | Add to notes |\n\n---\n\n## task view/list\n\n```bash\nknowns task <id> --plain\nknowns task list --plain\nknowns task list --status in-progress --plain\nknowns task list --tree --plain\n```\n\n---\n\n## doc create\n\n```bash\nknowns doc create <title> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--description` | `-d` | Description |\n| `--tags` | `-t` | Comma-separated tags |\n| `--folder` | `-f` | Folder path |\n\n---\n\n## doc edit\n\n```bash\nknowns doc edit <name> [options]\n```\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--content` | `-c` | Replace content |\n| `--append` | `-a` | Append content |\n| `--section` | | Target section (use with -c) |\n\n**In doc edit, `-a` = append content, NOT assignee!**\n\n---\n\n## doc view/list\n\n**ALWAYS use `--smart`** - auto-handles small/large docs:\n\n```bash\nknowns doc <path> --plain --smart\n```\n\nIf large, returns TOC. Then read section:\n```bash\nknowns doc <path> --plain --section 3\n```\n\n```bash\nknowns doc list --plain\nknowns doc list --tag api --plain\n```\n\n---\n\n## time\n\n```bash\nknowns time start <id> # REQUIRED when taking task\nknowns time stop # REQUIRED when completing\nknowns time status\nknowns time add <id> <duration> -n "Note"\n```\n\n---\n\n## search\n\n```bash\nknowns search "query" --plain\nknowns search "auth" --type task --plain\nknowns search "api" --type doc --plain\n```\n\n---\n\n## template\n\n```bash\nknowns template list\nknowns template info <name>\nknowns template run <name> --name "X" --dry-run\nknowns template create <name>\n```\n\n---\n\n## Multi-line Input\n\n```bash\nknowns task edit <id> --plan $\'1. Step\\n2. Step\\n3. Step\'\n```\n{{/if}}\n';
59411
59411
 
59412
59412
  // src/instructions/guidelines/unified/common-mistakes.md
59413
59413
  var common_mistakes_default = '# Common Mistakes\n\n{{#if cli}}\n## CRITICAL: The -a Flag\n\n| Command | `-a` Means | NOT This! |\n|---------|------------|-----------|\n| `task create/edit` | `--assignee` | ~~acceptance criteria~~ |\n| `doc edit` | `--append` | ~~assignee~~ |\n\n```bash\n# WRONG (sets assignee to garbage!)\nknowns task edit 35 -a "Criterion text"\n\n# CORRECT (use --ac)\nknowns task edit 35 --ac "Criterion text"\n```\n\n---\n{{/if}}\n\n## CRITICAL: Notes vs Append Notes\n\n**NEVER use `notes`/`--notes` for progress updates - it REPLACES all existing notes!**\n\n{{#if cli}}\n```bash\n# \u274C WRONG - Destroys audit trail!\nknowns task edit <id> --notes "Done: feature X"\n\n# \u2705 CORRECT - Preserves history\nknowns task edit <id> --append-notes "Done: feature X"\n```\n{{/if}}\n{{#if mcp}}\n```json\n// \u274C WRONG - Destroys audit trail!\nmcp__knowns__update_task({\n "taskId": "<id>",\n "notes": "Done: feature X"\n})\n\n// \u2705 CORRECT - Preserves history\nmcp__knowns__update_task({\n "taskId": "<id>",\n "appendNotes": "Done: feature X"\n})\n```\n{{/if}}\n\n| Field | Behavior |\n|-------|----------|\n{{#if cli}}\n| `--notes` | **REPLACES** all notes (use only for initial setup) |\n| `--append-notes` | **APPENDS** to existing notes (use for progress) |\n{{/if}}\n{{#if mcp}}\n| `notes` | **REPLACES** all notes (use only for initial setup) |\n| `appendNotes` | **APPENDS** to existing notes (use for progress) |\n{{/if}}\n\n---\n\n## Quick Reference\n\n| DON\'T | DO |\n|-------|-----|\n{{#if cli}}\n| Edit .md files directly | Use CLI commands |\n| `-a "criterion"` | `--ac "criterion"` |\n| `--parent task-48` | `--parent 48` (raw ID) |\n| `--plain` with create/edit | `--plain` only for view/list |\n| `--notes` for progress | `--append-notes` for progress |\n{{/if}}\n{{#if mcp}}\n| Edit .md files directly | Use MCP tools |\n| `notes` for progress | `appendNotes` for progress |\n{{/if}}\n| Check AC before work done | Check AC AFTER work done |\n| Code before plan approval | Wait for user approval |\n| Code before reading docs | Read docs FIRST |\n| Skip time tracking | Always start/stop timer |\n| Ignore refs | Follow ALL `@task-xxx`, `@doc/xxx`, `@template/xxx` refs |\n\n{{#if mcp}}\n---\n\n## MCP Task Operations\n\nAll task operations are available via MCP:\n\n| Operation | MCP Field |\n|-----------|-----------|\n| Add acceptance criteria | `addAc: ["criterion"]` |\n| Check AC | `checkAc: [1, 2]` (1-based) |\n| Uncheck AC | `uncheckAc: [1]` (1-based) |\n| Remove AC | `removeAc: [1]` (1-based) |\n| Set plan | `plan: "..."` |\n| Set notes | `notes: "..."` |\n| Append notes | `appendNotes: "..."` |\n| Change status | `status: "in-progress"` |\n| Assign | `assignee: "@me"` |\n{{/if}}\n\n---\n\n## Template Syntax Pitfalls\n\nWhen writing `.hbs` templates, **NEVER** create `$` followed by triple-brace - Handlebars interprets triple-brace as unescaped output:\n\n```\n// \u274C WRONG - Parse error!\nthis.logger.log(`Created: $` + `{` + `{` + `{camelCase entity}.id}`);\n\n// \u2705 CORRECT - Add space between ${ and double-brace, use ~ to trim whitespace\nthis.logger.log(`Created: ${ \\{{~camelCase entity~}}.id}`);\n```\n\n| DON\'T | DO |\n|-------|-----|\n| `$` + triple-brace | `${ \\{{~helper~}}}` (space + escaped) |\n\n**Rules:**\n- Add space between `${` and double-brace\n- Use `~` (tilde) to trim whitespace in output\n- Escape literal braces with backslash\n\n---\n\n## Error Recovery\n\n| Problem | Solution |\n|---------|----------|\n{{#if cli}}\n| Set assignee to AC text | `knowns task edit <id> -a @me` |\n| Forgot to stop timer | `knowns time add <id> <duration>` |\n| Checked AC too early | `knowns task edit <id> --uncheck-ac N` |\n| Task not found | `knowns task list --plain` |\n| Replaced notes by mistake | Cannot recover - notes are lost. Use `--append-notes` next time |\n{{/if}}\n{{#if mcp}}\n| Forgot to stop timer | `mcp__knowns__add_time` with duration |\n| Wrong status | `mcp__knowns__update_task` to fix |\n| Task not found | `mcp__knowns__list_tasks` to find ID |\n| Need to uncheck AC | `mcp__knowns__update_task` with `uncheckAc: [N]` |\n| Checked AC too early | `mcp__knowns__update_task` with `uncheckAc: [N]` |\n| Replaced notes by mistake | Cannot recover - notes are lost. Use `appendNotes` next time |\n{{/if}}\n';
@@ -59416,7 +59416,7 @@ var common_mistakes_default = '# Common Mistakes\n\n{{#if cli}}\n## CRITICAL: Th
59416
59416
  var context_optimization_default = '# Context Optimization\n\nOptimize your context usage to work more efficiently within token limits.\n\n---\n\n{{#if cli}}\n## Output Format\n\n```bash\n# Verbose output\nknowns task 42 --json\n\n# Compact output (always use --plain)\nknowns task 42 --plain\n```\n\n---\n{{/if}}\n\n## Search Before Read\n\n{{#if cli}}\n### CLI\n```bash\n# DON\'T: Read all docs hoping to find info\nknowns doc "doc1" --plain\nknowns doc "doc2" --plain\n\n# DO: Search first, then read only relevant docs\nknowns search "authentication" --type doc --plain\nknowns doc "security-patterns" --plain\n```\n{{/if}}\n{{#if mcp}}\n### MCP\n```json\n// DON\'T: Read all docs hoping to find info\nmcp__knowns__get_doc({ "path": "doc1" })\nmcp__knowns__get_doc({ "path": "doc2" })\n\n// DO: Search first, then read only relevant docs\nmcp__knowns__search_docs({ "query": "authentication" })\nmcp__knowns__get_doc({ "path": "security-patterns" })\n```\n{{/if}}\n\n---\n\n{{#if mcp}}\n## Use Filters\n\n```json\n// DON\'T: List all then filter manually\nmcp__knowns__list_tasks({})\n\n// DO: Use filters in the query\nmcp__knowns__list_tasks({\n "status": "in-progress",\n "assignee": "@me"\n})\n```\n\n---\n{{/if}}\n\n## Reading Documents\n\n{{#if cli}}\n### CLI\n**ALWAYS use `--smart`** - auto-handles both small and large docs:\n\n```bash\n# DON\'T: Read without --smart\nknowns doc readme --plain\n\n# DO: Always use --smart\nknowns doc readme --plain --smart\n# Small doc \u2192 full content\n# Large doc \u2192 stats + TOC\n\n# If large, read specific section:\nknowns doc readme --plain --section 3\n```\n{{/if}}\n{{#if mcp}}\n### MCP\n**ALWAYS use `smart: true`** - auto-handles both small and large docs:\n\n```json\n// DON\'T: Read without smart\nmcp__knowns__get_doc({ "path": "readme" })\n\n// DO: Always use smart\nmcp__knowns__get_doc({ "path": "readme", "smart": true })\n// Small doc \u2192 full content\n// Large doc \u2192 stats + TOC\n\n// If large, read specific section:\nmcp__knowns__get_doc({ "path": "readme", "section": "3" })\n```\n{{/if}}\n\n**Behavior:**\n- **\u22642000 tokens**: Returns full content automatically\n- **>2000 tokens**: Returns stats + TOC, then use section parameter\n\n---\n\n## Compact Notes\n\n```bash\n# DON\'T: Verbose notes\nknowns task edit 42 --append-notes "I have successfully completed the implementation..."\n\n# DO: Compact notes\nknowns task edit 42 --append-notes "Done: Auth middleware + JWT validation"\n```\n\n---\n\n## Avoid Redundant Operations\n\n| Don\'t | Do Instead |\n|-------|------------|\n| Re-read files already in context | Reference from memory |\n| List tasks/docs multiple times | List once, remember results |\n| Quote entire file contents | Summarize key points |\n\n---\n\n## Efficient Workflow\n\n| Phase | Context-Efficient Approach |\n|-------|---------------------------|\n| **Research** | Search \u2192 Read only matches |\n| **Planning** | Brief plan, not detailed prose |\n| **Coding** | Read only files being modified |\n| **Notes** | Bullet points, not paragraphs |\n| **Completion** | Summary, not full log |\n\n---\n\n## Quick Rules\n\n{{#if cli}}\n1. **Always `--plain`** - Never use `--json` unless needed\n2. **Always `--smart`** - Auto-handles doc size\n{{/if}}\n{{#if mcp}}\n1. **Always `smart: true`** - Auto-handles doc size\n{{/if}}\n3. **Search first** - Don\'t read all docs hoping to find info\n4. **Read selectively** - Only fetch what you need\n5. **Write concise** - Compact notes, not essays\n6. **Don\'t repeat** - Reference context already loaded\n';
59417
59417
 
59418
59418
  // src/instructions/guidelines/unified/core-rules.md
59419
- var core_rules_default = '# Core Rules\n\n> These rules are NON-NEGOTIABLE. Violating them leads to data corruption and lost work.\n\n---\n\n## The Golden Rule\n\n{{#if mcp}}\n{{#if cli}}\n**If you want to change ANYTHING in a task or doc, use MCP tools (preferred) or CLI commands (fallback). NEVER edit .md files directly.**\n{{else}}\n**If you want to change ANYTHING in a task or doc, use MCP tools. NEVER edit .md files directly.**\n{{/if}}\n{{else}}\n{{#if cli}}\n**If you want to change ANYTHING in a task or doc, use CLI commands. NEVER edit .md files directly.**\n{{/if}}\n{{/if}}\n\n{{#if cli}}\n---\n\n## CRITICAL: The -a Flag Confusion\n\nThe `-a` flag means DIFFERENT things in different commands:\n\n| Command | `-a` Means | NOT This! |\n|---------|------------|-----------|\n| `task create` | `--assignee` (assign user) | ~~acceptance criteria~~ |\n| `task edit` | `--assignee` (assign user) | ~~acceptance criteria~~ |\n| `doc edit` | `--append` (append content) | ~~assignee~~ |\n\n### Acceptance Criteria: Use --ac\n\n```bash\n# WRONG: -a is assignee, NOT acceptance criteria!\nknowns task edit 35 -a "- [ ] Criterion" # Sets assignee to garbage!\n\n# CORRECT: Use --ac for acceptance criteria\nknowns task edit 35 --ac "Criterion one"\nknowns task create "Title" --ac "Criterion one" --ac "Criterion two"\n```\n{{/if}}\n\n---\n\n## Quick Reference\n\n| Rule | Description |\n|------|-------------|\n{{#if mcp}}\n{{#if cli}}\n| **MCP Tools (preferred)** | Use MCP tools for ALL operations. Fallback to CLI if needed. NEVER edit .md files directly |\n{{else}}\n| **MCP Tools Only** | Use MCP tools for ALL operations. NEVER edit .md files directly |\n{{/if}}\n{{else}}\n{{#if cli}}\n| **CLI Only** | Use commands for ALL operations. NEVER edit .md files directly |\n{{/if}}\n{{/if}}\n| **Docs First** | Read project docs BEFORE planning or coding |\n| **Time Tracking** | Start timer when taking task, stop when done |\n| **Plan Approval** | Share plan with user, WAIT for approval before coding |\n| **Check AC After** | Only mark criteria done AFTER completing work |\n\n{{#if cli}}\n---\n\n## The --plain Flag\n\n**ONLY for view/list/search commands (NOT create/edit):**\n\n```bash\n# CORRECT\nknowns task <id> --plain\nknowns task list --plain\nknowns doc "path" --plain\nknowns search "query" --plain\n\n# WRONG (create/edit don\'t support --plain)\nknowns task create "Title" --plain # ERROR!\nknowns task edit <id> -s done --plain # ERROR!\n```\n{{/if}}\n\n---\n\n## Reference System\n\nTasks, docs, and templates can reference each other:\n\n| Type | Writing (Input) | Reading (Output) |\n|------|-----------------|------------------|\n| Task | `@task-<id>` | `@.knowns/tasks/task-<id>` |\n| Doc | `@doc/<path>` | `@.knowns/docs/<path>.md` |\n| Template | `@template/<name>` | `@.knowns/templates/<name>` |\n\n**Always follow refs recursively** to gather complete context before planning.\n\n---\n\n## Subtasks\n\n{{#if cli}}\n### CLI\n```bash\nknowns task create "Subtask title" --parent 48\n```\n\n**CRITICAL:** Use raw ID for `--parent`:\n```bash\n# CORRECT\nknowns task create "Title" --parent 48\n\n# WRONG\nknowns task create "Title" --parent task-48\n```\n{{/if}}\n{{#if mcp}}\n### MCP\n```json\nmcp__knowns__create_task({\n "title": "Subtask title",\n "parent": "parent-task-id"\n})\n```\n\n**CRITICAL:** Use raw ID (string) for all MCP tool calls.\n{{/if}}\n';
59419
+ var core_rules_default = '# Core Rules\n\n> These rules are NON-NEGOTIABLE. Violating them leads to data corruption and lost work.\n\n---\n\n## The Golden Rule\n\n{{#if mcp}}\n{{#if cli}}\n**If you want to change ANYTHING in a task or doc, use MCP tools (preferred) or CLI commands (fallback). NEVER edit .md files directly.**\n{{else}}\n**If you want to change ANYTHING in a task or doc, use MCP tools. NEVER edit .md files directly.**\n{{/if}}\n{{else}}\n{{#if cli}}\n**If you want to change ANYTHING in a task or doc, use CLI commands. NEVER edit .md files directly.**\n{{/if}}\n{{/if}}\n\n{{#if mcp}}\n---\n\n## Session Initialization (MCP)\n\n**CRITICAL: At the START of every session, run these tools to initialize the project:**\n\n```json\n// Step 1: Detect available projects\nmcp__knowns__detect_projects({})\n\n// Step 2: Set the project you want to work with\nmcp__knowns__set_project({ "projectRoot": "/path/to/project" })\n\n// Step 3: Verify project is set correctly\nmcp__knowns__get_current_project({})\n```\n\n**Why?** The MCP server may not know which project you\'re working in. These tools:\n- `detect_projects` - Scans common workspace directories for Knowns projects\n- `set_project` - Sets the active project for all subsequent operations\n- `get_current_project` - Verifies the current project path\n\n**If you skip this step**, other tools like `list_tasks`, `get_doc`, etc. may fail or work on the wrong project.\n{{/if}}\n\n{{#if cli}}\n---\n\n## CRITICAL: The -a Flag Confusion\n\nThe `-a` flag means DIFFERENT things in different commands:\n\n| Command | `-a` Means | NOT This! |\n|---------|------------|-----------|\n| `task create` | `--assignee` (assign user) | ~~acceptance criteria~~ |\n| `task edit` | `--assignee` (assign user) | ~~acceptance criteria~~ |\n| `doc edit` | `--append` (append content) | ~~assignee~~ |\n\n### Acceptance Criteria: Use --ac\n\n```bash\n# WRONG: -a is assignee, NOT acceptance criteria!\nknowns task edit 35 -a "- [ ] Criterion" # Sets assignee to garbage!\n\n# CORRECT: Use --ac for acceptance criteria\nknowns task edit 35 --ac "Criterion one"\nknowns task create "Title" --ac "Criterion one" --ac "Criterion two"\n```\n{{/if}}\n\n---\n\n## Quick Reference\n\n| Rule | Description |\n|------|-------------|\n{{#if mcp}}\n{{#if cli}}\n| **MCP Tools (preferred)** | Use MCP tools for ALL operations. Fallback to CLI if needed. NEVER edit .md files directly |\n{{else}}\n| **MCP Tools Only** | Use MCP tools for ALL operations. NEVER edit .md files directly |\n{{/if}}\n{{else}}\n{{#if cli}}\n| **CLI Only** | Use commands for ALL operations. NEVER edit .md files directly |\n{{/if}}\n{{/if}}\n| **Docs First** | Read project docs BEFORE planning or coding |\n| **Time Tracking** | Start timer when taking task, stop when done |\n| **Plan Approval** | Share plan with user, WAIT for approval before coding |\n| **Check AC After** | Only mark criteria done AFTER completing work |\n\n{{#if cli}}\n---\n\n## The --plain Flag\n\n**ONLY for view/list/search commands (NOT create/edit):**\n\n```bash\n# CORRECT\nknowns task <id> --plain\nknowns task list --plain\nknowns doc "path" --plain\nknowns search "query" --plain\n\n# WRONG (create/edit don\'t support --plain)\nknowns task create "Title" --plain # ERROR!\nknowns task edit <id> -s done --plain # ERROR!\n```\n{{/if}}\n\n---\n\n## Reference System\n\nTasks, docs, and templates can reference each other:\n\n| Type | Writing (Input) | Reading (Output) |\n|------|-----------------|------------------|\n| Task | `@task-<id>` | `@.knowns/tasks/task-<id>` |\n| Doc | `@doc/<path>` | `@.knowns/docs/<path>.md` |\n| Template | `@template/<name>` | `@.knowns/templates/<name>` |\n\n**Always follow refs recursively** to gather complete context before planning.\n\n---\n\n## Subtasks\n\n{{#if cli}}\n### CLI\n```bash\nknowns task create "Subtask title" --parent 48\n```\n\n**CRITICAL:** Use raw ID for `--parent`:\n```bash\n# CORRECT\nknowns task create "Title" --parent 48\n\n# WRONG\nknowns task create "Title" --parent task-48\n```\n{{/if}}\n{{#if mcp}}\n### MCP\n```json\nmcp__knowns__create_task({\n "title": "Subtask title",\n "parent": "parent-task-id"\n})\n```\n\n**CRITICAL:** Use raw ID (string) for all MCP tool calls.\n{{/if}}\n';
59420
59420
 
59421
59421
  // src/instructions/guidelines/unified/workflow-completion.md
59422
59422
  var workflow_completion_default = '# Task Completion\n\n## Definition of Done\n\nA task is **Done** when ALL of these are complete:\n\n{{#if cli}}\n### CLI\n| Requirement | Command |\n|-------------|---------|\n| All AC checked | `knowns task edit <id> --check-ac N` |\n| Notes added | `knowns task edit <id> --notes "Summary"` |\n| Timer stopped | `knowns time stop` |\n| Status = done | `knowns task edit <id> -s done` |\n| Tests pass | Run test suite |\n{{/if}}\n{{#if mcp}}\n### MCP\n| Requirement | How |\n|-------------|-----|\n| All AC checked | `mcp__knowns__update_task` with `checkAc` |\n| Notes added | `mcp__knowns__update_task` with `notes` |\n| Timer stopped | `mcp__knowns__stop_time` |\n| Status = done | `mcp__knowns__update_task` with `status: "done"` |\n| Tests pass | Run test suite |\n{{/if}}\n\n---\n\n## Completion Steps\n\n{{#if cli}}\n### CLI\n```bash\n# 1. Verify all AC are checked\nknowns task <id> --plain\n\n# 2. Add implementation notes\nknowns task edit <id> --notes $\'## Summary\nWhat was done and key decisions.\'\n\n# 3. Stop timer (REQUIRED!)\nknowns time stop\n\n# 4. Mark done\nknowns task edit <id> -s done\n```\n{{/if}}\n{{#if mcp}}\n### MCP\n```json\n// 1. Verify all AC are checked\nmcp__knowns__get_task({ "taskId": "<id>" })\n\n// 2. Add implementation notes\nmcp__knowns__update_task({\n "taskId": "<id>",\n "notes": "## Summary\\nWhat was done and key decisions."\n})\n\n// 3. Stop timer (REQUIRED!)\nmcp__knowns__stop_time({ "taskId": "<id>" })\n\n// 4. Mark done\nmcp__knowns__update_task({\n "taskId": "<id>",\n "status": "done"\n})\n```\n{{/if}}\n\n---\n\n## Post-Completion Changes\n\nIf user requests changes after task is done:\n\n{{#if cli}}\n### CLI\n```bash\nknowns task edit <id> -s in-progress # Reopen\nknowns time start <id> # Restart timer\nknowns task edit <id> --ac "Fix: description"\nknowns task edit <id> --append-notes "Reopened: reason"\n```\n{{/if}}\n{{#if mcp}}\n### MCP\n```json\n// 1. Reopen task\nmcp__knowns__update_task({\n "taskId": "<id>",\n "status": "in-progress"\n})\n\n// 2. Restart timer\nmcp__knowns__start_time({ "taskId": "<id>" })\n\n// 3. Add AC for the fix\nmcp__knowns__update_task({\n "taskId": "<id>",\n "addAc": ["Fix: description"],\n "appendNotes": "Reopened: reason"\n})\n```\n{{/if}}\n\nThen follow completion steps again.\n\n---\n\n## Checklist\n\n{{#if cli}}\n### CLI\n- [ ] All AC checked (`--check-ac`)\n- [ ] Notes added (`--notes`)\n- [ ] Timer stopped (`time stop`)\n- [ ] Tests pass\n- [ ] Status = done (`-s done`)\n{{/if}}\n{{#if mcp}}\n### MCP\n- [ ] All AC checked (`checkAc`)\n- [ ] Notes added (`notes`)\n- [ ] Timer stopped (`mcp__knowns__stop_time`)\n- [ ] Tests pass\n- [ ] Status = done (`mcp__knowns__update_task`)\n{{/if}}\n';
@@ -59566,10 +59566,10 @@ function getIDENames() {
59566
59566
  import { existsSync as existsSync3 } from "node:fs";
59567
59567
  import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
59568
59568
  import { dirname as dirname2, join as join5 } from "node:path";
59569
- var import_prompts = __toESM(require_prompts3(), 1);
59570
59569
  var PROJECT_ROOT = process.cwd();
59571
59570
  var INSTRUCTION_FILES = [
59572
59571
  { path: "CLAUDE.md", name: "Claude Code", selected: true },
59572
+ { path: "GEMINI.md", name: "Antigravity (Gemini)", selected: true },
59573
59573
  { path: "AGENTS.md", name: "Agent SDK", selected: true },
59574
59574
  {
59575
59575
  path: ".github/copilot-instructions.md",
@@ -59616,169 +59616,6 @@ ${guidelines}
59616
59616
  await writeFile3(fullPath, newContent, "utf-8");
59617
59617
  return { success: true, action: "updated" };
59618
59618
  }
59619
- var agentsCommand = new Command("agents").description("Manage agent instruction files (CLAUDE.md, GEMINI.md, etc.)").enablePositionalOptions().passThroughOptions().option("--update-instructions", "Update agent instruction files (non-interactive)").option("--type <type>", "Guidelines type: cli or mcp", "cli").option("--files <files>", "Comma-separated list of files to update").action(
59620
- async (options2) => {
59621
- try {
59622
- if (options2.updateInstructions) {
59623
- const type = options2.type === "mcp" ? "mcp" : "cli";
59624
- const guidelines2 = getGuidelines(type);
59625
- let filesToUpdate = INSTRUCTION_FILES;
59626
- if (options2.files) {
59627
- const requestedFiles = options2.files.split(",").map((f) => f.trim());
59628
- filesToUpdate = INSTRUCTION_FILES.filter(
59629
- (f) => requestedFiles.includes(f.path) || requestedFiles.includes(f.name)
59630
- );
59631
- }
59632
- const label2 = `${type.toUpperCase()}`;
59633
- console.log(source_default.bold(`
59634
- Updating agent instruction files (${label2})...
59635
- `));
59636
- await updateFiles(filesToUpdate, guidelines2);
59637
- return;
59638
- }
59639
- console.log(source_default.bold("\n\u{1F916} Agent Instructions Manager\n"));
59640
- const typeResponse = await (0, import_prompts.default)({
59641
- type: "select",
59642
- name: "type",
59643
- message: "Select guidelines type:",
59644
- choices: [
59645
- {
59646
- title: "CLI",
59647
- value: "cli",
59648
- description: "CLI commands (knowns task edit, knowns doc view, etc.)"
59649
- },
59650
- {
59651
- title: "MCP",
59652
- value: "mcp",
59653
- description: "MCP tools (mcp__knowns__update_task, etc.)"
59654
- }
59655
- ],
59656
- initial: 0
59657
- });
59658
- if (!typeResponse.type) {
59659
- console.log(source_default.yellow("\n\u26A0\uFE0F Cancelled"));
59660
- return;
59661
- }
59662
- const filesResponse = await (0, import_prompts.default)({
59663
- type: "multiselect",
59664
- name: "files",
59665
- message: "Select agent files to update:",
59666
- choices: INSTRUCTION_FILES.map((f) => ({
59667
- title: `${f.name} (${f.path})`,
59668
- value: f,
59669
- selected: f.selected
59670
- })),
59671
- hint: "- Space to select. Return to submit"
59672
- });
59673
- if (!filesResponse.files || filesResponse.files.length === 0) {
59674
- console.log(source_default.yellow("\n\u26A0\uFE0F No files selected"));
59675
- return;
59676
- }
59677
- const label = typeResponse.type.toUpperCase();
59678
- const confirmResponse = await (0, import_prompts.default)({
59679
- type: "confirm",
59680
- name: "confirm",
59681
- message: `Update ${filesResponse.files.length} file(s) with ${label} guidelines?`,
59682
- initial: true
59683
- });
59684
- if (!confirmResponse.confirm) {
59685
- console.log(source_default.yellow("\n\u26A0\uFE0F Cancelled"));
59686
- return;
59687
- }
59688
- const guidelines = getGuidelines(typeResponse.type);
59689
- console.log(source_default.bold(`
59690
- Updating files with ${label} guidelines...
59691
- `));
59692
- await updateFiles(filesResponse.files, guidelines);
59693
- } catch (error48) {
59694
- console.error(source_default.red("Error:"), error48 instanceof Error ? error48.message : String(error48));
59695
- process.exit(1);
59696
- }
59697
- }
59698
- );
59699
- async function updateFiles(files, guidelines) {
59700
- let createdCount = 0;
59701
- let appendedCount = 0;
59702
- let updatedCount = 0;
59703
- let errorCount = 0;
59704
- for (const file3 of files) {
59705
- try {
59706
- const result = await updateInstructionFile(file3.path, guidelines);
59707
- if (result.success) {
59708
- if (result.action === "created") {
59709
- createdCount++;
59710
- console.log(source_default.green(`\u2713 Created ${file3.name}: ${file3.path}`));
59711
- } else if (result.action === "appended") {
59712
- appendedCount++;
59713
- console.log(source_default.cyan(`\u2713 Appended ${file3.name}: ${file3.path}`));
59714
- } else {
59715
- updatedCount++;
59716
- console.log(source_default.green(`\u2713 Updated ${file3.name}: ${file3.path}`));
59717
- }
59718
- }
59719
- } catch (error48) {
59720
- errorCount++;
59721
- console.error(
59722
- source_default.red(`\u2717 Failed ${file3.name}: ${file3.path}`),
59723
- error48 instanceof Error ? error48.message : String(error48)
59724
- );
59725
- }
59726
- }
59727
- console.log(source_default.bold("\nSummary:"));
59728
- if (createdCount > 0) {
59729
- console.log(source_default.green(` Created: ${createdCount}`));
59730
- }
59731
- if (appendedCount > 0) {
59732
- console.log(source_default.cyan(` Appended: ${appendedCount}`));
59733
- }
59734
- if (updatedCount > 0) {
59735
- console.log(source_default.green(` Updated: ${updatedCount}`));
59736
- }
59737
- if (errorCount > 0) {
59738
- console.log(source_default.red(` Failed: ${errorCount}`));
59739
- }
59740
- console.log();
59741
- }
59742
- var guidelineCommand = new Command("guideline").description("Output guidelines for AI agents (use this at session start)").option("--cli", "Show CLI-specific guidelines (legacy)").option("--mcp", "Show MCP-specific guidelines (legacy)").option("--full", "Show full guidelines (all sections)").option("--compact", "Show compact guidelines (core + mistakes only)").option("--stage <stage>", "Show guidelines for specific stage: creation, execution, completion").option("--core", "Show core rules only").option("--commands", "Show commands reference only").option("--mistakes", "Show common mistakes only").action(
59743
- async (options2) => {
59744
- try {
59745
- if (options2.cli || options2.mcp) {
59746
- console.log(Guidelines.getFull());
59747
- return;
59748
- }
59749
- if (options2.core) {
59750
- console.log(Guidelines.core);
59751
- return;
59752
- }
59753
- if (options2.commands) {
59754
- console.log(Guidelines.commands);
59755
- return;
59756
- }
59757
- if (options2.mistakes) {
59758
- console.log(Guidelines.mistakes);
59759
- return;
59760
- }
59761
- if (options2.compact) {
59762
- console.log(Guidelines.getCompact());
59763
- return;
59764
- }
59765
- if (options2.stage) {
59766
- const stage = options2.stage;
59767
- if (!["creation", "execution", "completion"].includes(stage)) {
59768
- console.error("Error: Invalid stage. Use: creation, execution, or completion");
59769
- process.exit(1);
59770
- }
59771
- console.log(Guidelines.getForStage(stage));
59772
- return;
59773
- }
59774
- console.log(Guidelines.getFull());
59775
- } catch (error48) {
59776
- console.error("Error:", error48 instanceof Error ? error48.message : String(error48));
59777
- process.exit(1);
59778
- }
59779
- }
59780
- );
59781
- agentsCommand.addCommand(guidelineCommand);
59782
59619
 
59783
59620
  // src/commands/init.ts
59784
59621
  function mapPlatformId(initId) {
@@ -59871,6 +59708,46 @@ async function createMcpJsonFile(projectRoot, force = false) {
59871
59708
  console.log(source_default.green("\u2713 Created .mcp.json for Claude Code MCP auto-discovery"));
59872
59709
  }
59873
59710
  }
59711
+ async function createAntigravityMcpConfig(force = false) {
59712
+ const { mkdirSync: mkdirSync2, writeFileSync: writeFileSync4, readFileSync: readFileSync5 } = await import("node:fs");
59713
+ const { homedir: homedir4 } = await import("node:os");
59714
+ const homeDir = homedir4();
59715
+ const antigravityDir = join6(homeDir, ".gemini", "antigravity");
59716
+ const mcpConfigPath = join6(antigravityDir, "mcp_config.json");
59717
+ const mcpConfig = {
59718
+ mcpServers: {
59719
+ knowns: {
59720
+ command: "npx",
59721
+ args: ["-y", "knowns", "mcp"]
59722
+ }
59723
+ }
59724
+ };
59725
+ if (!existsSync4(antigravityDir)) {
59726
+ mkdirSync2(antigravityDir, { recursive: true });
59727
+ }
59728
+ if (existsSync4(mcpConfigPath)) {
59729
+ try {
59730
+ const existing = JSON.parse(readFileSync5(mcpConfigPath, "utf-8"));
59731
+ if (existing?.mcpServers?.knowns && !force) {
59732
+ console.log(source_default.gray(" Antigravity MCP already has knowns configuration"));
59733
+ return;
59734
+ }
59735
+ existing.mcpServers = {
59736
+ ...existing.mcpServers,
59737
+ ...mcpConfig.mcpServers
59738
+ };
59739
+ writeFileSync4(mcpConfigPath, JSON.stringify(existing, null, " "), "utf-8");
59740
+ const action = force ? "Updated" : "Added";
59741
+ console.log(source_default.green(`\u2713 ${action} knowns in Antigravity MCP config`));
59742
+ } catch {
59743
+ writeFileSync4(mcpConfigPath, JSON.stringify(mcpConfig, null, " "), "utf-8");
59744
+ console.log(source_default.green("\u2713 Created Antigravity MCP config (replaced invalid file)"));
59745
+ }
59746
+ } else {
59747
+ writeFileSync4(mcpConfigPath, JSON.stringify(mcpConfig, null, " "), "utf-8");
59748
+ console.log(source_default.green("\u2713 Created Antigravity MCP config (~/.gemini/antigravity/mcp_config.json)"));
59749
+ }
59750
+ }
59874
59751
  async function updateGitignore(projectRoot, mode) {
59875
59752
  const { appendFileSync, readFileSync: readFileSync5, writeFileSync: writeFileSync4 } = await import("node:fs");
59876
59753
  const gitignorePath = join6(projectRoot, ".gitignore");
@@ -59957,7 +59834,7 @@ async function runWizard() {
59957
59834
  console.log(source_default.bold.cyan("\u{1F680} Knowns Project Setup Wizard"));
59958
59835
  console.log(source_default.gray(" Configure your project settings"));
59959
59836
  console.log();
59960
- const response = await (0, import_prompts2.default)(
59837
+ const response = await (0, import_prompts.default)(
59961
59838
  [
59962
59839
  {
59963
59840
  type: "text",
@@ -60059,8 +59936,8 @@ var initCommand = new Command("init").description("Initialize .knowns/ folder in
60059
59936
  if (config2.gitTrackingMode === "git-ignored" || config2.gitTrackingMode === "none") {
60060
59937
  await updateGitignore(projectRoot, config2.gitTrackingMode);
60061
59938
  }
60062
- const fileStore2 = new FileStore(projectRoot);
60063
- const project = await fileStore2.initProject(config2.name, {
59939
+ const fileStore = new FileStore(projectRoot);
59940
+ const project = await fileStore.initProject(config2.name, {
60064
59941
  defaultPriority: config2.defaultPriority,
60065
59942
  defaultLabels: config2.defaultLabels,
60066
59943
  timeFormat: config2.timeFormat,
@@ -60097,16 +59974,36 @@ var initCommand = new Command("init").description("Initialize .knowns/ folder in
60097
59974
  }
60098
59975
  }
60099
59976
  }
60100
- await createMcpJsonFile(projectRoot, options2.force);
59977
+ const hasClaudeCode = config2.platforms.includes("claude-code");
59978
+ const hasAntigravity = config2.platforms.includes("antigravity");
59979
+ if (hasClaudeCode) {
59980
+ await createMcpJsonFile(projectRoot, options2.force);
59981
+ }
59982
+ if (hasAntigravity) {
59983
+ await createAntigravityMcpConfig(options2.force);
59984
+ }
60101
59985
  const guidelines = UnifiedGuidelines.getFull(true);
60102
- try {
60103
- const result = await updateInstructionFile("CLAUDE.md", guidelines);
60104
- if (result.success) {
60105
- const action = result.action === "created" ? "Created" : result.action === "appended" ? "Appended" : "Updated";
60106
- console.log(source_default.green(`\u2713 ${action}: CLAUDE.md (unified CLI + MCP guidelines)`));
59986
+ if (hasClaudeCode) {
59987
+ try {
59988
+ const result = await updateInstructionFile("CLAUDE.md", guidelines);
59989
+ if (result.success) {
59990
+ const action = result.action === "created" ? "Created" : result.action === "appended" ? "Appended" : "Updated";
59991
+ console.log(source_default.green(`\u2713 ${action}: CLAUDE.md (unified CLI + MCP guidelines)`));
59992
+ }
59993
+ } catch {
59994
+ console.log(source_default.yellow("\u26A0\uFE0F Skipped: CLAUDE.md"));
59995
+ }
59996
+ }
59997
+ if (hasAntigravity) {
59998
+ try {
59999
+ const result = await updateInstructionFile("GEMINI.md", guidelines);
60000
+ if (result.success) {
60001
+ const action = result.action === "created" ? "Created" : result.action === "appended" ? "Appended" : "Updated";
60002
+ console.log(source_default.green(`\u2713 ${action}: GEMINI.md (unified CLI + MCP guidelines)`));
60003
+ }
60004
+ } catch {
60005
+ console.log(source_default.yellow("\u26A0\uFE0F Skipped: GEMINI.md"));
60107
60006
  }
60108
- } catch {
60109
- console.log(source_default.yellow("\u26A0\uFE0F Skipped: CLAUDE.md"));
60110
60007
  }
60111
60008
  }
60112
60009
  for (const platform of selectedPlatforms) {
@@ -60713,7 +60610,7 @@ function getFileStore() {
60713
60610
  }
60714
60611
  return new FileStore(projectRoot);
60715
60612
  }
60716
- async function wouldCreateCycle(taskId, newParentId, fileStore2) {
60613
+ async function wouldCreateCycle(taskId, newParentId, fileStore) {
60717
60614
  if (taskId === newParentId) {
60718
60615
  return true;
60719
60616
  }
@@ -60722,7 +60619,7 @@ async function wouldCreateCycle(taskId, newParentId, fileStore2) {
60722
60619
  if (current === taskId) {
60723
60620
  return true;
60724
60621
  }
60725
- const parent = await fileStore2.getTask(current);
60622
+ const parent = await fileStore.getTask(current);
60726
60623
  current = parent?.parent || "";
60727
60624
  }
60728
60625
  return false;
@@ -60737,7 +60634,7 @@ function collectNumbers(value, previous) {
60737
60634
  }
60738
60635
  return previous.concat([num]);
60739
60636
  }
60740
- async function formatTask(task, fileStore2, plain = false) {
60637
+ async function formatTask(task, fileStore, plain = false) {
60741
60638
  if (plain) {
60742
60639
  const border = "-".repeat(50);
60743
60640
  const titleBorder = "=".repeat(50);
@@ -60858,7 +60755,7 @@ async function formatTask(task, fileStore2, plain = false) {
60858
60755
  if (task.subtasks.length > 0) {
60859
60756
  output.push(source_default.bold("Subtasks:"));
60860
60757
  for (const subtaskId of task.subtasks) {
60861
- const subtask = await fileStore2.getTask(subtaskId);
60758
+ const subtask = await fileStore.getTask(subtaskId);
60862
60759
  if (subtask) {
60863
60760
  const statusIcon = getStatusIcon(subtask.status);
60864
60761
  const statusColor2 = getStatusColor(subtask.status);
@@ -60940,18 +60837,18 @@ function getStatusIcon(status) {
60940
60837
  return "\u25CB";
60941
60838
  }
60942
60839
  }
60943
- async function getSubtaskProgress(task, fileStore2) {
60840
+ async function getSubtaskProgress(task, fileStore) {
60944
60841
  if (task.subtasks.length === 0) return "";
60945
60842
  let completed = 0;
60946
60843
  for (const subtaskId of task.subtasks) {
60947
- const subtask = await fileStore2.getTask(subtaskId);
60844
+ const subtask = await fileStore.getTask(subtaskId);
60948
60845
  if (subtask && subtask.status === "done") {
60949
60846
  completed++;
60950
60847
  }
60951
60848
  }
60952
60849
  return ` (${completed}/${task.subtasks.length})`;
60953
60850
  }
60954
- async function formatTaskTree(tasks, fileStore2, plain = false) {
60851
+ async function formatTaskTree(tasks, fileStore, plain = false) {
60955
60852
  const topLevelTasks = tasks.filter((t) => !t.parent);
60956
60853
  if (topLevelTasks.length === 0) {
60957
60854
  return plain ? "No tasks found" : source_default.gray("No tasks found");
@@ -60966,15 +60863,15 @@ async function formatTaskTree(tasks, fileStore2, plain = false) {
60966
60863
  }
60967
60864
  for (let i = 0; i < topLevelTasks.length; i++) {
60968
60865
  const isLast = i === topLevelTasks.length - 1;
60969
- await formatTaskNode(topLevelTasks[i], fileStore2, "", isLast, output, plain);
60866
+ await formatTaskNode(topLevelTasks[i], fileStore, "", isLast, output, plain);
60970
60867
  }
60971
60868
  return output.join("\n");
60972
60869
  }
60973
- async function formatTaskNode(task, fileStore2, prefix, isLast, output, plain, depth = 0) {
60870
+ async function formatTaskNode(task, fileStore, prefix, isLast, output, plain, depth = 0) {
60974
60871
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
60975
60872
  const extension = isLast ? " " : "\u2502 ";
60976
60873
  const statusIcon = getStatusIcon(task.status);
60977
- const progress = await getSubtaskProgress(task, fileStore2);
60874
+ const progress = await getSubtaskProgress(task, fileStore);
60978
60875
  if (plain) {
60979
60876
  const indent = depth > 0 ? `${" ".repeat(depth)}> ` : "";
60980
60877
  const statusDisplay = task.status.toUpperCase().replace("-", "_");
@@ -60988,15 +60885,15 @@ async function formatTaskNode(task, fileStore2, prefix, isLast, output, plain, d
60988
60885
  if (task.subtasks.length > 0) {
60989
60886
  for (let i = 0; i < task.subtasks.length; i++) {
60990
60887
  const subtaskId = task.subtasks[i];
60991
- const subtask = await fileStore2.getTask(subtaskId);
60888
+ const subtask = await fileStore.getTask(subtaskId);
60992
60889
  if (subtask) {
60993
60890
  const isLastChild = i === task.subtasks.length - 1;
60994
- await formatTaskNode(subtask, fileStore2, prefix + extension, isLastChild, output, plain, depth + 1);
60891
+ await formatTaskNode(subtask, fileStore, prefix + extension, isLastChild, output, plain, depth + 1);
60995
60892
  }
60996
60893
  }
60997
60894
  }
60998
60895
  }
60999
- async function formatTaskChildren(task, fileStore2, plain = false) {
60896
+ async function formatTaskChildren(task, fileStore, plain = false) {
61000
60897
  const output = [];
61001
60898
  if (plain) {
61002
60899
  output.push(`Children of Task #${task.id}: ${task.title}`);
@@ -61009,7 +60906,7 @@ async function formatTaskChildren(task, fileStore2, plain = false) {
61009
60906
  let completed = 0;
61010
60907
  const total = task.subtasks.length;
61011
60908
  for (const subtaskId of task.subtasks) {
61012
- const subtask = await fileStore2.getTask(subtaskId);
60909
+ const subtask = await fileStore.getTask(subtaskId);
61013
60910
  if (subtask) {
61014
60911
  if (subtask.status === "done") completed++;
61015
60912
  const statusDisplay = subtask.status.toUpperCase().replace("-", "_");
@@ -61028,7 +60925,7 @@ async function formatTaskChildren(task, fileStore2, plain = false) {
61028
60925
  }
61029
60926
  let completed = 0;
61030
60927
  for (const subtaskId of task.subtasks) {
61031
- const subtask = await fileStore2.getTask(subtaskId);
60928
+ const subtask = await fileStore.getTask(subtaskId);
61032
60929
  if (subtask) {
61033
60930
  if (subtask.status === "done") completed++;
61034
60931
  const statusIcon = getStatusIcon(subtask.status);
@@ -61110,8 +61007,8 @@ function formatTaskList(tasks, plain = false) {
61110
61007
  var createCommand2 = new Command("create").description("Create a new task").argument("<title>", "Task title").option("-d, --description <text>", "Task description").option("--ac <criterion>", "Acceptance criterion (can be used multiple times)", collect, []).option("-l, --labels <labels>", "Comma-separated labels").option("-a, --assignee <name>", "Assignee (@username)").option("--priority <level>", "Priority: low, medium, high", "medium").option("-s, --status <status>", "Status", "todo").option("--parent <id>", "Parent task ID for subtasks").action(
61111
61008
  async (title, options2) => {
61112
61009
  try {
61113
- const fileStore2 = getFileStore();
61114
- const project = await fileStore2.getProject();
61010
+ const fileStore = getFileStore();
61011
+ const project = await fileStore.getProject();
61115
61012
  const allowedStatuses = project?.settings.statuses || DEFAULT_STATUSES;
61116
61013
  if (!isValidTaskStatus(options2.status, allowedStatuses)) {
61117
61014
  console.error(source_default.red(`\u2717 Invalid status: ${options2.status}`));
@@ -61128,7 +61025,7 @@ var createCommand2 = new Command("create").description("Create a new task").argu
61128
61025
  text,
61129
61026
  completed: false
61130
61027
  }));
61131
- const task = await fileStore2.createTask({
61028
+ const task = await fileStore.createTask({
61132
61029
  title,
61133
61030
  description: options2.description ? normalizeRefs(options2.description) : void 0,
61134
61031
  status: options2.status,
@@ -61158,8 +61055,8 @@ var createCommand2 = new Command("create").description("Create a new task").argu
61158
61055
  var listCommand = new Command("list").description("List all tasks").option("--status <status>", "Filter by status").option("--assignee <name>", "Filter by assignee").option("-l, --labels <labels>", "Filter by labels (comma-separated)").option("--priority <level>", "Filter by priority").option("--tree", "Display tasks as tree hierarchy").option("--plain", "Plain text output for AI").action(
61159
61056
  async (options2) => {
61160
61057
  try {
61161
- const fileStore2 = getFileStore();
61162
- let tasks = await fileStore2.getAllTasks();
61058
+ const fileStore = getFileStore();
61059
+ let tasks = await fileStore.getAllTasks();
61163
61060
  if (options2.status) {
61164
61061
  tasks = tasks.filter((t) => t.status === options2.status);
61165
61062
  }
@@ -61174,7 +61071,7 @@ var listCommand = new Command("list").description("List all tasks").option("--st
61174
61071
  tasks = tasks.filter((t) => filterLabels.some((label) => t.labels.includes(label)));
61175
61072
  }
61176
61073
  if (options2.tree) {
61177
- console.log(await formatTaskTree(tasks, fileStore2, options2.plain));
61074
+ console.log(await formatTaskTree(tasks, fileStore, options2.plain));
61178
61075
  } else {
61179
61076
  console.log(formatTaskList(tasks, options2.plain));
61180
61077
  }
@@ -61190,17 +61087,17 @@ var listCommand = new Command("list").description("List all tasks").option("--st
61190
61087
  var viewCommand = new Command("view").description("View task details").argument("<id>", "Task ID").option("--plain", "Plain text output for AI").option("--children", "Show detailed list of child tasks").action(async (rawId, options2) => {
61191
61088
  try {
61192
61089
  const id = normalizeTaskId(rawId);
61193
- const fileStore2 = getFileStore();
61194
- const task = await fileStore2.getTask(id);
61090
+ const fileStore = getFileStore();
61091
+ const task = await fileStore.getTask(id);
61195
61092
  if (!task) {
61196
61093
  console.error(source_default.red(`\u2717 Task ${id} not found`));
61197
61094
  process.exit(1);
61198
61095
  }
61199
61096
  if (options2.children) {
61200
- console.log(await formatTaskChildren(task, fileStore2, options2.plain));
61097
+ console.log(await formatTaskChildren(task, fileStore, options2.plain));
61201
61098
  return;
61202
61099
  }
61203
- console.log(await formatTask(task, fileStore2, options2.plain));
61100
+ console.log(await formatTask(task, fileStore, options2.plain));
61204
61101
  } catch (error48) {
61205
61102
  console.error(source_default.red("\u2717 Failed to view task"));
61206
61103
  if (error48 instanceof Error) {
@@ -61228,13 +61125,13 @@ var editCommand = new Command("edit").description("Edit task properties").argume
61228
61125
  async (rawId, options2) => {
61229
61126
  try {
61230
61127
  const id = normalizeTaskId(rawId);
61231
- const fileStore2 = getFileStore();
61232
- const task = await fileStore2.getTask(id);
61128
+ const fileStore = getFileStore();
61129
+ const task = await fileStore.getTask(id);
61233
61130
  if (!task) {
61234
61131
  console.error(source_default.red(`\u2717 Task ${id} not found`));
61235
61132
  process.exit(1);
61236
61133
  }
61237
- const project = await fileStore2.getProject();
61134
+ const project = await fileStore.getProject();
61238
61135
  const allowedStatuses = project?.settings.statuses || DEFAULT_STATUSES;
61239
61136
  const updates = {};
61240
61137
  if (options2.title) {
@@ -61269,12 +61166,12 @@ var editCommand = new Command("edit").description("Edit task properties").argume
61269
61166
  if (options2.parent.toLowerCase() === "none") {
61270
61167
  updates.parent = void 0;
61271
61168
  } else {
61272
- const newParent = await fileStore2.getTask(options2.parent);
61169
+ const newParent = await fileStore.getTask(options2.parent);
61273
61170
  if (!newParent) {
61274
61171
  console.error(source_default.red(`\u2717 Parent task ${options2.parent} not found`));
61275
61172
  process.exit(1);
61276
61173
  }
61277
- if (await wouldCreateCycle(id, options2.parent, fileStore2)) {
61174
+ if (await wouldCreateCycle(id, options2.parent, fileStore)) {
61278
61175
  console.error(source_default.red("\u2717 Cannot set parent: would create circular dependency"));
61279
61176
  console.error(source_default.gray(" A task cannot be its own ancestor or descendant"));
61280
61177
  process.exit(1);
@@ -61328,7 +61225,7 @@ var editCommand = new Command("edit").description("Edit task properties").argume
61328
61225
  const separator = existingNotes ? "\n\n" : "";
61329
61226
  updates.implementationNotes = existingNotes + separator + normalizeRefs(options2.appendNotes);
61330
61227
  }
61331
- await fileStore2.updateTask(id, updates);
61228
+ await fileStore.updateTask(id, updates);
61332
61229
  await notifyTaskUpdate(id);
61333
61230
  console.log(source_default.green(`\u2713 Updated task-${id}`));
61334
61231
  const changes = [];
@@ -61371,8 +61268,8 @@ var archiveCommand = new Command("archive").description("Archive a task").argume
61371
61268
  console.error(source_default.gray(' Run "knowns init" to initialize'));
61372
61269
  process.exit(1);
61373
61270
  }
61374
- const fileStore2 = getFileStore();
61375
- const task = await fileStore2.getTask(id);
61271
+ const fileStore = getFileStore();
61272
+ const task = await fileStore.getTask(id);
61376
61273
  if (!task) {
61377
61274
  console.error(source_default.red(`\u2717 Task ${id} not found`));
61378
61275
  process.exit(1);
@@ -61436,13 +61333,13 @@ var unarchiveCommand = new Command("unarchive").description("Restore archived ta
61436
61333
  var historyCommand = new Command("history").description("View task change history").argument("<id>", "Task ID").option("--plain", "Plain text output for AI").option("--limit <n>", "Limit number of entries", Number.parseInt).action(async (rawId, options2) => {
61437
61334
  try {
61438
61335
  const id = normalizeTaskId(rawId);
61439
- const fileStore2 = getFileStore();
61440
- const task = await fileStore2.getTask(id);
61336
+ const fileStore = getFileStore();
61337
+ const task = await fileStore.getTask(id);
61441
61338
  if (!task) {
61442
61339
  console.error(source_default.red(`\u2717 Task ${id} not found`));
61443
61340
  process.exit(1);
61444
61341
  }
61445
- let versions = await fileStore2.getTaskVersionHistory(id);
61342
+ let versions = await fileStore.getTaskVersionHistory(id);
61446
61343
  versions = versions.sort((a, b) => b.version - a.version);
61447
61344
  if (options2.limit && options2.limit > 0) {
61448
61345
  versions = versions.slice(0, options2.limit);
@@ -61567,13 +61464,13 @@ function formatValuePlain(value) {
61567
61464
  var diffCommand = new Command("diff").description("Compare task versions").argument("<id>", "Task ID").option("-v, --ver <n>", "Compare current with specific version", Number.parseInt).option("--from <v>", "Start version for comparison", Number.parseInt).option("--to <v>", "End version for comparison", Number.parseInt).option("--plain", "Plain text output for AI").action(async (rawId, options2) => {
61568
61465
  try {
61569
61466
  const id = normalizeTaskId(rawId);
61570
- const fileStore2 = getFileStore();
61571
- const task = await fileStore2.getTask(id);
61467
+ const fileStore = getFileStore();
61468
+ const task = await fileStore.getTask(id);
61572
61469
  if (!task) {
61573
61470
  console.error(source_default.red(`\u2717 Task ${id} not found`));
61574
61471
  process.exit(1);
61575
61472
  }
61576
- const versions = await fileStore2.getTaskVersionHistory(id);
61473
+ const versions = await fileStore.getTaskVersionHistory(id);
61577
61474
  if (versions.length === 0) {
61578
61475
  if (options2.plain) {
61579
61476
  console.log("no_versions: true");
@@ -61750,13 +61647,13 @@ function deepEqual(a, b) {
61750
61647
  var restoreCommand = new Command("restore").description("Restore task to a previous version").argument("<id>", "Task ID").requiredOption("-v, --ver <n>", "Version to restore to", Number.parseInt).option("-y, --yes", "Skip confirmation").option("--dry-run", "Preview changes without applying").action(async (rawId, options2) => {
61751
61648
  try {
61752
61649
  const id = normalizeTaskId(rawId);
61753
- const fileStore2 = getFileStore();
61754
- const task = await fileStore2.getTask(id);
61650
+ const fileStore = getFileStore();
61651
+ const task = await fileStore.getTask(id);
61755
61652
  if (!task) {
61756
61653
  console.error(source_default.red(`\u2717 Task ${id} not found`));
61757
61654
  process.exit(1);
61758
61655
  }
61759
- const versions = await fileStore2.getTaskVersionHistory(id);
61656
+ const versions = await fileStore.getTaskVersionHistory(id);
61760
61657
  if (versions.length === 0) {
61761
61658
  console.error(source_default.red(`\u2717 No version history found for task-${id}`));
61762
61659
  process.exit(1);
@@ -61820,9 +61717,9 @@ var restoreCommand = new Command("restore").description("Restore task to a previ
61820
61717
  console.log(source_default.yellow("\u26A0 This will modify the task. Use --yes to confirm."));
61821
61718
  return;
61822
61719
  }
61823
- const _restored = await fileStore2.rollbackTask(id, options2.ver);
61720
+ const _restored = await fileStore.rollbackTask(id, options2.ver);
61824
61721
  console.log(source_default.green(`\u2713 Restored task-${id} to version ${options2.ver}`));
61825
- console.log(source_default.gray(` New version created: v${await fileStore2.getTaskCurrentVersion(id)}`));
61722
+ console.log(source_default.gray(` New version created: v${await fileStore.getTaskCurrentVersion(id)}`));
61826
61723
  } catch (error48) {
61827
61724
  console.error(source_default.red("\u2717 Failed to restore task"));
61828
61725
  if (error48 instanceof Error) {
@@ -61984,17 +61881,17 @@ var taskCommand = new Command("task").description("Manage tasks").argument("[id]
61984
61881
  }
61985
61882
  try {
61986
61883
  const id = normalizeTaskId(rawId);
61987
- const fileStore2 = getFileStore();
61988
- const task = await fileStore2.getTask(id);
61884
+ const fileStore = getFileStore();
61885
+ const task = await fileStore.getTask(id);
61989
61886
  if (!task) {
61990
61887
  console.error(source_default.red(`\u2717 Task ${id} not found`));
61991
61888
  process.exit(1);
61992
61889
  }
61993
61890
  if (options2.children) {
61994
- console.log(await formatTaskChildren(task, fileStore2, options2.plain));
61891
+ console.log(await formatTaskChildren(task, fileStore, options2.plain));
61995
61892
  return;
61996
61893
  }
61997
- console.log(await formatTask(task, fileStore2, options2.plain));
61894
+ console.log(await formatTask(task, fileStore, options2.plain));
61998
61895
  } catch (error48) {
61999
61896
  console.error(source_default.red("\u2717 Failed to view task"));
62000
61897
  if (error48 instanceof Error) {
@@ -62140,8 +62037,8 @@ function printColoredBoard(columns) {
62140
62037
  var boardCommand = new Command("board").description("Display Kanban board").option("--plain", "Plain text output for AI").option("--status <status>", "Filter by status").option("--assignee <name>", "Filter by assignee").action(
62141
62038
  async (options2) => {
62142
62039
  try {
62143
- const fileStore2 = getFileStore2();
62144
- let tasks = await fileStore2.getAllTasks();
62040
+ const fileStore = getFileStore2();
62041
+ let tasks = await fileStore.getAllTasks();
62145
62042
  tasks = tasks.filter((t) => !t.parent);
62146
62043
  if (options2.status) {
62147
62044
  tasks = tasks.filter((t) => t.status === options2.status);
@@ -62273,8 +62170,8 @@ var searchCommand = new Command("search").description("Search tasks and document
62273
62170
  let taskResults = [];
62274
62171
  let docResults = [];
62275
62172
  if (searchType === "task" || searchType === "all") {
62276
- const fileStore2 = getFileStore3();
62277
- const allTasks = await fileStore2.getAllTasks();
62173
+ const fileStore = getFileStore3();
62174
+ const allTasks = await fileStore.getAllTasks();
62278
62175
  taskResults = allTasks.filter((task) => {
62279
62176
  const text = `${task.title} ${task.description || ""} ${task.labels.join(" ")} ${task.id}`.toLowerCase();
62280
62177
  if (!text.includes(q)) {
@@ -64265,8 +64162,8 @@ var startCommand = new Command("start").description("Start timer for a task").ar
64265
64162
  try {
64266
64163
  const taskId = normalizeTaskId(rawTaskId);
64267
64164
  const projectRoot = getProjectRoot();
64268
- const fileStore2 = getFileStore4();
64269
- const task = await fileStore2.getTask(taskId);
64165
+ const fileStore = getFileStore4();
64166
+ const task = await fileStore.getTask(taskId);
64270
64167
  if (!task) {
64271
64168
  console.error(source_default.red(`\u2717 Task ${taskId} not found`));
64272
64169
  process.exit(1);
@@ -64303,7 +64200,7 @@ var startCommand = new Command("start").description("Start timer for a task").ar
64303
64200
  var stopCommand = new Command("stop").description("Stop timer and save time entry").argument("[taskId]", "Task ID (optional - prompts if multiple timers)").option("-a, --all", "Stop all timers").action(async (rawTaskId, options2) => {
64304
64201
  try {
64305
64202
  const projectRoot = getProjectRoot();
64306
- const fileStore2 = getFileStore4();
64203
+ const fileStore = getFileStore4();
64307
64204
  const data = await loadTimeData(projectRoot);
64308
64205
  if (data.active.length === 0) {
64309
64206
  console.log(source_default.yellow("No active timers"));
@@ -64340,7 +64237,7 @@ var stopCommand = new Command("stop").description("Stop timer and save time entr
64340
64237
  const endTime = pausedAt ? new Date(pausedAt) : /* @__PURE__ */ new Date();
64341
64238
  const elapsed = endTime.getTime() - new Date(startedAt).getTime() - totalPausedMs;
64342
64239
  const seconds = Math.floor(elapsed / 1e3);
64343
- const task = await fileStore2.getTask(taskId);
64240
+ const task = await fileStore.getTask(taskId);
64344
64241
  if (task) {
64345
64242
  const entry = {
64346
64243
  id: `te-${Date.now()}-${taskId}`,
@@ -64350,7 +64247,7 @@ var stopCommand = new Command("stop").description("Stop timer and save time entr
64350
64247
  };
64351
64248
  task.timeEntries.push(entry);
64352
64249
  task.timeSpent += seconds;
64353
- await fileStore2.updateTask(taskId, {
64250
+ await fileStore.updateTask(taskId, {
64354
64251
  timeEntries: task.timeEntries,
64355
64252
  timeSpent: task.timeSpent
64356
64253
  });
@@ -64376,7 +64273,7 @@ var stopCommand = new Command("stop").description("Stop timer and save time entr
64376
64273
  var pauseCommand = new Command("pause").description("Pause timer").argument("[taskId]", "Task ID (optional - prompts if multiple timers)").option("-a, --all", "Pause all running timers").action(async (rawTaskId, options2) => {
64377
64274
  try {
64378
64275
  const projectRoot = getProjectRoot();
64379
- const fileStore2 = getFileStore4();
64276
+ const fileStore = getFileStore4();
64380
64277
  const data = await loadTimeData(projectRoot);
64381
64278
  if (data.active.length === 0) {
64382
64279
  console.log(source_default.yellow("No active timers"));
@@ -64435,7 +64332,7 @@ var pauseCommand = new Command("pause").description("Pause timer").argument("[ta
64435
64332
  var resumeCommand = new Command("resume").description("Resume paused timer").argument("[taskId]", "Task ID (optional - prompts if multiple timers)").option("-a, --all", "Resume all paused timers").action(async (rawTaskId, options2) => {
64436
64333
  try {
64437
64334
  const projectRoot = getProjectRoot();
64438
- const fileStore2 = getFileStore4();
64335
+ const fileStore = getFileStore4();
64439
64336
  const data = await loadTimeData(projectRoot);
64440
64337
  if (data.active.length === 0) {
64441
64338
  console.log(source_default.yellow("No active timers"));
@@ -64498,7 +64395,7 @@ var resumeCommand = new Command("resume").description("Resume paused timer").arg
64498
64395
  var statusCommand = new Command("status").description("Show active timer status").option("--plain", "Plain text output for AI").action(async (options2) => {
64499
64396
  try {
64500
64397
  const projectRoot = getProjectRoot();
64501
- const fileStore2 = getFileStore4();
64398
+ const fileStore = getFileStore4();
64502
64399
  const data = await loadTimeData(projectRoot);
64503
64400
  if (data.active.length === 0) {
64504
64401
  console.log(options2?.plain ? "No active timers" : source_default.gray("No active timers"));
@@ -64526,7 +64423,7 @@ var statusCommand = new Command("status").description("Show active timer status"
64526
64423
  const status = timer.pausedAt ? source_default.yellow("(paused)") : source_default.green("(running)");
64527
64424
  let title = timer.taskTitle;
64528
64425
  if (!title) {
64529
- const task = await fileStore2.getTask(timer.taskId);
64426
+ const task = await fileStore.getTask(timer.taskId);
64530
64427
  title = task?.title || "Unknown";
64531
64428
  }
64532
64429
  console.log(` #${timer.taskId}: ${title}`);
@@ -64545,8 +64442,8 @@ var statusCommand = new Command("status").description("Show active timer status"
64545
64442
  var logCommand = new Command("log").description("Show time log for a task").argument("<taskId>", "Task ID").action(async (rawTaskId) => {
64546
64443
  try {
64547
64444
  const taskId = normalizeTaskId(rawTaskId);
64548
- const fileStore2 = getFileStore4();
64549
- const task = await fileStore2.getTask(taskId);
64445
+ const fileStore = getFileStore4();
64446
+ const task = await fileStore.getTask(taskId);
64550
64447
  if (!task) {
64551
64448
  console.error(source_default.red(`\u2717 Task ${taskId} not found`));
64552
64449
  process.exit(1);
@@ -64598,8 +64495,8 @@ function parseDuration(durationStr) {
64598
64495
  var addCommand = new Command("add").description("Manually add time entry to a task").argument("<taskId>", "Task ID").argument("<duration>", "Duration (e.g., 2h, 30m, 1h30m)").option("-n, --note <text>", "Note for this time entry").option("-d, --date <date>", "Date for time entry (default: now)").action(async (rawTaskId, durationStr, options2) => {
64599
64496
  try {
64600
64497
  const taskId = normalizeTaskId(rawTaskId);
64601
- const fileStore2 = getFileStore4();
64602
- const task = await fileStore2.getTask(taskId);
64498
+ const fileStore = getFileStore4();
64499
+ const task = await fileStore.getTask(taskId);
64603
64500
  if (!task) {
64604
64501
  console.error(source_default.red(`\u2717 Task ${taskId} not found`));
64605
64502
  process.exit(1);
@@ -64624,7 +64521,7 @@ var addCommand = new Command("add").description("Manually add time entry to a ta
64624
64521
  };
64625
64522
  task.timeEntries.push(entry);
64626
64523
  task.timeSpent += seconds;
64627
- await fileStore2.updateTask(taskId, {
64524
+ await fileStore.updateTask(taskId, {
64628
64525
  timeEntries: task.timeEntries,
64629
64526
  timeSpent: task.timeSpent
64630
64527
  });
@@ -64644,8 +64541,8 @@ var addCommand = new Command("add").description("Manually add time entry to a ta
64644
64541
  var reportCommand = new Command("report").description("Generate time tracking report").option("--from <date>", "Start date (YYYY-MM-DD)").option("--to <date>", "End date (YYYY-MM-DD)").option("--by-label", "Group by label").option("--by-status", "Group by status").option("--csv", "Export as CSV").action(
64645
64542
  async (options2) => {
64646
64543
  try {
64647
- const fileStore2 = getFileStore4();
64648
- const tasks = await fileStore2.getAllTasks();
64544
+ const fileStore = getFileStore4();
64545
+ const tasks = await fileStore.getAllTasks();
64649
64546
  let fromDate = null;
64650
64547
  let toDate = null;
64651
64548
  if (options2.from) {
@@ -88117,7 +88014,7 @@ var glob2 = Object.assign(glob_, {
88117
88014
  glob2.glob = glob2;
88118
88015
 
88119
88016
  // src/codegen/runner.ts
88120
- var import_prompts4 = __toESM(require_prompts3(), 1);
88017
+ var import_prompts3 = __toESM(require_prompts3(), 1);
88121
88018
  async function runTemplate(template, options2) {
88122
88019
  const result = {
88123
88020
  success: false,
@@ -88178,7 +88075,7 @@ async function collectPromptValues(promptDefs, prefilledValues, nonInteractive)
88178
88075
  }
88179
88076
  async function runPrompt(promptDef) {
88180
88077
  const promptConfig = buildPromptConfig(promptDef);
88181
- const response = await (0, import_prompts4.default)(promptConfig, {
88078
+ const response = await (0, import_prompts3.default)(promptConfig, {
88182
88079
  onCancel: () => {
88183
88080
  throw new Error("Template cancelled by user");
88184
88081
  }
@@ -88585,7 +88482,7 @@ export function {{camelCase name}}() {
88585
88482
  res.status(404).json({ error: `Template not found: ${name}` });
88586
88483
  return;
88587
88484
  }
88588
- const prompts4 = template.config.prompts?.map((p) => ({
88485
+ const prompts3 = template.config.prompts?.map((p) => ({
88589
88486
  name: p.name,
88590
88487
  message: p.message,
88591
88488
  type: p.type || "input",
@@ -88600,7 +88497,7 @@ export function {{camelCase name}}() {
88600
88497
  description: template.config.description,
88601
88498
  doc: template.config.doc,
88602
88499
  destination: template.config.destination || "./",
88603
- prompts: prompts4 || [],
88500
+ prompts: prompts3 || [],
88604
88501
  files: files || [],
88605
88502
  messages: template.config.messages
88606
88503
  }
@@ -90828,13 +90725,13 @@ syncCommand.addCommand(agentSubcommand);
90828
90725
  syncCommand.addCommand(ideSubcommand);
90829
90726
 
90830
90727
  // src/commands/mcp.ts
90831
- import { existsSync as existsSync33, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
90832
- import { join as join38 } from "node:path";
90728
+ import { existsSync as existsSync34, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
90729
+ import { join as join39 } from "node:path";
90833
90730
 
90834
90731
  // src/mcp/server.ts
90835
- import { existsSync as existsSync32 } from "node:fs";
90732
+ import { existsSync as existsSync33 } from "node:fs";
90836
90733
  import { readFile as readFile24 } from "node:fs/promises";
90837
- import { join as join37 } from "node:path";
90734
+ import { join as join38 } from "node:path";
90838
90735
 
90839
90736
  // node_modules/zod/v3/helpers/util.js
90840
90737
  var util;
@@ -97898,8 +97795,207 @@ var import_gray_matter11 = __toESM(require_gray_matter(), 1);
97898
97795
 
97899
97796
  // src/mcp/utils.ts
97900
97797
  import { readFile as readFile20 } from "node:fs/promises";
97901
- import { join as join32 } from "node:path";
97798
+ import { join as join33 } from "node:path";
97902
97799
  var import_gray_matter8 = __toESM(require_gray_matter(), 1);
97800
+
97801
+ // src/mcp/handlers/project.ts
97802
+ import { existsSync as existsSync28, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
97803
+ import { homedir as homedir2 } from "node:os";
97804
+ import { basename as basename4, join as join32 } from "node:path";
97805
+ var currentProjectRoot = null;
97806
+ function getProjectRoot3() {
97807
+ if (currentProjectRoot) {
97808
+ return currentProjectRoot;
97809
+ }
97810
+ if (process.env.KNOWNS_PROJECT_ROOT) {
97811
+ return process.env.KNOWNS_PROJECT_ROOT;
97812
+ }
97813
+ return process.cwd();
97814
+ }
97815
+ function setProjectRoot(path3) {
97816
+ currentProjectRoot = path3;
97817
+ }
97818
+ function getWorkspaceDirectories() {
97819
+ const home = homedir2();
97820
+ const dirs = [];
97821
+ const commonPaths = [
97822
+ join32(home, "Workspaces"),
97823
+ join32(home, "workspace"),
97824
+ join32(home, "projects"),
97825
+ join32(home, "Projects"),
97826
+ join32(home, "dev"),
97827
+ join32(home, "Development"),
97828
+ join32(home, "Code"),
97829
+ join32(home, "code"),
97830
+ join32(home, "repos"),
97831
+ join32(home, "Repos"),
97832
+ join32(home, "src"),
97833
+ join32(home, "Documents", "Projects"),
97834
+ join32(home, "Documents", "GitHub"),
97835
+ join32(home, "GitHub")
97836
+ ];
97837
+ for (const path3 of commonPaths) {
97838
+ if (existsSync28(path3)) {
97839
+ dirs.push(path3);
97840
+ }
97841
+ }
97842
+ return dirs;
97843
+ }
97844
+ function scanForKnownsProjects(baseDir, maxDepth = 2) {
97845
+ const projects = [];
97846
+ function scan(dir, depth) {
97847
+ if (depth > maxDepth) return;
97848
+ try {
97849
+ const entries = readdirSync2(dir);
97850
+ if (entries.includes(".knowns")) {
97851
+ const knownsPath = join32(dir, ".knowns");
97852
+ if (existsSync28(knownsPath) && statSync2(knownsPath).isDirectory()) {
97853
+ projects.push(dir);
97854
+ return;
97855
+ }
97856
+ }
97857
+ for (const entry of entries) {
97858
+ if (entry.startsWith(".") || entry === "node_modules" || entry === "vendor") {
97859
+ continue;
97860
+ }
97861
+ const entryPath = join32(dir, entry);
97862
+ try {
97863
+ if (statSync2(entryPath).isDirectory()) {
97864
+ scan(entryPath, depth + 1);
97865
+ }
97866
+ } catch {
97867
+ }
97868
+ }
97869
+ } catch {
97870
+ }
97871
+ }
97872
+ scan(baseDir, 0);
97873
+ return projects;
97874
+ }
97875
+ function detectKnownsProjects() {
97876
+ const workspaceDirs = getWorkspaceDirectories();
97877
+ const allProjects = [];
97878
+ const cwd = process.cwd();
97879
+ if (existsSync28(join32(cwd, ".knowns"))) {
97880
+ allProjects.push(cwd);
97881
+ }
97882
+ for (const dir of workspaceDirs) {
97883
+ const projects = scanForKnownsProjects(dir);
97884
+ for (const project of projects) {
97885
+ if (!allProjects.includes(project)) {
97886
+ allProjects.push(project);
97887
+ }
97888
+ }
97889
+ }
97890
+ return allProjects.sort().map((path3) => ({
97891
+ path: path3,
97892
+ name: basename4(path3)
97893
+ }));
97894
+ }
97895
+ var projectTools = [
97896
+ {
97897
+ name: "detect_projects",
97898
+ description: "Detect all Knowns projects on the system. Scans common workspace directories for projects with .knowns/ folder. Use this to find available projects when the current working directory is not set correctly.",
97899
+ inputSchema: {
97900
+ type: "object",
97901
+ properties: {
97902
+ additionalPaths: {
97903
+ type: "array",
97904
+ items: { type: "string" },
97905
+ description: "Additional directories to scan for projects"
97906
+ }
97907
+ }
97908
+ }
97909
+ },
97910
+ {
97911
+ name: "set_project",
97912
+ description: "Set the current working project for all subsequent Knowns MCP operations. Use this after detect_projects to select which project to work with.",
97913
+ inputSchema: {
97914
+ type: "object",
97915
+ properties: {
97916
+ projectRoot: {
97917
+ type: "string",
97918
+ description: "Absolute path to the project root directory (must contain .knowns/ folder)"
97919
+ }
97920
+ },
97921
+ required: ["projectRoot"]
97922
+ }
97923
+ },
97924
+ {
97925
+ name: "get_current_project",
97926
+ description: "Get the currently active project path and verify it's valid.",
97927
+ inputSchema: {
97928
+ type: "object",
97929
+ properties: {}
97930
+ }
97931
+ }
97932
+ ];
97933
+ function handleDetectProjects(input) {
97934
+ let projects = detectKnownsProjects();
97935
+ if (input.additionalPaths) {
97936
+ for (const path3 of input.additionalPaths) {
97937
+ if (existsSync28(path3)) {
97938
+ const additional = scanForKnownsProjects(path3);
97939
+ for (const project of additional) {
97940
+ if (!projects.find((p) => p.path === project)) {
97941
+ projects.push({ path: project, name: basename4(project) });
97942
+ }
97943
+ }
97944
+ }
97945
+ }
97946
+ }
97947
+ projects = projects.sort((a, b) => a.name.localeCompare(b.name));
97948
+ const current = currentProjectRoot || process.env.KNOWNS_PROJECT_ROOT || null;
97949
+ return {
97950
+ projects,
97951
+ currentProject: current,
97952
+ note: projects.length === 0 ? "No Knowns projects found. Initialize a project with 'knowns init'." : projects.length === 1 ? "Found 1 project. Use set_project to activate it." : `Found ${projects.length} projects. Use set_project to select one.`
97953
+ };
97954
+ }
97955
+ function handleSetProject(input) {
97956
+ const { projectRoot } = input;
97957
+ if (!existsSync28(projectRoot)) {
97958
+ return {
97959
+ success: false,
97960
+ projectRoot,
97961
+ message: `Path does not exist: ${projectRoot}`
97962
+ };
97963
+ }
97964
+ const knownsPath = join32(projectRoot, ".knowns");
97965
+ if (!existsSync28(knownsPath)) {
97966
+ return {
97967
+ success: false,
97968
+ projectRoot,
97969
+ message: `Not a Knowns project (no .knowns/ folder): ${projectRoot}`
97970
+ };
97971
+ }
97972
+ setProjectRoot(projectRoot);
97973
+ return {
97974
+ success: true,
97975
+ projectRoot,
97976
+ message: `Project set to: ${projectRoot}. All subsequent operations will use this project.`
97977
+ };
97978
+ }
97979
+ function handleGetCurrentProject() {
97980
+ let source = "cwd";
97981
+ let projectRoot = process.cwd();
97982
+ if (currentProjectRoot) {
97983
+ source = "explicit";
97984
+ projectRoot = currentProjectRoot;
97985
+ } else if (process.env.KNOWNS_PROJECT_ROOT) {
97986
+ source = "env";
97987
+ projectRoot = process.env.KNOWNS_PROJECT_ROOT;
97988
+ }
97989
+ const isValid2 = existsSync28(join32(projectRoot, ".knowns"));
97990
+ return {
97991
+ projectRoot,
97992
+ isExplicitlySet: source === "explicit",
97993
+ isValid: isValid2,
97994
+ source
97995
+ };
97996
+ }
97997
+
97998
+ // src/mcp/utils.ts
97903
97999
  function parseDuration2(durationStr) {
97904
98000
  let totalSeconds = 0;
97905
98001
  const hoursMatch = durationStr.match(/(\d+)h/);
@@ -97930,8 +98026,8 @@ function formatDuration2(seconds) {
97930
98026
  return parts.length > 0 ? parts.join(" ") : "0s";
97931
98027
  }
97932
98028
  async function fetchLinkedDocs(task) {
97933
- const projectRoot = process.cwd();
97934
- const docsDir = join32(projectRoot, ".knowns", "docs");
98029
+ const projectRoot = getProjectRoot3();
98030
+ const docsDir = join33(projectRoot, ".knowns", "docs");
97935
98031
  const allContent = [task.description || "", task.implementationPlan || "", task.implementationNotes || ""].join("\n");
97936
98032
  const docRefs = resolveDocReferences(allContent, projectRoot);
97937
98033
  const linkedDocs = [];
@@ -97939,7 +98035,7 @@ async function fetchLinkedDocs(task) {
97939
98035
  if (!ref.exists) continue;
97940
98036
  try {
97941
98037
  const filename = ref.resolvedPath.replace("@.knowns/docs/", "");
97942
- const filepath = join32(docsDir, filename);
98038
+ const filepath = join33(docsDir, filename);
97943
98039
  const fileContent = await readFile20(filepath, "utf-8");
97944
98040
  const { data, content } = (0, import_gray_matter8.default)(fileContent);
97945
98041
  linkedDocs.push({
@@ -98138,9 +98234,9 @@ var taskTools = [
98138
98234
  }
98139
98235
  }
98140
98236
  ];
98141
- async function handleCreateTask(args2, fileStore2) {
98237
+ async function handleCreateTask(args2, fileStore) {
98142
98238
  const input = createTaskSchema.parse(args2);
98143
- const task = await fileStore2.createTask({
98239
+ const task = await fileStore.createTask({
98144
98240
  title: input.title,
98145
98241
  description: input.description,
98146
98242
  status: input.status || "todo",
@@ -98163,10 +98259,10 @@ async function handleCreateTask(args2, fileStore2) {
98163
98259
  }
98164
98260
  });
98165
98261
  }
98166
- async function handleGetTask(args2, fileStore2) {
98262
+ async function handleGetTask(args2, fileStore) {
98167
98263
  const input = getTaskSchema.parse(args2);
98168
98264
  const taskId = normalizeTaskId(input.taskId);
98169
- const task = await fileStore2.getTask(taskId);
98265
+ const task = await fileStore.getTask(taskId);
98170
98266
  if (!task) {
98171
98267
  return errorResponse(`Task ${taskId} not found`);
98172
98268
  }
@@ -98189,10 +98285,10 @@ async function handleGetTask(args2, fileStore2) {
98189
98285
  }
98190
98286
  });
98191
98287
  }
98192
- async function handleUpdateTask(args2, fileStore2) {
98288
+ async function handleUpdateTask(args2, fileStore) {
98193
98289
  const input = updateTaskSchema.parse(args2);
98194
98290
  const taskId = normalizeTaskId(input.taskId);
98195
- const currentTask = await fileStore2.getTask(taskId);
98291
+ const currentTask = await fileStore.getTask(taskId);
98196
98292
  if (!currentTask) {
98197
98293
  return errorResponse(`Task ${taskId} not found`);
98198
98294
  }
@@ -98255,7 +98351,7 @@ async function handleUpdateTask(args2, fileStore2) {
98255
98351
  const separator = existingNotes ? "\n\n" : "";
98256
98352
  updates.implementationNotes = existingNotes + separator + input.appendNotes;
98257
98353
  }
98258
- const task = await fileStore2.updateTask(taskId, updates);
98354
+ const task = await fileStore.updateTask(taskId, updates);
98259
98355
  await notifyTaskUpdate(task.id);
98260
98356
  return successResponse({
98261
98357
  task: {
@@ -98269,9 +98365,9 @@ async function handleUpdateTask(args2, fileStore2) {
98269
98365
  }
98270
98366
  });
98271
98367
  }
98272
- async function handleListTasks(args2, fileStore2) {
98368
+ async function handleListTasks(args2, fileStore) {
98273
98369
  const input = listTasksSchema.parse(args2);
98274
- let tasks = await fileStore2.getAllTasks();
98370
+ let tasks = await fileStore.getAllTasks();
98275
98371
  if (input.status) {
98276
98372
  tasks = tasks.filter((t) => t.status === input.status);
98277
98373
  }
@@ -98296,9 +98392,9 @@ async function handleListTasks(args2, fileStore2) {
98296
98392
  }))
98297
98393
  });
98298
98394
  }
98299
- async function handleSearchTasks(args2, fileStore2) {
98395
+ async function handleSearchTasks(args2, fileStore) {
98300
98396
  const input = searchTasksSchema.parse(args2);
98301
- const tasks = await fileStore2.getAllTasks();
98397
+ const tasks = await fileStore.getAllTasks();
98302
98398
  const query = input.query.toLowerCase();
98303
98399
  const results = tasks.filter(
98304
98400
  (t) => t.title.toLowerCase().includes(query) || t.description?.toLowerCase().includes(query) || t.labels.some((l) => l.toLowerCase().includes(query))
@@ -98315,9 +98411,9 @@ async function handleSearchTasks(args2, fileStore2) {
98315
98411
  }
98316
98412
 
98317
98413
  // src/mcp/handlers/time.ts
98318
- import { existsSync as existsSync28 } from "node:fs";
98414
+ import { existsSync as existsSync29 } from "node:fs";
98319
98415
  import { readFile as readFile21, writeFile as writeFile15 } from "node:fs/promises";
98320
- import { join as join33 } from "node:path";
98416
+ import { join as join34 } from "node:path";
98321
98417
  var startTimeSchema = external_exports.object({
98322
98418
  taskId: external_exports.string()
98323
98419
  });
@@ -98400,8 +98496,8 @@ var timeTools = [
98400
98496
  }
98401
98497
  ];
98402
98498
  async function loadTimeData2(projectRoot) {
98403
- const timePath = join33(projectRoot, ".knowns", "time.json");
98404
- if (!existsSync28(timePath)) {
98499
+ const timePath = join34(projectRoot, ".knowns", "time.json");
98500
+ if (!existsSync29(timePath)) {
98405
98501
  return { active: [] };
98406
98502
  }
98407
98503
  const content = await readFile21(timePath, "utf-8");
@@ -98415,17 +98511,17 @@ async function loadTimeData2(projectRoot) {
98415
98511
  return data;
98416
98512
  }
98417
98513
  async function saveTimeData2(projectRoot, data) {
98418
- const timePath = join33(projectRoot, ".knowns", "time.json");
98514
+ const timePath = join34(projectRoot, ".knowns", "time.json");
98419
98515
  await writeFile15(timePath, JSON.stringify(data, null, 2), "utf-8");
98420
98516
  }
98421
- async function handleStartTime(args2, fileStore2) {
98517
+ async function handleStartTime(args2, fileStore) {
98422
98518
  const input = startTimeSchema.parse(args2);
98423
98519
  const taskId = normalizeTaskId(input.taskId);
98424
- const task = await fileStore2.getTask(taskId);
98520
+ const task = await fileStore.getTask(taskId);
98425
98521
  if (!task) {
98426
98522
  return errorResponse(`Task ${taskId} not found`);
98427
98523
  }
98428
- const data = await loadTimeData2(fileStore2.projectRoot);
98524
+ const data = await loadTimeData2(fileStore.projectRoot);
98429
98525
  const existingTimer = data.active.find((t) => t.taskId === taskId);
98430
98526
  if (existingTimer) {
98431
98527
  return errorResponse(`Timer already running for task ${taskId}`);
@@ -98438,7 +98534,7 @@ async function handleStartTime(args2, fileStore2) {
98438
98534
  totalPausedMs: 0
98439
98535
  };
98440
98536
  data.active.push(newTimer);
98441
- await saveTimeData2(fileStore2.projectRoot, data);
98537
+ await saveTimeData2(fileStore.projectRoot, data);
98442
98538
  await notifyTaskUpdate(taskId);
98443
98539
  await notifyTimeUpdate(data.active);
98444
98540
  return successResponse({
@@ -98447,14 +98543,14 @@ async function handleStartTime(args2, fileStore2) {
98447
98543
  activeTimers: data.active.length
98448
98544
  });
98449
98545
  }
98450
- async function handleStopTime(args2, fileStore2) {
98546
+ async function handleStopTime(args2, fileStore) {
98451
98547
  const input = stopTimeSchema.parse(args2);
98452
98548
  const taskId = normalizeTaskId(input.taskId);
98453
- const task = await fileStore2.getTask(taskId);
98549
+ const task = await fileStore.getTask(taskId);
98454
98550
  if (!task) {
98455
98551
  return errorResponse(`Task ${taskId} not found`);
98456
98552
  }
98457
- const data = await loadTimeData2(fileStore2.projectRoot);
98553
+ const data = await loadTimeData2(fileStore.projectRoot);
98458
98554
  const timerIndex = data.active.findIndex((t) => t.taskId === taskId);
98459
98555
  if (timerIndex === -1) {
98460
98556
  return errorResponse(`No active timer for task ${taskId}`);
@@ -98471,12 +98567,12 @@ async function handleStopTime(args2, fileStore2) {
98471
98567
  duration: duration3
98472
98568
  };
98473
98569
  const newTimeSpent = task.timeSpent + duration3;
98474
- await fileStore2.updateTask(taskId, {
98570
+ await fileStore.updateTask(taskId, {
98475
98571
  timeEntries: [...task.timeEntries, newEntry],
98476
98572
  timeSpent: newTimeSpent
98477
98573
  });
98478
98574
  data.active.splice(timerIndex, 1);
98479
- await saveTimeData2(fileStore2.projectRoot, data);
98575
+ await saveTimeData2(fileStore.projectRoot, data);
98480
98576
  await notifyTaskUpdate(taskId);
98481
98577
  await notifyTimeUpdate(data.active.length > 0 ? data.active : null);
98482
98578
  return successResponse({
@@ -98486,10 +98582,10 @@ async function handleStopTime(args2, fileStore2) {
98486
98582
  activeTimers: data.active.length
98487
98583
  });
98488
98584
  }
98489
- async function handleAddTime(args2, fileStore2) {
98585
+ async function handleAddTime(args2, fileStore) {
98490
98586
  const input = addTimeSchema.parse(args2);
98491
98587
  const taskId = normalizeTaskId(input.taskId);
98492
- const task = await fileStore2.getTask(taskId);
98588
+ const task = await fileStore.getTask(taskId);
98493
98589
  if (!task) {
98494
98590
  return errorResponse(`Task ${taskId} not found`);
98495
98591
  }
@@ -98503,7 +98599,7 @@ async function handleAddTime(args2, fileStore2) {
98503
98599
  note: input.note || "Added via MCP"
98504
98600
  };
98505
98601
  const newTimeSpent = task.timeSpent + duration3;
98506
- await fileStore2.updateTask(taskId, {
98602
+ await fileStore.updateTask(taskId, {
98507
98603
  timeEntries: [...task.timeEntries, newEntry],
98508
98604
  timeSpent: newTimeSpent
98509
98605
  });
@@ -98513,9 +98609,9 @@ async function handleAddTime(args2, fileStore2) {
98513
98609
  totalTime: formatDuration2(newTimeSpent)
98514
98610
  });
98515
98611
  }
98516
- async function handleGetTimeReport(args2, fileStore2) {
98612
+ async function handleGetTimeReport(args2, fileStore) {
98517
98613
  const input = getTimeReportSchema.parse(args2);
98518
- const tasks = await fileStore2.getAllTasks();
98614
+ const tasks = await fileStore.getAllTasks();
98519
98615
  let fromDate;
98520
98616
  let toDate;
98521
98617
  if (input.from) fromDate = new Date(input.from);
@@ -98597,8 +98693,8 @@ var boardTools = [
98597
98693
  }
98598
98694
  }
98599
98695
  ];
98600
- async function handleGetBoard(fileStore2) {
98601
- const tasks = await fileStore2.getAllTasks();
98696
+ async function handleGetBoard(fileStore) {
98697
+ const tasks = await fileStore.getAllTasks();
98602
98698
  const board = {
98603
98699
  todo: [],
98604
98700
  "in-progress": [],
@@ -98631,11 +98727,13 @@ async function handleGetBoard(fileStore2) {
98631
98727
  }
98632
98728
 
98633
98729
  // src/mcp/handlers/doc.ts
98634
- import { existsSync as existsSync29 } from "node:fs";
98730
+ import { existsSync as existsSync30 } from "node:fs";
98635
98731
  import { mkdir as mkdir17, readFile as readFile22, readdir as readdir13, writeFile as writeFile16 } from "node:fs/promises";
98636
- import { join as join34 } from "node:path";
98732
+ import { join as join35 } from "node:path";
98637
98733
  var import_gray_matter9 = __toESM(require_gray_matter(), 1);
98638
- var DOCS_DIR4 = join34(process.cwd(), ".knowns", "docs");
98734
+ function getDocsDir() {
98735
+ return join35(getProjectRoot3(), ".knowns", "docs");
98736
+ }
98639
98737
  var listDocsSchema = external_exports.object({
98640
98738
  tag: external_exports.string().optional()
98641
98739
  });
@@ -98785,8 +98883,8 @@ var docTools = [
98785
98883
  }
98786
98884
  ];
98787
98885
  async function ensureDocsDir2() {
98788
- if (!existsSync29(DOCS_DIR4)) {
98789
- await mkdir17(DOCS_DIR4, { recursive: true });
98886
+ if (!existsSync30(getDocsDir())) {
98887
+ await mkdir17(getDocsDir(), { recursive: true });
98790
98888
  }
98791
98889
  }
98792
98890
  function titleToFilename2(title) {
@@ -98794,13 +98892,13 @@ function titleToFilename2(title) {
98794
98892
  }
98795
98893
  async function getAllMdFiles2(dir, basePath = "") {
98796
98894
  const files = [];
98797
- if (!existsSync29(dir)) {
98895
+ if (!existsSync30(dir)) {
98798
98896
  return files;
98799
98897
  }
98800
98898
  const entries = await readdir13(dir, { withFileTypes: true });
98801
98899
  for (const entry of entries) {
98802
- const fullPath = join34(dir, entry.name);
98803
- const relativePath = normalizePath2(basePath ? join34(basePath, entry.name) : entry.name);
98900
+ const fullPath = join35(dir, entry.name);
98901
+ const relativePath = normalizePath2(basePath ? join35(basePath, entry.name) : entry.name);
98804
98902
  if (entry.isDirectory()) {
98805
98903
  const subFiles = await getAllMdFiles2(fullPath, relativePath);
98806
98904
  files.push(...subFiles);
@@ -98813,16 +98911,16 @@ async function getAllMdFiles2(dir, basePath = "") {
98813
98911
  async function resolveDocPath2(name) {
98814
98912
  await ensureDocsDir2();
98815
98913
  let filename = name.endsWith(".md") ? name : `${name}.md`;
98816
- let filepath = join34(DOCS_DIR4, filename);
98817
- if (existsSync29(filepath)) {
98914
+ let filepath = join35(getDocsDir(), filename);
98915
+ if (existsSync30(filepath)) {
98818
98916
  return { filepath, filename };
98819
98917
  }
98820
98918
  filename = `${titleToFilename2(name)}.md`;
98821
- filepath = join34(DOCS_DIR4, filename);
98822
- if (existsSync29(filepath)) {
98919
+ filepath = join35(getDocsDir(), filename);
98920
+ if (existsSync30(filepath)) {
98823
98921
  return { filepath, filename };
98824
98922
  }
98825
- const allFiles = await getAllMdFiles2(DOCS_DIR4);
98923
+ const allFiles = await getAllMdFiles2(getDocsDir());
98826
98924
  const searchName = name.toLowerCase().replace(/\.md$/, "");
98827
98925
  const matchingFile = allFiles.find((file3) => {
98828
98926
  const fileNameOnly = file3.toLowerCase().replace(/\.md$/, "");
@@ -98831,7 +98929,7 @@ async function resolveDocPath2(name) {
98831
98929
  });
98832
98930
  if (matchingFile) {
98833
98931
  return {
98834
- filepath: join34(DOCS_DIR4, matchingFile),
98932
+ filepath: join35(getDocsDir(), matchingFile),
98835
98933
  filename: matchingFile
98836
98934
  };
98837
98935
  }
@@ -98840,7 +98938,7 @@ async function resolveDocPath2(name) {
98840
98938
  async function handleListDocs(args2) {
98841
98939
  const input = listDocsSchema.parse(args2);
98842
98940
  await ensureDocsDir2();
98843
- const projectRoot = process.cwd();
98941
+ const projectRoot = getProjectRoot3();
98844
98942
  const allDocs = await listAllDocs(projectRoot);
98845
98943
  if (allDocs.length === 0) {
98846
98944
  return successResponse({
@@ -98980,8 +99078,8 @@ async function handleGetDoc(args2) {
98980
99078
  }
98981
99079
  });
98982
99080
  }
98983
- const projectRoot = process.cwd();
98984
- const tasksDir = join34(projectRoot, ".knowns", "tasks");
99081
+ const projectRoot = getProjectRoot3();
99082
+ const tasksDir = join35(projectRoot, ".knowns", "tasks");
98985
99083
  const refs = await validateRefs(projectRoot, content, tasksDir);
98986
99084
  const brokenRefs = refs.filter((r) => !r.exists).map((r) => r.ref);
98987
99085
  return successResponse({
@@ -99001,18 +99099,18 @@ async function handleCreateDoc(args2) {
99001
99099
  const input = createDocSchema.parse(args2);
99002
99100
  await ensureDocsDir2();
99003
99101
  const filename = `${titleToFilename2(input.title)}.md`;
99004
- let targetDir = DOCS_DIR4;
99102
+ let targetDir = getDocsDir();
99005
99103
  let relativePath = filename;
99006
99104
  if (input.folder) {
99007
99105
  const folderPath = input.folder.replace(/^\/|\/$/g, "");
99008
- targetDir = join34(DOCS_DIR4, folderPath);
99009
- relativePath = join34(folderPath, filename);
99010
- if (!existsSync29(targetDir)) {
99106
+ targetDir = join35(getDocsDir(), folderPath);
99107
+ relativePath = join35(folderPath, filename);
99108
+ if (!existsSync30(targetDir)) {
99011
99109
  await mkdir17(targetDir, { recursive: true });
99012
99110
  }
99013
99111
  }
99014
- const filepath = join34(targetDir, filename);
99015
- if (existsSync29(filepath)) {
99112
+ const filepath = join35(targetDir, filename);
99113
+ if (existsSync30(filepath)) {
99016
99114
  return errorResponse(`Document already exists: ${relativePath}`);
99017
99115
  }
99018
99116
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -99092,11 +99190,11 @@ ${input.appendContent}`;
99092
99190
  async function handleSearchDocs(args2) {
99093
99191
  const input = searchDocsSchema.parse(args2);
99094
99192
  await ensureDocsDir2();
99095
- const mdFiles = await getAllMdFiles2(DOCS_DIR4);
99193
+ const mdFiles = await getAllMdFiles2(getDocsDir());
99096
99194
  const query = input.query.toLowerCase();
99097
99195
  const results = [];
99098
99196
  for (const file3 of mdFiles) {
99099
- const fileContent = await readFile22(join34(DOCS_DIR4, file3), "utf-8");
99197
+ const fileContent = await readFile22(join35(getDocsDir(), file3), "utf-8");
99100
99198
  const { data, content } = (0, import_gray_matter9.default)(fileContent);
99101
99199
  const metadata = data;
99102
99200
  if (input.tag && !metadata.tags?.includes(input.tag)) {
@@ -99132,56 +99230,13 @@ async function handleSearchDocs(args2) {
99132
99230
  });
99133
99231
  }
99134
99232
 
99135
- // src/mcp/handlers/guideline.ts
99136
- var getGuidelineSchema = external_exports.object({
99137
- type: external_exports.enum(["unified", "cli", "mcp"]).optional().default("unified")
99138
- });
99139
- var guidelineTools = [
99140
- {
99141
- name: "get_guideline",
99142
- description: "Get usage guidelines for Knowns CLI/MCP. Call this at session start to understand how to use the tools correctly.",
99143
- inputSchema: {
99144
- type: "object",
99145
- properties: {
99146
- type: {
99147
- type: "string",
99148
- enum: ["unified", "cli", "mcp"],
99149
- description: "Type of guidelines: unified (default, covers both), cli (CLI only), mcp (MCP only)"
99150
- }
99151
- }
99152
- }
99153
- }
99154
- ];
99155
- async function handleGetGuideline(args2) {
99156
- const input = getGuidelineSchema.parse(args2 || {});
99157
- let guidelines;
99158
- switch (input.type) {
99159
- case "mcp":
99160
- guidelines = MCPGuidelines.getFull();
99161
- break;
99162
- case "cli":
99163
- guidelines = Guidelines.getFull();
99164
- break;
99165
- default:
99166
- guidelines = MCPGuidelines.getFull();
99167
- break;
99168
- }
99169
- return {
99170
- content: [
99171
- {
99172
- type: "text",
99173
- text: guidelines
99174
- }
99175
- ]
99176
- };
99177
- }
99178
-
99179
99233
  // src/mcp/handlers/template.ts
99180
- import { existsSync as existsSync30 } from "node:fs";
99234
+ import { existsSync as existsSync31 } from "node:fs";
99181
99235
  import { mkdir as mkdir18, writeFile as writeFile17 } from "node:fs/promises";
99182
- import { join as join35 } from "node:path";
99183
- var TEMPLATES_DIR3 = join35(process.cwd(), ".knowns", "templates");
99184
- var PROJECT_ROOT3 = process.cwd();
99236
+ import { join as join36 } from "node:path";
99237
+ function getTemplatesDir() {
99238
+ return join36(getProjectRoot3(), ".knowns", "templates");
99239
+ }
99185
99240
  var listTemplatesSchema = external_exports.object({});
99186
99241
  var getTemplateSchema = external_exports.object({
99187
99242
  name: external_exports.string()
@@ -99287,7 +99342,7 @@ async function handleListTemplates(_args) {
99287
99342
  const templateList = [];
99288
99343
  for (const t of allTemplates) {
99289
99344
  try {
99290
- const loaded = await listTemplates(join35(t.path, ".."));
99345
+ const loaded = await listTemplates(join36(t.path, ".."));
99291
99346
  const match2 = loaded.find((l) => l.name === t.name);
99292
99347
  templateList.push({
99293
99348
  name: t.name,
@@ -99324,7 +99379,7 @@ async function handleListTemplates(_args) {
99324
99379
  async function handleGetTemplate(args2) {
99325
99380
  const input = getTemplateSchema.parse(args2);
99326
99381
  try {
99327
- const resolved = await resolveTemplate(PROJECT_ROOT3, input.name);
99382
+ const resolved = await resolveTemplate(getProjectRoot3(), input.name);
99328
99383
  if (!resolved) {
99329
99384
  return errorResponse(`Template not found: ${input.name}. Use list_templates to see available templates.`);
99330
99385
  }
@@ -99332,7 +99387,7 @@ async function handleGetTemplate(args2) {
99332
99387
  if (!template) {
99333
99388
  return errorResponse(`Failed to load template: ${input.name}`);
99334
99389
  }
99335
- const prompts4 = template.config.prompts?.map((p) => ({
99390
+ const prompts3 = template.config.prompts?.map((p) => ({
99336
99391
  name: p.name,
99337
99392
  message: p.message,
99338
99393
  type: p.type || "text",
@@ -99361,7 +99416,7 @@ async function handleGetTemplate(args2) {
99361
99416
  description: template.config.description,
99362
99417
  doc: template.config.doc,
99363
99418
  // Linked documentation - AI should read this
99364
- prompts: prompts4 || [],
99419
+ prompts: prompts3 || [],
99365
99420
  actions: actions || [],
99366
99421
  messages: template.config.messages
99367
99422
  },
@@ -99377,7 +99432,7 @@ async function handleRunTemplate(args2) {
99377
99432
  const input = runTemplateSchema.parse(args2);
99378
99433
  const dryRun = input.dryRun !== false;
99379
99434
  try {
99380
- const resolved = await resolveTemplate(PROJECT_ROOT3, input.name);
99435
+ const resolved = await resolveTemplate(getProjectRoot3(), input.name);
99381
99436
  if (!resolved) {
99382
99437
  return errorResponse(`Template not found: ${input.name}. Use list_templates to see available templates.`);
99383
99438
  }
@@ -99401,7 +99456,7 @@ async function handleRunTemplate(args2) {
99401
99456
  }
99402
99457
  }
99403
99458
  const result = await runTemplate(template, {
99404
- projectRoot: PROJECT_ROOT3,
99459
+ projectRoot: getProjectRoot3(),
99405
99460
  values,
99406
99461
  dryRun
99407
99462
  });
@@ -99430,11 +99485,11 @@ async function handleRunTemplate(args2) {
99430
99485
  async function handleCreateTemplate(args2) {
99431
99486
  const input = createTemplateSchema.parse(args2);
99432
99487
  try {
99433
- if (!existsSync30(TEMPLATES_DIR3)) {
99434
- await mkdir18(TEMPLATES_DIR3, { recursive: true });
99488
+ if (!existsSync31(getTemplatesDir())) {
99489
+ await mkdir18(getTemplatesDir(), { recursive: true });
99435
99490
  }
99436
- const templateDir = join35(TEMPLATES_DIR3, input.name);
99437
- if (existsSync30(templateDir)) {
99491
+ const templateDir = join36(getTemplatesDir(), input.name);
99492
+ if (existsSync31(templateDir)) {
99438
99493
  return errorResponse(`Template "${input.name}" already exists`);
99439
99494
  }
99440
99495
  await mkdir18(templateDir, { recursive: true });
@@ -99463,7 +99518,7 @@ messages:
99463
99518
  success: |
99464
99519
  \u2713 Created {{name}}!
99465
99520
  `;
99466
- await writeFile17(join35(templateDir, "_template.yaml"), configContent, "utf-8");
99521
+ await writeFile17(join36(templateDir, "_template.yaml"), configContent, "utf-8");
99467
99522
  const exampleTemplate = `/**
99468
99523
  * {{pascalCase name}}
99469
99524
  * Generated from ${input.name} template
@@ -99473,7 +99528,7 @@ export function {{camelCase name}}() {
99473
99528
  console.log("Hello from {{name}}!");
99474
99529
  }
99475
99530
  `;
99476
- await writeFile17(join35(templateDir, "example.ts.hbs"), exampleTemplate, "utf-8");
99531
+ await writeFile17(join36(templateDir, "example.ts.hbs"), exampleTemplate, "utf-8");
99477
99532
  return successResponse({
99478
99533
  message: `Created template: ${input.name}`,
99479
99534
  template: {
@@ -99496,9 +99551,9 @@ export function {{camelCase name}}() {
99496
99551
 
99497
99552
  // src/mcp/handlers/search.ts
99498
99553
  var import_gray_matter10 = __toESM(require_gray_matter(), 1);
99499
- import { existsSync as existsSync31 } from "node:fs";
99554
+ import { existsSync as existsSync32 } from "node:fs";
99500
99555
  import { readFile as readFile23, readdir as readdir14 } from "node:fs/promises";
99501
- import { join as join36 } from "node:path";
99556
+ import { join as join37 } from "node:path";
99502
99557
  var searchSchema = external_exports.object({
99503
99558
  query: external_exports.string(),
99504
99559
  type: external_exports.enum(["all", "task", "doc"]).optional(),
@@ -99585,12 +99640,12 @@ function calculateDocScore2(title, description, content, tags, query) {
99585
99640
  }
99586
99641
  async function getAllMdFiles3(dir, basePath = "") {
99587
99642
  const files = [];
99588
- if (!existsSync31(dir)) {
99643
+ if (!existsSync32(dir)) {
99589
99644
  return files;
99590
99645
  }
99591
99646
  const entries = await readdir14(dir, { withFileTypes: true });
99592
99647
  for (const entry of entries) {
99593
- const fullPath = join36(dir, entry.name);
99648
+ const fullPath = join37(dir, entry.name);
99594
99649
  const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;
99595
99650
  if (entry.isDirectory()) {
99596
99651
  const subFiles = await getAllMdFiles3(fullPath, relativePath);
@@ -99601,8 +99656,8 @@ async function getAllMdFiles3(dir, basePath = "") {
99601
99656
  }
99602
99657
  return files;
99603
99658
  }
99604
- async function searchTasks(fileStore2, query, filters) {
99605
- const allTasks = await fileStore2.getAllTasks();
99659
+ async function searchTasks(fileStore, query, filters) {
99660
+ const allTasks = await fileStore.getAllTasks();
99606
99661
  const q = query.toLowerCase();
99607
99662
  return allTasks.filter((task) => {
99608
99663
  const text = `${task.title} ${task.description || ""} ${task.labels.join(" ")} ${task.id} ${task.implementationPlan || ""} ${task.implementationNotes || ""}`.toLowerCase();
@@ -99633,14 +99688,14 @@ async function searchTasks(fileStore2, query, filters) {
99633
99688
  })).sort((a, b) => b.score - a.score);
99634
99689
  }
99635
99690
  async function searchDocs2(docsDir, query, tagFilter) {
99636
- if (!existsSync31(docsDir)) {
99691
+ if (!existsSync32(docsDir)) {
99637
99692
  return [];
99638
99693
  }
99639
99694
  const mdFiles = await getAllMdFiles3(docsDir);
99640
99695
  const q = query.toLowerCase();
99641
99696
  const results = [];
99642
99697
  for (const file3 of mdFiles) {
99643
- const fileContent = await readFile23(join36(docsDir, file3), "utf-8");
99698
+ const fileContent = await readFile23(join37(docsDir, file3), "utf-8");
99644
99699
  const { data, content } = (0, import_gray_matter10.default)(fileContent);
99645
99700
  const metadata = data;
99646
99701
  if (tagFilter && !metadata.tags?.includes(tagFilter)) {
@@ -99673,15 +99728,15 @@ async function searchDocs2(docsDir, query, tagFilter) {
99673
99728
  }
99674
99729
  return results.sort((a, b) => b.score - a.score);
99675
99730
  }
99676
- async function handleSearch(args2, fileStore2) {
99731
+ async function handleSearch(args2, fileStore) {
99677
99732
  const input = searchSchema.parse(args2);
99678
99733
  const searchType = input.type || "all";
99679
99734
  const limit = input.limit || 20;
99680
- const docsDir = join36(process.cwd(), ".knowns", "docs");
99735
+ const docsDir = join37(getProjectRoot3(), ".knowns", "docs");
99681
99736
  let taskResults = [];
99682
99737
  let docResults = [];
99683
99738
  if (searchType === "all" || searchType === "task") {
99684
- taskResults = await searchTasks(fileStore2, input.query, {
99739
+ taskResults = await searchTasks(fileStore, input.query, {
99685
99740
  status: input.status,
99686
99741
  priority: input.priority,
99687
99742
  assignee: input.assignee,
@@ -99709,7 +99764,16 @@ async function handleSearch(args2, fileStore2) {
99709
99764
  }
99710
99765
 
99711
99766
  // src/mcp/server.ts
99712
- var fileStore = new FileStore(process.cwd());
99767
+ var fileStoreCache = /* @__PURE__ */ new Map();
99768
+ function getFileStore5() {
99769
+ const projectRoot = getProjectRoot3();
99770
+ let store = fileStoreCache.get(projectRoot);
99771
+ if (!store) {
99772
+ store = new FileStore(projectRoot);
99773
+ fileStoreCache.set(projectRoot, store);
99774
+ }
99775
+ return store;
99776
+ }
99713
99777
  var server = new Server(
99714
99778
  {
99715
99779
  name: "knowns-mcp-server",
@@ -99723,11 +99787,11 @@ var server = new Server(
99723
99787
  }
99724
99788
  );
99725
99789
  var tools = [
99790
+ ...projectTools,
99726
99791
  ...taskTools,
99727
99792
  ...timeTools,
99728
99793
  ...boardTools,
99729
99794
  ...docTools,
99730
- ...guidelineTools,
99731
99795
  ...templateTools,
99732
99796
  ...searchTools
99733
99797
  ];
@@ -99738,29 +99802,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
99738
99802
  const { name, arguments: args2 } = request.params;
99739
99803
  try {
99740
99804
  switch (name) {
99805
+ // Project handlers (no FileStore needed)
99806
+ case "detect_projects":
99807
+ return { content: [{ type: "text", text: JSON.stringify(handleDetectProjects(args2 || {}), null, 2) }] };
99808
+ case "set_project":
99809
+ return {
99810
+ content: [{ type: "text", text: JSON.stringify(handleSetProject(args2), null, 2) }]
99811
+ };
99812
+ case "get_current_project":
99813
+ return { content: [{ type: "text", text: JSON.stringify(handleGetCurrentProject(), null, 2) }] };
99741
99814
  // Task handlers
99742
99815
  case "create_task":
99743
- return await handleCreateTask(args2, fileStore);
99816
+ return await handleCreateTask(args2, getFileStore5());
99744
99817
  case "get_task":
99745
- return await handleGetTask(args2, fileStore);
99818
+ return await handleGetTask(args2, getFileStore5());
99746
99819
  case "update_task":
99747
- return await handleUpdateTask(args2, fileStore);
99820
+ return await handleUpdateTask(args2, getFileStore5());
99748
99821
  case "list_tasks":
99749
- return await handleListTasks(args2, fileStore);
99822
+ return await handleListTasks(args2, getFileStore5());
99750
99823
  case "search_tasks":
99751
- return await handleSearchTasks(args2, fileStore);
99824
+ return await handleSearchTasks(args2, getFileStore5());
99752
99825
  // Time handlers
99753
99826
  case "start_time":
99754
- return await handleStartTime(args2, fileStore);
99827
+ return await handleStartTime(args2, getFileStore5());
99755
99828
  case "stop_time":
99756
- return await handleStopTime(args2, fileStore);
99829
+ return await handleStopTime(args2, getFileStore5());
99757
99830
  case "add_time":
99758
- return await handleAddTime(args2, fileStore);
99831
+ return await handleAddTime(args2, getFileStore5());
99759
99832
  case "get_time_report":
99760
- return await handleGetTimeReport(args2, fileStore);
99833
+ return await handleGetTimeReport(args2, getFileStore5());
99761
99834
  // Board handlers
99762
99835
  case "get_board":
99763
- return await handleGetBoard(fileStore);
99836
+ return await handleGetBoard(getFileStore5());
99764
99837
  // Doc handlers
99765
99838
  case "list_docs":
99766
99839
  return await handleListDocs(args2);
@@ -99772,9 +99845,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
99772
99845
  return await handleUpdateDoc(args2);
99773
99846
  case "search_docs":
99774
99847
  return await handleSearchDocs(args2);
99775
- // Guideline handler
99776
- case "get_guideline":
99777
- return await handleGetGuideline(args2);
99778
99848
  // Template handlers
99779
99849
  case "list_templates":
99780
99850
  return await handleListTemplates(args2);
@@ -99786,7 +99856,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
99786
99856
  return await handleCreateTemplate(args2);
99787
99857
  // Unified search handler
99788
99858
  case "search":
99789
- return await handleSearch(args2, fileStore);
99859
+ return await handleSearch(args2, getFileStore5());
99790
99860
  default:
99791
99861
  return errorResponse(`Unknown tool: ${name}`);
99792
99862
  }
@@ -99795,8 +99865,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
99795
99865
  }
99796
99866
  });
99797
99867
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
99798
- const tasks = await fileStore.getAllTasks();
99799
- const docsDir = join37(process.cwd(), ".knowns", "docs");
99868
+ const tasks = await getFileStore5().getAllTasks();
99869
+ const docsDir = join38(getProjectRoot3(), ".knowns", "docs");
99800
99870
  const taskResources = tasks.map((task) => ({
99801
99871
  uri: `knowns://task/${task.id}`,
99802
99872
  name: task.title,
@@ -99804,14 +99874,14 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
99804
99874
  description: `Task #${task.id}: ${task.title}`
99805
99875
  }));
99806
99876
  const docResources = [];
99807
- if (existsSync32(docsDir)) {
99877
+ if (existsSync33(docsDir)) {
99808
99878
  const { readdir: readdir16 } = await import("node:fs/promises");
99809
99879
  async function getAllMdFiles4(dir, basePath = "") {
99810
99880
  const files = [];
99811
99881
  const entries = await readdir16(dir, { withFileTypes: true });
99812
99882
  for (const entry of entries) {
99813
- const fullPath = join37(dir, entry.name);
99814
- const relativePath = normalizePath2(basePath ? join37(basePath, entry.name) : entry.name);
99883
+ const fullPath = join38(dir, entry.name);
99884
+ const relativePath = normalizePath2(basePath ? join38(basePath, entry.name) : entry.name);
99815
99885
  if (entry.isDirectory()) {
99816
99886
  const subFiles = await getAllMdFiles4(fullPath, relativePath);
99817
99887
  files.push(...subFiles);
@@ -99823,7 +99893,7 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
99823
99893
  }
99824
99894
  const mdFiles = await getAllMdFiles4(docsDir);
99825
99895
  for (const file3 of mdFiles) {
99826
- const filepath = join37(docsDir, file3);
99896
+ const filepath = join38(docsDir, file3);
99827
99897
  const content = await readFile24(filepath, "utf-8");
99828
99898
  const { data } = (0, import_gray_matter11.default)(content);
99829
99899
  docResources.push({
@@ -99843,7 +99913,7 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
99843
99913
  const taskMatch = uri.match(/^knowns:\/\/task\/(.+)$/);
99844
99914
  if (taskMatch) {
99845
99915
  const taskId = taskMatch[1];
99846
- const task = await fileStore.getTask(taskId);
99916
+ const task = await getFileStore5().getTask(taskId);
99847
99917
  if (!task) {
99848
99918
  throw new Error(`Task ${taskId} not found`);
99849
99919
  }
@@ -99860,9 +99930,9 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
99860
99930
  const docMatch = uri.match(/^knowns:\/\/doc\/(.+)$/);
99861
99931
  if (docMatch) {
99862
99932
  const docPath = docMatch[1];
99863
- const docsDir = join37(process.cwd(), ".knowns", "docs");
99864
- const filepath = join37(docsDir, `${docPath}.md`);
99865
- if (!existsSync32(filepath)) {
99933
+ const docsDir = join38(getProjectRoot3(), ".knowns", "docs");
99934
+ const filepath = join38(docsDir, `${docPath}.md`);
99935
+ if (!existsSync33(filepath)) {
99866
99936
  throw new Error(`Documentation ${docPath} not found`);
99867
99937
  }
99868
99938
  const content = await readFile24(filepath, "utf-8");
@@ -99944,13 +100014,13 @@ async function setupClaudeCode() {
99944
100014
  return false;
99945
100015
  }
99946
100016
  function createProjectMcpJson(projectRoot) {
99947
- const mcpJsonPath = join38(projectRoot, ".mcp.json");
100017
+ const mcpJsonPath = join39(projectRoot, ".mcp.json");
99948
100018
  const mcpConfig = {
99949
100019
  mcpServers: {
99950
100020
  knowns: getMcpConfig()
99951
100021
  }
99952
100022
  };
99953
- if (existsSync33(mcpJsonPath)) {
100023
+ if (existsSync34(mcpJsonPath)) {
99954
100024
  try {
99955
100025
  const existing = JSON.parse(readFileSync3(mcpJsonPath, "utf-8"));
99956
100026
  if (existing?.mcpServers?.knowns) {
@@ -99994,12 +100064,9 @@ var mcpCommand = new Command("mcp").description("Start MCP server for AI agent i
99994
100064
  return;
99995
100065
  }
99996
100066
  const projectRoot = findProjectRoot();
99997
- if (!projectRoot) {
99998
- console.error(source_default.red("Error: Not in a Knowns project"));
99999
- console.error(source_default.gray("Run 'knowns init' to initialize a project"));
100000
- process.exit(1);
100067
+ if (projectRoot) {
100068
+ process.chdir(projectRoot);
100001
100069
  }
100002
- process.chdir(projectRoot);
100003
100070
  try {
100004
100071
  await startMcpServer({ verbose: options2.verbose });
100005
100072
  } catch (error48) {
@@ -100050,11 +100117,11 @@ function showConfigInfo() {
100050
100117
  }
100051
100118
 
100052
100119
  // src/commands/template.ts
100053
- import { existsSync as existsSync34 } from "node:fs";
100120
+ import { existsSync as existsSync35 } from "node:fs";
100054
100121
  import { mkdir as mkdir19, writeFile as writeFile18 } from "node:fs/promises";
100055
- import { join as join39 } from "node:path";
100056
- var TEMPLATES_DIR4 = ".knowns/templates";
100057
- function getProjectRoot3() {
100122
+ import { join as join40 } from "node:path";
100123
+ var TEMPLATES_DIR3 = ".knowns/templates";
100124
+ function getProjectRoot4() {
100058
100125
  const projectRoot = findProjectRoot();
100059
100126
  if (!projectRoot) {
100060
100127
  console.error(source_default.red("\u2717 Not a knowns project"));
@@ -100063,12 +100130,12 @@ function getProjectRoot3() {
100063
100130
  }
100064
100131
  return projectRoot;
100065
100132
  }
100066
- function getTemplatesDir(projectRoot) {
100067
- return join39(projectRoot, TEMPLATES_DIR4);
100133
+ function getTemplatesDir2(projectRoot) {
100134
+ return join40(projectRoot, TEMPLATES_DIR3);
100068
100135
  }
100069
100136
  async function ensureTemplatesDir(projectRoot) {
100070
- const templatesDir = getTemplatesDir(projectRoot);
100071
- if (!existsSync34(templatesDir)) {
100137
+ const templatesDir = getTemplatesDir2(projectRoot);
100138
+ if (!existsSync35(templatesDir)) {
100072
100139
  await mkdir19(templatesDir, { recursive: true });
100073
100140
  }
100074
100141
  return templatesDir;
@@ -100076,7 +100143,7 @@ async function ensureTemplatesDir(projectRoot) {
100076
100143
  var templateCommand = new Command("template").description("Manage code generation templates").enablePositionalOptions();
100077
100144
  var listCommand4 = new Command("list").description("List available templates (local + imported)").option("--plain", "Plain text output for AI").option("--local", "Show only local templates").option("--imported", "Show only imported templates").action(async (options2) => {
100078
100145
  try {
100079
- const projectRoot = getProjectRoot3();
100146
+ const projectRoot = getProjectRoot4();
100080
100147
  const allTemplates = await listAllTemplates(projectRoot);
100081
100148
  let templates = allTemplates;
100082
100149
  if (options2.local) {
@@ -100096,7 +100163,7 @@ var listCommand4 = new Command("list").description("List available templates (lo
100096
100163
  const templatesWithDesc = [];
100097
100164
  for (const t of templates) {
100098
100165
  try {
100099
- const loaded = await listTemplates(join39(t.path, ".."));
100166
+ const loaded = await listTemplates(join40(t.path, ".."));
100100
100167
  const match2 = loaded.find((l) => l.name === t.name);
100101
100168
  templatesWithDesc.push({
100102
100169
  ref: t.ref,
@@ -100183,7 +100250,7 @@ var listCommand4 = new Command("list").description("List available templates (lo
100183
100250
  });
100184
100251
  var runCommand = new Command("run").description("Run a template to generate files").argument("<name>", "Template name (supports import prefix, e.g., 'knowns/component')").option("--dry-run", "Preview without writing files").option("-f, --force", "Overwrite existing files").option("--plain", "Plain text output for AI").allowUnknownOption(true).action(async (name, options2, command) => {
100185
100252
  try {
100186
- const projectRoot = getProjectRoot3();
100253
+ const projectRoot = getProjectRoot4();
100187
100254
  const resolved = await resolveTemplate(projectRoot, name);
100188
100255
  if (!resolved) {
100189
100256
  console.error(source_default.red(`\u2717 Template not found: ${name}`));
@@ -100269,10 +100336,10 @@ function printRunResult(result, options2) {
100269
100336
  }
100270
100337
  var createCommand4 = new Command("create").description("Create a new template scaffold").argument("<name>", "Template name").option("-d, --description <desc>", "Template description").action(async (name, options2) => {
100271
100338
  try {
100272
- const projectRoot = getProjectRoot3();
100339
+ const projectRoot = getProjectRoot4();
100273
100340
  const templatesDir = await ensureTemplatesDir(projectRoot);
100274
- const templateDir = join39(templatesDir, name);
100275
- if (existsSync34(templateDir)) {
100341
+ const templateDir = join40(templatesDir, name);
100342
+ if (existsSync35(templateDir)) {
100276
100343
  console.error(source_default.red(`\u2717 Template "${name}" already exists`));
100277
100344
  process.exit(1);
100278
100345
  }
@@ -100303,7 +100370,7 @@ messages:
100303
100370
  success: |
100304
100371
  \u2713 Created {{name}}!
100305
100372
  `;
100306
- await writeFile18(join39(templateDir, "_template.yaml"), configContent, "utf-8");
100373
+ await writeFile18(join40(templateDir, "_template.yaml"), configContent, "utf-8");
100307
100374
  const exampleTemplate = `/**
100308
100375
  * {{pascalCase name}}
100309
100376
  * Generated from ${name} template
@@ -100313,10 +100380,10 @@ export function {{camelCase name}}() {
100313
100380
  console.log("Hello from {{name}}!");
100314
100381
  }
100315
100382
  `;
100316
- await writeFile18(join39(templateDir, "example.ts.hbs"), exampleTemplate, "utf-8");
100383
+ await writeFile18(join40(templateDir, "example.ts.hbs"), exampleTemplate, "utf-8");
100317
100384
  console.log();
100318
100385
  console.log(source_default.green(`\u2713 Created template: ${name}`));
100319
- console.log(source_default.gray(` Location: ${TEMPLATES_DIR4}/${name}/`));
100386
+ console.log(source_default.gray(` Location: ${TEMPLATES_DIR3}/${name}/`));
100320
100387
  console.log();
100321
100388
  console.log(source_default.cyan("Files created:"));
100322
100389
  console.log(source_default.gray(" - _template.yaml (config)"));
@@ -100334,7 +100401,7 @@ export function {{camelCase name}}() {
100334
100401
  });
100335
100402
  var viewCommand3 = new Command("view").description("View template details").argument("<name>", "Template name (supports import prefix, e.g., 'knowns/component')").option("--plain", "Plain text output for AI").action(async (name, options2) => {
100336
100403
  try {
100337
- const projectRoot = getProjectRoot3();
100404
+ const projectRoot = getProjectRoot4();
100338
100405
  const resolved = await resolveTemplate(projectRoot, name);
100339
100406
  if (!resolved) {
100340
100407
  console.error(source_default.red(`\u2717 Template not found: ${name}`));
@@ -100464,11 +100531,11 @@ templateCommand.argument("[name]", "Template name (shorthand for view)").option(
100464
100531
  });
100465
100532
 
100466
100533
  // src/commands/skill.ts
100467
- import { existsSync as existsSync35 } from "node:fs";
100534
+ import { existsSync as existsSync36 } from "node:fs";
100468
100535
  import { mkdir as mkdir20, writeFile as writeFile19 } from "node:fs/promises";
100469
- import { join as join40 } from "node:path";
100536
+ import { join as join41 } from "node:path";
100470
100537
  var SKILLS_DIR = ".knowns/skills";
100471
- function getProjectRoot4() {
100538
+ function getProjectRoot5() {
100472
100539
  const projectRoot = findProjectRoot();
100473
100540
  if (!projectRoot) {
100474
100541
  console.error(source_default.red("\u2717 Not a knowns project"));
@@ -100478,11 +100545,11 @@ function getProjectRoot4() {
100478
100545
  return projectRoot;
100479
100546
  }
100480
100547
  function getSkillsDir(projectRoot) {
100481
- return join40(projectRoot, SKILLS_DIR);
100548
+ return join41(projectRoot, SKILLS_DIR);
100482
100549
  }
100483
100550
  async function ensureSkillsDir(projectRoot) {
100484
100551
  const skillsDir = getSkillsDir(projectRoot);
100485
- if (!existsSync35(skillsDir)) {
100552
+ if (!existsSync36(skillsDir)) {
100486
100553
  await mkdir20(skillsDir, { recursive: true });
100487
100554
  }
100488
100555
  return skillsDir;
@@ -100490,9 +100557,9 @@ async function ensureSkillsDir(projectRoot) {
100490
100557
  var skillCommand = new Command("skill").description("Manage AI skills").enablePositionalOptions();
100491
100558
  var listCommand5 = new Command("list").description("List available skills").option("--plain", "Plain text output for AI").action(async (options2) => {
100492
100559
  try {
100493
- const projectRoot = getProjectRoot4();
100560
+ const projectRoot = getProjectRoot5();
100494
100561
  const skillsDir = getSkillsDir(projectRoot);
100495
- if (!existsSync35(skillsDir)) {
100562
+ if (!existsSync36(skillsDir)) {
100496
100563
  if (options2.plain) {
100497
100564
  console.log("No skills found");
100498
100565
  } else {
@@ -100534,10 +100601,10 @@ var listCommand5 = new Command("list").description("List available skills").opti
100534
100601
  });
100535
100602
  var createCommand5 = new Command("create").description("Create a new skill").argument("<name>", "Skill name").option("-d, --description <desc>", "Skill description").action(async (name, options2) => {
100536
100603
  try {
100537
- const projectRoot = getProjectRoot4();
100604
+ const projectRoot = getProjectRoot5();
100538
100605
  const skillsDir = await ensureSkillsDir(projectRoot);
100539
- const skillDir = join40(skillsDir, name);
100540
- if (existsSync35(skillDir)) {
100606
+ const skillDir = join41(skillsDir, name);
100607
+ if (existsSync36(skillDir)) {
100541
100608
  console.error(source_default.red(`\u2717 Skill "${name}" already exists`));
100542
100609
  process.exit(1);
100543
100610
  }
@@ -100568,7 +100635,7 @@ Describe when this skill should be used.
100568
100635
  knowns task list
100569
100636
  \`\`\`
100570
100637
  `;
100571
- await writeFile19(join40(skillDir, "SKILL.md"), skillContent, "utf-8");
100638
+ await writeFile19(join41(skillDir, "SKILL.md"), skillContent, "utf-8");
100572
100639
  console.log();
100573
100640
  console.log(source_default.green(`\u2713 Created skill: ${name}`));
100574
100641
  console.log(source_default.gray(` Location: ${SKILLS_DIR}/${name}/SKILL.md`));
@@ -100584,7 +100651,7 @@ knowns task list
100584
100651
  });
100585
100652
  var viewCommand4 = new Command("view").description("View skill details").argument("<name>", "Skill name").option("--plain", "Plain text output for AI").action(async (name, options2) => {
100586
100653
  try {
100587
- const projectRoot = getProjectRoot4();
100654
+ const projectRoot = getProjectRoot5();
100588
100655
  const skillsDir = getSkillsDir(projectRoot);
100589
100656
  const skill = await loadSkillByName(skillsDir, name);
100590
100657
  if (!skill) {
@@ -100618,9 +100685,9 @@ var viewCommand4 = new Command("view").description("View skill details").argumen
100618
100685
  });
100619
100686
  var syncCommand2 = new Command("sync").description("Sync skills to AI platforms").option("-p, --platform <platforms>", "Platforms to sync (comma-separated)").option("-f, --force", "Force overwrite existing files").option("--dry-run", "Preview without writing files").option("--plain", "Plain text output for AI").action(async (options2) => {
100620
100687
  try {
100621
- const projectRoot = getProjectRoot4();
100688
+ const projectRoot = getProjectRoot5();
100622
100689
  const skillsDir = getSkillsDir(projectRoot);
100623
- if (!existsSync35(skillsDir)) {
100690
+ if (!existsSync36(skillsDir)) {
100624
100691
  console.error(source_default.red("\u2717 No skills directory found"));
100625
100692
  console.error(source_default.gray(` Create skills in ${SKILLS_DIR}/`));
100626
100693
  process.exit(1);
@@ -100699,14 +100766,14 @@ var syncCommand2 = new Command("sync").description("Sync skills to AI platforms"
100699
100766
  });
100700
100767
  var statusCommand2 = new Command("status").description("Check skill sync status").option("--plain", "Plain text output for AI").action(async (options2) => {
100701
100768
  try {
100702
- const projectRoot = getProjectRoot4();
100769
+ const projectRoot = getProjectRoot5();
100703
100770
  const skillsDir = getSkillsDir(projectRoot);
100704
- const skills = existsSync35(skillsDir) ? await listSkills(skillsDir) : [];
100771
+ const skills = existsSync36(skillsDir) ? await listSkills(skillsDir) : [];
100705
100772
  if (options2.plain) {
100706
100773
  console.log(`Skills: ${skills.length}`);
100707
100774
  for (const platform of PLATFORMS) {
100708
- const targetPath = join40(projectRoot, platform.targetDir);
100709
- const exists = existsSync35(targetPath);
100775
+ const targetPath = join41(projectRoot, platform.targetDir);
100776
+ const exists = existsSync36(targetPath);
100710
100777
  console.log(`${platform.name}: ${exists ? "present" : "not found"}`);
100711
100778
  }
100712
100779
  } else {
@@ -100716,8 +100783,8 @@ var statusCommand2 = new Command("status").description("Check skill sync status"
100716
100783
  console.log(source_default.bold("Platforms:"));
100717
100784
  console.log(source_default.gray("\u2500".repeat(50)));
100718
100785
  for (const platform of PLATFORMS) {
100719
- const targetPath = join40(projectRoot, platform.targetDir);
100720
- const exists = existsSync35(targetPath);
100786
+ const targetPath = join41(projectRoot, platform.targetDir);
100787
+ const exists = existsSync36(targetPath);
100721
100788
  const status = exists ? source_default.green("\u2713 Present") : source_default.gray("\u25CB Not synced");
100722
100789
  console.log(` ${platform.name.padEnd(15)} ${platform.targetDir.padEnd(20)} ${status}`);
100723
100790
  }
@@ -100744,7 +100811,7 @@ skillCommand.argument("[name]", "Skill name (shorthand for view)").option("--pla
100744
100811
  });
100745
100812
 
100746
100813
  // src/commands/import.ts
100747
- function getProjectRoot5() {
100814
+ function getProjectRoot6() {
100748
100815
  const projectRoot = findProjectRoot();
100749
100816
  if (!projectRoot) {
100750
100817
  console.error(source_default.red("\u2717 Not a knowns project"));
@@ -100818,7 +100885,7 @@ var importCommand = new Command("import").description("Import templates and docs
100818
100885
  var addCommand2 = new Command("add").description("Import from a source (git, npm, or local path)").argument("<source>", "Source to import (git URL, npm package, or local path)").option("-n, --name <name>", "Custom name for the import").option("-t, --type <type>", "Source type: git, npm, or local").option("-r, --ref <ref>", "Git branch/tag or npm version").option("--include <patterns...>", "Include only these file patterns").option("--exclude <patterns...>", "Exclude these file patterns").option("--link", "Create symlink for local imports (instead of copying)").option("-f, --force", "Overwrite existing import").option("--dry-run", "Preview without importing").option("--plain", "Plain text output for AI").action(
100819
100886
  async (source, options2) => {
100820
100887
  try {
100821
- const projectRoot = getProjectRoot5();
100888
+ const projectRoot = getProjectRoot6();
100822
100889
  if (!options2.plain && !options2.dryRun) {
100823
100890
  console.log(source_default.cyan(`
100824
100891
  Importing from: ${source}
@@ -100854,7 +100921,7 @@ Importing from: ${source}
100854
100921
  );
100855
100922
  var listCommand6 = new Command("list").description("List imported sources").option("--plain", "Plain text output for AI").action(async (options2) => {
100856
100923
  try {
100857
- const projectRoot = getProjectRoot5();
100924
+ const projectRoot = getProjectRoot6();
100858
100925
  const imports = await getImportsWithMetadata(projectRoot);
100859
100926
  if (imports.length === 0) {
100860
100927
  if (options2.plain) {
@@ -100906,7 +100973,7 @@ var listCommand6 = new Command("list").description("List imported sources").opti
100906
100973
  var syncCommand3 = new Command("sync").description("Sync imports from their sources").argument("[name]", "Import name to sync (syncs all if not specified)").option("-f, --force", "Force overwrite locally modified files").option("--dry-run", "Preview without syncing").option("--plain", "Plain text output for AI").action(
100907
100974
  async (name, options2) => {
100908
100975
  try {
100909
- const projectRoot = getProjectRoot5();
100976
+ const projectRoot = getProjectRoot6();
100910
100977
  if (name) {
100911
100978
  if (!options2.plain && !options2.dryRun) {
100912
100979
  console.log(source_default.cyan(`
@@ -100967,7 +101034,7 @@ Syncing: ${name}
100967
101034
  var removeCommand = new Command("remove").description("Remove an imported source").argument("<name>", "Import name to remove").option("--delete", "Also delete imported files").option("--plain", "Plain text output for AI").action(
100968
101035
  async (name, options2) => {
100969
101036
  try {
100970
- const projectRoot = getProjectRoot5();
101037
+ const projectRoot = getProjectRoot6();
100971
101038
  const result = await removeImport(projectRoot, name, options2.delete);
100972
101039
  if (options2.plain) {
100973
101040
  console.log(`Removed: ${name}`);
@@ -101020,10 +101087,10 @@ importCommand.argument("[source]", "Source to import (shorthand for 'import add'
101020
101087
  });
101021
101088
 
101022
101089
  // src/utils/update-notifier.ts
101023
- import { existsSync as existsSync36, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
101090
+ import { existsSync as existsSync37, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
101024
101091
  import { mkdir as mkdir21 } from "node:fs/promises";
101025
- import { homedir as homedir2 } from "node:os";
101026
- import { dirname as dirname8, join as join41 } from "node:path";
101092
+ import { homedir as homedir3 } from "node:os";
101093
+ import { dirname as dirname8, join as join42 } from "node:path";
101027
101094
  var DEFAULT_TTL_MS = 60 * 60 * 1e3;
101028
101095
  var DEFAULT_TIMEOUT_MS = 2e3;
101029
101096
  var hasNotifiedThisProcess = false;
@@ -101037,10 +101104,10 @@ function detectPackageManager(cwd) {
101037
101104
  if (ua.startsWith("yarn/")) return "yarn";
101038
101105
  if (ua.startsWith("bun/")) return "bun";
101039
101106
  if (ua.startsWith("npm/")) return "npm";
101040
- if (existsSync36(join41(cwd, "pnpm-lock.yaml"))) return "pnpm";
101041
- if (existsSync36(join41(cwd, "yarn.lock"))) return "yarn";
101042
- if (existsSync36(join41(cwd, "bun.lock"))) return "bun";
101043
- if (existsSync36(join41(cwd, "package-lock.json"))) return "npm";
101107
+ if (existsSync37(join42(cwd, "pnpm-lock.yaml"))) return "pnpm";
101108
+ if (existsSync37(join42(cwd, "yarn.lock"))) return "yarn";
101109
+ if (existsSync37(join42(cwd, "bun.lock"))) return "bun";
101110
+ if (existsSync37(join42(cwd, "package-lock.json"))) return "npm";
101044
101111
  return "npm";
101045
101112
  }
101046
101113
  function compareVersions(a, b) {
@@ -101064,7 +101131,7 @@ function shouldSkip(args2, force) {
101064
101131
  }
101065
101132
  function getGlobalCachePath(explicit) {
101066
101133
  if (explicit) return explicit;
101067
- return join41(homedir2(), ".knowns", "cli-cache.json");
101134
+ return join42(homedir3(), ".knowns", "cli-cache.json");
101068
101135
  }
101069
101136
  function readCache(cachePath) {
101070
101137
  try {
@@ -101080,7 +101147,7 @@ function readCache(cachePath) {
101080
101147
  }
101081
101148
  async function writeCache(cachePath, data) {
101082
101149
  const dir = dirname8(cachePath);
101083
- if (dir && !existsSync36(dir)) {
101150
+ if (dir && !existsSync37(dir)) {
101084
101151
  await mkdir21(dir, { recursive: true });
101085
101152
  }
101086
101153
  writeFileSync3(cachePath, JSON.stringify(data, null, 2), "utf-8");
@@ -101149,7 +101216,7 @@ async function notifyCliUpdate(options2) {
101149
101216
  // package.json
101150
101217
  var package_default = {
101151
101218
  name: "knowns",
101152
- version: "0.10.5",
101219
+ version: "0.10.6",
101153
101220
  description: "AI-native task and documentation management for dev teams",
101154
101221
  module: "index.ts",
101155
101222
  type: "module",
@@ -101315,7 +101382,6 @@ program2.addCommand(timeCommand);
101315
101382
  program2.addCommand(docCommand);
101316
101383
  program2.addCommand(configCommand);
101317
101384
  program2.addCommand(syncCommand);
101318
- program2.addCommand(agentsCommand);
101319
101385
  program2.addCommand(mcpCommand);
101320
101386
  program2.addCommand(templateCommand);
101321
101387
  program2.addCommand(skillCommand);