@c4a/context-cli 0.7.25 → 0.7.29

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.
Files changed (27) hide show
  1. package/cli.js +59 -41
  2. package/indexers/contracts/profile-contract.json +245 -245
  3. package/indexers/release-manifest.json +1 -1
  4. package/package.json +12 -12
  5. package/parserEntryWorker.js +90 -10
  6. package/plugins/README.md +5 -5
  7. package/plugins/README_CN.md +4 -4
  8. package/plugins/VERSION +1 -1
  9. package/plugins/claude/.claude-plugin/plugin.json +3 -2
  10. package/plugins/claude/commands/context-inspect-search.md +45 -10
  11. package/plugins/claude/skills/context-inspect-search/SKILL.md +182 -0
  12. package/plugins/claude/skills/context-inspect-search/agents/openai.yaml +2 -0
  13. package/plugins/codex/.codex-plugin/plugin.json +2 -2
  14. package/plugins/codex/skills/context-inspect-search/SKILL.md +45 -11
  15. package/plugins/codex/skills/context-inspect-search/agents/openai.yaml +1 -1
  16. package/plugins/cursor/.cursor-plugin/plugin.json +3 -2
  17. package/plugins/cursor/commands/c4a-context-inspect-search.md +45 -10
  18. package/plugins/cursor/skills/context-inspect-search/SKILL.md +182 -0
  19. package/plugins/cursor/skills/context-inspect-search/agents/openai.yaml +2 -0
  20. package/plugins/skills/context-inspect-search/SKILL.md +45 -11
  21. package/plugins/skills/context-inspect-search/agents/openai.yaml +1 -1
  22. package/providers/context/graphs/indexer.yaml +4 -0
  23. package/providers/context/manifest.json +17 -8
  24. package/providers/context/provider.yaml +1 -1
  25. package/providers/context/resources/procedures/document-code-investigation.md +45 -0
  26. package/providers/context/resources/procedures/repository-source-recovery.md +8 -1
  27. package/providers/context/skills/work-production-stage/SKILL.md +4 -0
package/cli.js CHANGED
@@ -76780,22 +76780,14 @@ var init_indexerSourceBoundary = __esm(() => {
76780
76780
 
76781
76781
  // src/project/indexerParserSourceMaterialization.ts
76782
76782
  import { execFile as execFile3 } from "node:child_process";
76783
- import { lstat as lstat4, readFile as readFile18 } from "node:fs/promises";
76783
+ import { lstat as lstat4, readFile as readFile18, stat as stat6 } from "node:fs/promises";
76784
76784
  import { promisify as promisify3 } from "node:util";
76785
76785
  import { basename as basename4, extname as extname8, join as join17 } from "node:path";
76786
76786
  function sourceRefName(sourceRef) {
76787
76787
  return sourceRef.startsWith("repo:") ? sourceRef.slice("repo:".length) : null;
76788
76788
  }
76789
76789
  async function trackedPaths(root, ref2) {
76790
- try {
76791
- await execFileAsync2("git", ["diff", "--quiet", ref2, "--", "."], { cwd: root });
76792
- } catch (error) {
76793
- const exitCode = error !== null && typeof error === "object" && "code" in error ? error.code : null;
76794
- if (exitCode === 1) {
76795
- throw new TypeError(`materialized repository source differs from its pinned ref: ${root}`);
76796
- }
76797
- throw error;
76798
- }
76790
+ await assertPinnedSource(root, ref2);
76799
76791
  const { stdout } = await execFileAsync2("git", ["ls-files", "-z", "--", "."], {
76800
76792
  cwd: root,
76801
76793
  encoding: "buffer",
@@ -76804,6 +76796,20 @@ async function trackedPaths(root, ref2) {
76804
76796
  return Buffer.from(stdout).toString("utf8").split("\x00").filter(Boolean).sort();
76805
76797
  }
76806
76798
  async function assertPinnedSource(root, ref2) {
76799
+ const sourceStat = await stat6(root).catch((error) => {
76800
+ if (error.code === "ENOENT" || error.code === "ENOTDIR")
76801
+ return;
76802
+ throw error;
76803
+ });
76804
+ if (!sourceStat?.isDirectory()) {
76805
+ throw new ContextError(ExitCode.WorkspaceStateError, `Repository source directory is unavailable: ${root}. Inspect recovery with context source recovery-plan --format json.`, {
76806
+ category: ErrorCategory.WorkspaceStateInvalid,
76807
+ reason_code: "repository-source-directory-unavailable",
76808
+ cwd: root,
76809
+ next_action: { command: "context source recovery-plan --format json" },
76810
+ input_schema: { type: "object", properties: {}, additionalProperties: false }
76811
+ });
76812
+ }
76807
76813
  try {
76808
76814
  await execFileAsync2("git", ["diff", "--quiet", ref2, "--", "."], { cwd: root });
76809
76815
  } catch (error) {
@@ -76811,6 +76817,15 @@ async function assertPinnedSource(root, ref2) {
76811
76817
  if (exitCode === 1) {
76812
76818
  throw new TypeError(`materialized repository source differs from its pinned ref: ${root}`);
76813
76819
  }
76820
+ if (exitCode === "ENOENT") {
76821
+ throw new ContextError(ExitCode.ExternalToolError, `Git could not start for repository source ${root}. Check git --version and the source directory in the same host environment.`, {
76822
+ category: ErrorCategory.ExternalToolFailed,
76823
+ reason_code: "repository-git-spawn-unavailable",
76824
+ cwd: root,
76825
+ next_action: { command: "git --version" },
76826
+ input_schema: { type: "object", properties: {}, additionalProperties: false }
76827
+ });
76828
+ }
76814
76829
  throw error;
76815
76830
  }
76816
76831
  }
@@ -76874,6 +76889,9 @@ var init_indexerParserSourceMaterialization = __esm(() => {
76874
76889
  init_src2();
76875
76890
  init_indexerReadScopeAuthorization();
76876
76891
  init_indexerSourceBoundary();
76892
+ init_errors3();
76893
+ init_exitCode();
76894
+ init_cliFeedback();
76877
76895
  execFileAsync2 = promisify3(execFile3);
76878
76896
  });
76879
76897
 
@@ -76882,7 +76900,7 @@ var exports_managedDocumentSnapshot = {};
76882
76900
  __export(exports_managedDocumentSnapshot, {
76883
76901
  readManagedDocumentSnapshot: () => readManagedDocumentSnapshot
76884
76902
  });
76885
- import { readFile as readFile19, stat as stat6 } from "node:fs/promises";
76903
+ import { readFile as readFile19, stat as stat7 } from "node:fs/promises";
76886
76904
  import { basename as basename5, dirname as dirname15 } from "node:path";
76887
76905
  async function readManagedDocumentSnapshot(projectRoot, type, name2) {
76888
76906
  const absolutePath = await assertManagedDocumentPath(projectRoot, type, name2);
@@ -76891,7 +76909,7 @@ async function readManagedDocumentSnapshot(projectRoot, type, name2) {
76891
76909
  const manifest = createDocumentSnapshotManifest({
76892
76910
  sourceType: type,
76893
76911
  sourceName: name2,
76894
- capturedAt: (await stat6(absolutePath)).mtime.toISOString(),
76912
+ capturedAt: (await stat7(absolutePath)).mtime.toISOString(),
76895
76913
  files: [{
76896
76914
  path: file,
76897
76915
  bytes: markdown,
@@ -79423,7 +79441,7 @@ __export(exports_productionStageStore, {
79423
79441
  PRODUCTION_STAGES_ROOT: () => PRODUCTION_STAGES_ROOT
79424
79442
  });
79425
79443
  import { constants as constants4 } from "node:fs";
79426
- import { readFile as readFile28, access as access2, stat as stat7 } from "node:fs/promises";
79444
+ import { readFile as readFile28, access as access2, stat as stat8 } from "node:fs/promises";
79427
79445
  import { join as join31 } from "node:path";
79428
79446
  function productionStageDirectory(id3) {
79429
79447
  productionAgentDirectory(id3);
@@ -79442,7 +79460,7 @@ async function readOptional(root, path2) {
79442
79460
  async function hasReadableProjection(root, path2) {
79443
79461
  const absolute = await safeProjectTarget(root, path2);
79444
79462
  try {
79445
- if (!(await stat7(absolute)).isFile())
79463
+ if (!(await stat8(absolute)).isFile())
79446
79464
  throw new TypeError(`Stage material must be a regular file: ${path2}`);
79447
79465
  await access2(absolute, constants4.R_OK);
79448
79466
  return true;
@@ -81693,19 +81711,19 @@ function failure(reason, message, next) {
81693
81711
  }
81694
81712
  async function entries(root, path2) {
81695
81713
  await safeProjectTarget(root, path2);
81696
- let stat8;
81714
+ let stat9;
81697
81715
  try {
81698
- stat8 = await lstat7(join43(root, path2));
81716
+ stat9 = await lstat7(join43(root, path2));
81699
81717
  } catch (error) {
81700
81718
  if (error.code === "ENOENT")
81701
81719
  return [];
81702
81720
  throw error;
81703
81721
  }
81704
- if (stat8.isSymbolicLink())
81722
+ if (stat9.isSymbolicLink())
81705
81723
  failure("preparation-symlink", `Refusing to clean linked task state: ${path2}`, "Inspect and relocate the link without deleting its target, then preview again.");
81706
- if (stat8.isFile())
81724
+ if (stat9.isFile())
81707
81725
  return [path2];
81708
- if (!stat8.isDirectory())
81726
+ if (!stat9.isDirectory())
81709
81727
  failure("preparation-file-type", `Unsupported task-state file: ${path2}`, "Inspect this file before preparing the workspace.");
81710
81728
  const result = [];
81711
81729
  for (const name3 of (await readdir10(join43(root, path2))).sort())
@@ -86351,7 +86369,7 @@ var init_packageSiteExtensions = __esm(() => {
86351
86369
  // src/project/packageSite.ts
86352
86370
  import { createHash as createHash17 } from "node:crypto";
86353
86371
  import { spawn as spawn3 } from "node:child_process";
86354
- import { mkdir as mkdir23, mkdtemp as mkdtemp2, readFile as readFile52, writeFile as writeFile19, rm as rm12, symlink as symlink2, cp, access as access5, stat as stat8 } from "node:fs/promises";
86372
+ import { mkdir as mkdir23, mkdtemp as mkdtemp2, readFile as readFile52, writeFile as writeFile19, rm as rm12, symlink as symlink2, cp, access as access5, stat as stat9 } from "node:fs/promises";
86355
86373
  import { createRequire as createRequire5 } from "node:module";
86356
86374
  import { dirname as dirname28, join as join64, posix as posix6 } from "node:path";
86357
86375
  function sitePagePath(identity) {
@@ -86675,7 +86693,7 @@ title: LLM Docs
86675
86693
  const placeholder = [".css", ".js", ".mjs", ".cjs"].includes(extension2) ? `/* Intentionally empty. */
86676
86694
  ` : [".html", ".htm"].includes(extension2) ? `<!-- Intentionally empty. -->
86677
86695
  ` : null;
86678
- if (placeholder !== null && (await stat8(file.absPath)).size === 0) {
86696
+ if (placeholder !== null && (await stat9(file.absPath)).size === 0) {
86679
86697
  await writeFile19(file.absPath, placeholder);
86680
86698
  }
86681
86699
  }
@@ -89996,7 +90014,7 @@ var init_sourceInputMutation = __esm(() => {
89996
90014
 
89997
90015
  // src/project/documentCapture.ts
89998
90016
  import { createHash as createHash21 } from "node:crypto";
89999
- import { mkdir as mkdir28, readdir as readdir18, readFile as readFile63, rm as rm17, stat as stat9, writeFile as writeFile23 } from "node:fs/promises";
90017
+ import { mkdir as mkdir28, readdir as readdir18, readFile as readFile63, rm as rm17, stat as stat10, writeFile as writeFile23 } from "node:fs/promises";
90000
90018
  import { basename as basename8, dirname as dirname34, extname as extname12, join as join75, relative as relative22, resolve as resolve24 } from "node:path";
90001
90019
  function toPosixPath7(path2) {
90002
90020
  return path2.split(/[\\/]+/u).filter((part) => part.length > 0).join("/");
@@ -90101,7 +90119,7 @@ function assignFlatSnapshotPaths(files, module) {
90101
90119
  });
90102
90120
  }
90103
90121
  async function walkMarkdownFiles(input) {
90104
- const rootStat = await stat9(input.localRoot);
90122
+ const rootStat = await stat10(input.localRoot);
90105
90123
  if (rootStat.isFile()) {
90106
90124
  const sourcePath = normalizeSnapshotRelativePath(basename8(input.localRoot));
90107
90125
  return {
@@ -99938,15 +99956,15 @@ import { join as join100 } from "node:path";
99938
99956
  import { createHash as createHash30, randomUUID as randomUUID7 } from "node:crypto";
99939
99957
  async function inspectWriterLock(root2) {
99940
99958
  const path3 = await safeProjectTarget(root2, lockRelative);
99941
- let stat10;
99959
+ let stat11;
99942
99960
  try {
99943
- stat10 = await lstat10(path3);
99961
+ stat11 = await lstat10(path3);
99944
99962
  } catch (error) {
99945
99963
  if (error.code === "ENOENT")
99946
99964
  return null;
99947
99965
  throw error;
99948
99966
  }
99949
- if (!stat10.isDirectory() || stat10.isSymbolicLink())
99967
+ if (!stat11.isDirectory() || stat11.isSymbolicLink())
99950
99968
  throw new Error("Writer lock must be a real directory.");
99951
99969
  const ownerPath = await safeProjectTarget(root2, `${lockRelative}/owner.json`);
99952
99970
  const bytes = await readFile82(ownerPath, "utf8");
@@ -99961,7 +99979,7 @@ async function inspectWriterLock(root2) {
99961
99979
  const code3 = error.code;
99962
99980
  processState = code3 === "ESRCH" ? "not-running" : code3 === "EPERM" ? "running" : "unknown";
99963
99981
  }
99964
- const digest6 = `sha256:${createHash30("sha256").update(`${stat10.dev}:${stat10.ino}:${stat10.birthtimeMs}:${bytes}`).digest("hex")}`;
99982
+ const digest6 = `sha256:${createHash30("sha256").update(`${stat11.dev}:${stat11.ino}:${stat11.birthtimeMs}:${bytes}`).digest("hex")}`;
99965
99983
  return { ...owner, process_state: processState, digest: digest6, path: lockRelative };
99966
99984
  }
99967
99985
  async function recoverWriterLock(input) {
@@ -100033,22 +100051,22 @@ async function recoveryJournals(root2) {
100033
100051
  const entries2 = [];
100034
100052
  async function visit4(path3, depth) {
100035
100053
  await safeProjectTarget(root2, path3);
100036
- let stat10;
100054
+ let stat11;
100037
100055
  try {
100038
- stat10 = await lstat11(join101(root2, path3));
100056
+ stat11 = await lstat11(join101(root2, path3));
100039
100057
  } catch (error) {
100040
100058
  if (error.code === "ENOENT")
100041
100059
  return;
100042
100060
  throw error;
100043
100061
  }
100044
- if (stat10.isSymbolicLink())
100062
+ if (stat11.isSymbolicLink())
100045
100063
  throw new TypeError("Recovery does not follow transaction symlinks.");
100046
- if (stat10.isDirectory()) {
100064
+ if (stat11.isDirectory()) {
100047
100065
  if (depth > 3)
100048
100066
  throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
100049
100067
  for (const name3 of (await readdir25(join101(root2, path3))).sort())
100050
100068
  await visit4(`${path3}/${name3}`, depth + 1);
100051
- } else if (stat10.isFile())
100069
+ } else if (stat11.isFile())
100052
100070
  entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
100053
100071
  }
100054
100072
  await visit4(TRANSACTIONS_PATH, 0);
@@ -112531,7 +112549,7 @@ function conflict(path3) {
112531
112549
  next: "Choose another --local directory, or move conflicting/customized skills aside before retrying."
112532
112550
  });
112533
112551
  }
112534
- async function stat10(path3) {
112552
+ async function stat11(path3) {
112535
112553
  try {
112536
112554
  return await lstat14(path3);
112537
112555
  } catch (error) {
@@ -112541,7 +112559,7 @@ async function stat10(path3) {
112541
112559
  }
112542
112560
  }
112543
112561
  async function checkParents(path3) {
112544
- const entry = await stat10(path3);
112562
+ const entry = await stat11(path3);
112545
112563
  if (entry && (!entry.isDirectory() || entry.isSymbolicLink()))
112546
112564
  conflict(path3);
112547
112565
  const parent = dirname46(path3);
@@ -112600,11 +112618,11 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112600
112618
  const target = join112(commandsRoot, entry.name);
112601
112619
  const marker = join112(commandsRoot, `.context-${entry.name}.json`);
112602
112620
  for (const file of [target, marker]) {
112603
- const existing = await stat10(file);
112621
+ const existing = await stat11(file);
112604
112622
  if (existing && (!existing.isFile() || existing.isSymbolicLink()))
112605
112623
  conflict(file);
112606
112624
  }
112607
- if (await stat10(target)) {
112625
+ if (await stat11(target)) {
112608
112626
  let previous3;
112609
112627
  try {
112610
112628
  previous3 = JSON.parse(await readFile94(marker, "utf8"));
@@ -112614,7 +112632,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112614
112632
  const current2 = createHash34("sha256").update(await readFile94(target)).digest("hex");
112615
112633
  if (previous3?.owner !== "context-plugin-local" || previous3.digest !== current2)
112616
112634
  conflict(target);
112617
- } else if (await stat10(marker))
112635
+ } else if (await stat11(marker))
112618
112636
  conflict(marker);
112619
112637
  commandPlans.push({ name: entry.name, target, marker, content: content3, hash: createHash34("sha256").update(content3).digest("hex") });
112620
112638
  }
@@ -112623,21 +112641,21 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112623
112641
  }
112624
112642
  const plans = [];
112625
112643
  for (const entry of (await readdir29(sourceRoot2, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
112626
- if (!entry.isDirectory() || !await stat10(join112(sourceRoot2, entry.name, "SKILL.md")))
112644
+ if (!entry.isDirectory() || !await stat11(join112(sourceRoot2, entry.name, "SKILL.md")))
112627
112645
  continue;
112628
112646
  const source2 = join112(sourceRoot2, entry.name);
112629
112647
  const target = join112(skillsRoot, entry.name);
112630
112648
  if (commandEntries.has(entry.name)) {
112631
- if (await stat10(target))
112649
+ if (await stat11(target))
112632
112650
  conflict(`${target} (use a fresh host directory to avoid duplicate command/skill entries)`);
112633
112651
  continue;
112634
112652
  }
112635
- const existing = await stat10(target);
112653
+ const existing = await stat11(target);
112636
112654
  if (existing) {
112637
112655
  if (!existing.isDirectory() || existing.isSymbolicLink())
112638
112656
  conflict(target);
112639
112657
  const markerPath = join112(target, MARKER);
112640
- if (!(await stat10(markerPath))?.isFile())
112658
+ if (!(await stat11(markerPath))?.isFile())
112641
112659
  conflict(target);
112642
112660
  let marker;
112643
112661
  try {