@askexenow/exe-os 0.9.69 → 0.9.70

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 (75) hide show
  1. package/deploy/stack-manifests/v0.9.json +96 -16
  2. package/dist/bin/agentic-ontology-backfill.js +6 -0
  3. package/dist/bin/agentic-reflection-backfill.js +6 -0
  4. package/dist/bin/agentic-semantic-label.js +6 -0
  5. package/dist/bin/backfill-conversations.js +6 -0
  6. package/dist/bin/backfill-responses.js +6 -0
  7. package/dist/bin/backfill-vectors.js +6 -0
  8. package/dist/bin/bulk-sync-postgres.js +6 -0
  9. package/dist/bin/cleanup-stale-review-tasks.js +6 -0
  10. package/dist/bin/cli.js +1257 -178
  11. package/dist/bin/exe-agent.js +6 -0
  12. package/dist/bin/exe-assign.js +6 -0
  13. package/dist/bin/exe-boot.js +6 -0
  14. package/dist/bin/exe-call.js +6 -0
  15. package/dist/bin/exe-cloud.js +6 -0
  16. package/dist/bin/exe-dispatch.js +6 -0
  17. package/dist/bin/exe-doctor.js +6 -0
  18. package/dist/bin/exe-export-behaviors.js +6 -0
  19. package/dist/bin/exe-forget.js +6 -0
  20. package/dist/bin/exe-gateway.js +151 -110
  21. package/dist/bin/exe-heartbeat.js +6 -0
  22. package/dist/bin/exe-kill.js +6 -0
  23. package/dist/bin/exe-launch-agent.js +6 -0
  24. package/dist/bin/exe-new-employee.js +6 -0
  25. package/dist/bin/exe-pending-messages.js +6 -0
  26. package/dist/bin/exe-pending-notifications.js +6 -0
  27. package/dist/bin/exe-pending-reviews.js +6 -0
  28. package/dist/bin/exe-rename.js +13 -4
  29. package/dist/bin/exe-review.js +6 -0
  30. package/dist/bin/exe-search.js +6 -0
  31. package/dist/bin/exe-session-cleanup.js +6 -0
  32. package/dist/bin/exe-start-codex.js +6 -0
  33. package/dist/bin/exe-start-opencode.js +6 -0
  34. package/dist/bin/exe-status.js +6 -0
  35. package/dist/bin/exe-team.js +6 -0
  36. package/dist/bin/git-sweep.js +6 -0
  37. package/dist/bin/graph-backfill.js +150 -110
  38. package/dist/bin/graph-export.js +6 -0
  39. package/dist/bin/intercom-check.js +6 -0
  40. package/dist/bin/registry-proxy.js +207 -0
  41. package/dist/bin/scan-tasks.js +6 -0
  42. package/dist/bin/setup.js +6 -0
  43. package/dist/bin/shard-migrate.js +6 -0
  44. package/dist/bin/stack-update.js +128 -0
  45. package/dist/gateway/index.js +151 -110
  46. package/dist/hooks/bug-report-worker.js +6 -0
  47. package/dist/hooks/codex-stop-task-finalizer.js +6 -0
  48. package/dist/hooks/commit-complete.js +6 -0
  49. package/dist/hooks/error-recall.js +6 -0
  50. package/dist/hooks/ingest.js +6 -0
  51. package/dist/hooks/instructions-loaded.js +6 -0
  52. package/dist/hooks/notification.js +6 -0
  53. package/dist/hooks/post-compact.js +6 -0
  54. package/dist/hooks/post-tool-combined.js +6 -0
  55. package/dist/hooks/pre-compact.js +6 -0
  56. package/dist/hooks/pre-tool-use.js +6 -0
  57. package/dist/hooks/prompt-submit.js +6 -0
  58. package/dist/hooks/session-end.js +6 -0
  59. package/dist/hooks/session-start.js +6 -0
  60. package/dist/hooks/stop.js +6 -0
  61. package/dist/hooks/subagent-stop.js +6 -0
  62. package/dist/hooks/summary-worker.js +6 -0
  63. package/dist/index.js +151 -110
  64. package/dist/lib/employee-templates.js +6 -0
  65. package/dist/lib/exe-daemon.js +382 -234
  66. package/dist/lib/hybrid-search.js +6 -0
  67. package/dist/lib/registry-proxy.js +162 -0
  68. package/dist/lib/schedules.js +6 -0
  69. package/dist/lib/store.js +6 -0
  70. package/dist/mcp/server.js +318 -222
  71. package/dist/runtime/index.js +6 -0
  72. package/dist/tui/App.js +6 -0
  73. package/package.json +3 -2
  74. package/stack.release.json +6 -4
  75. package/stack.release.schema.json +89 -18
@@ -4124,6 +4124,12 @@ var init_platform_procedures = __esm({
4124
4124
  priority: "p0",
4125
4125
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4126
4126
  },
4127
+ {
4128
+ title: "Code context first for repository orientation",
4129
+ domain: "workflow",
4130
+ priority: "p1",
4131
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
4132
+ },
4127
4133
  {
4128
4134
  title: "Commit discipline \u2014 never leave verified work floating",
4129
4135
  domain: "workflow",
@@ -4168,6 +4168,12 @@ var init_platform_procedures = __esm({
4168
4168
  priority: "p0",
4169
4169
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4170
4170
  },
4171
+ {
4172
+ title: "Code context first for repository orientation",
4173
+ domain: "workflow",
4174
+ priority: "p1",
4175
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
4176
+ },
4171
4177
  {
4172
4178
  title: "Commit discipline \u2014 never leave verified work floating",
4173
4179
  domain: "workflow",
@@ -3440,6 +3440,12 @@ var init_platform_procedures = __esm({
3440
3440
  priority: "p0",
3441
3441
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
3442
3442
  },
3443
+ {
3444
+ title: "Code context first for repository orientation",
3445
+ domain: "workflow",
3446
+ priority: "p1",
3447
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
3448
+ },
3443
3449
  {
3444
3450
  title: "Commit discipline \u2014 never leave verified work floating",
3445
3451
  domain: "workflow",
@@ -3440,6 +3440,12 @@ var init_platform_procedures = __esm({
3440
3440
  priority: "p0",
3441
3441
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
3442
3442
  },
3443
+ {
3444
+ title: "Code context first for repository orientation",
3445
+ domain: "workflow",
3446
+ priority: "p1",
3447
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
3448
+ },
3443
3449
  {
3444
3450
  title: "Commit discipline \u2014 never leave verified work floating",
3445
3451
  domain: "workflow",
@@ -4147,6 +4147,12 @@ var init_platform_procedures = __esm({
4147
4147
  priority: "p0",
4148
4148
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4149
4149
  },
4150
+ {
4151
+ title: "Code context first for repository orientation",
4152
+ domain: "workflow",
4153
+ priority: "p1",
4154
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
4155
+ },
4150
4156
  {
4151
4157
  title: "Commit discipline \u2014 never leave verified work floating",
4152
4158
  domain: "workflow",
@@ -4136,6 +4136,12 @@ var init_platform_procedures = __esm({
4136
4136
  priority: "p0",
4137
4137
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4138
4138
  },
4139
+ {
4140
+ title: "Code context first for repository orientation",
4141
+ domain: "workflow",
4142
+ priority: "p1",
4143
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
4144
+ },
4139
4145
  {
4140
4146
  title: "Commit discipline \u2014 never leave verified work floating",
4141
4147
  domain: "workflow",
@@ -7841,6 +7841,12 @@ var init_platform_procedures = __esm({
7841
7841
  priority: "p0",
7842
7842
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
7843
7843
  },
7844
+ {
7845
+ title: "Code context first for repository orientation",
7846
+ domain: "workflow",
7847
+ priority: "p1",
7848
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
7849
+ },
7844
7850
  {
7845
7851
  title: "Commit discipline \u2014 never leave verified work floating",
7846
7852
  domain: "workflow",
@@ -3353,6 +3353,12 @@ var init_platform_procedures = __esm({
3353
3353
  priority: "p0",
3354
3354
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
3355
3355
  },
3356
+ {
3357
+ title: "Code context first for repository orientation",
3358
+ domain: "workflow",
3359
+ priority: "p1",
3360
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
3361
+ },
3356
3362
  {
3357
3363
  title: "Commit discipline \u2014 never leave verified work floating",
3358
3364
  domain: "workflow",
@@ -4662,13 +4668,75 @@ import crypto2 from "crypto";
4662
4668
 
4663
4669
  // src/lib/code-chunker.ts
4664
4670
  import ts from "typescript";
4671
+ var LANGUAGE_BY_EXTENSION = {
4672
+ c: "c",
4673
+ cc: "cpp",
4674
+ cpp: "cpp",
4675
+ cxx: "cpp",
4676
+ h: "c",
4677
+ hh: "cpp",
4678
+ hpp: "cpp",
4679
+ cs: "csharp",
4680
+ css: "css",
4681
+ scss: "scss",
4682
+ f: "fortran",
4683
+ f90: "fortran",
4684
+ f95: "fortran",
4685
+ go: "go",
4686
+ html: "html",
4687
+ htm: "html",
4688
+ java: "java",
4689
+ js: "javascript",
4690
+ jsx: "javascript",
4691
+ json: "json",
4692
+ kt: "kotlin",
4693
+ kts: "kotlin",
4694
+ lua: "lua",
4695
+ md: "markdown",
4696
+ mdx: "mdx",
4697
+ pas: "pascal",
4698
+ php: "php",
4699
+ py: "python",
4700
+ r: "r",
4701
+ rb: "ruby",
4702
+ rs: "rust",
4703
+ scala: "scala",
4704
+ sc: "scala",
4705
+ sol: "solidity",
4706
+ sql: "sql",
4707
+ svelte: "svelte",
4708
+ swift: "swift",
4709
+ toml: "toml",
4710
+ ts: "typescript",
4711
+ tsx: "typescript",
4712
+ vue: "vue",
4713
+ xml: "xml",
4714
+ yaml: "yaml",
4715
+ yml: "yaml",
4716
+ sh: "shell",
4717
+ bash: "shell",
4718
+ zsh: "shell"
4719
+ };
4720
+ var TEXT_LIKE_LANGUAGES = /* @__PURE__ */ new Set(["json", "markdown", "mdx", "toml", "yaml", "xml", "html", "css", "scss", "sql"]);
4721
+ function languageForFile(filePath) {
4722
+ const base = filePath.split(/[\\/]/).pop()?.toLowerCase() ?? "";
4723
+ if (["dockerfile", "makefile", "rakefile", "gemfile"].includes(base)) return base;
4724
+ const ext = base.includes(".") ? base.split(".").pop() : void 0;
4725
+ return ext ? LANGUAGE_BY_EXTENSION[ext] : void 0;
4726
+ }
4665
4727
  function chunkSourceFile(source, fileName = "file.ts") {
4728
+ const language = languageForFile(fileName);
4729
+ if (language === "typescript" || language === "javascript") {
4730
+ return chunkTypeScriptLike(source, fileName);
4731
+ }
4732
+ return chunkGenericSource(source, fileName, language);
4733
+ }
4734
+ function chunkTypeScriptLike(source, fileName) {
4666
4735
  const sourceFile = ts.createSourceFile(
4667
4736
  fileName,
4668
4737
  source,
4669
4738
  ts.ScriptTarget.Latest,
4670
4739
  true,
4671
- // setParentNodes
4672
4740
  fileName.endsWith(".tsx") || fileName.endsWith(".jsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS
4673
4741
  );
4674
4742
  const chunks = [];
@@ -4690,149 +4758,121 @@ function chunkSourceFile(source, fileName = "file.ts") {
4690
4758
  if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) {
4691
4759
  return node.name?.getText(sourceFile) ?? "(anonymous)";
4692
4760
  }
4693
- if (ts.isClassDeclaration(node)) {
4694
- return node.name?.getText(sourceFile) ?? "(anonymous class)";
4695
- }
4696
- if (ts.isInterfaceDeclaration(node)) {
4697
- return node.name.getText(sourceFile);
4698
- }
4699
- if (ts.isTypeAliasDeclaration(node)) {
4700
- return node.name.getText(sourceFile);
4701
- }
4702
- if (ts.isEnumDeclaration(node)) {
4703
- return node.name.getText(sourceFile);
4704
- }
4705
- if (ts.isVariableStatement(node)) {
4706
- const decls = node.declarationList.declarations;
4707
- return decls.map((d) => d.name.getText(sourceFile)).join(", ");
4708
- }
4709
- if (ts.isExportAssignment(node)) {
4710
- return "default export";
4711
- }
4761
+ if (ts.isClassDeclaration(node)) return node.name?.getText(sourceFile) ?? "(anonymous class)";
4762
+ if (ts.isInterfaceDeclaration(node)) return node.name.getText(sourceFile);
4763
+ if (ts.isTypeAliasDeclaration(node)) return node.name.getText(sourceFile);
4764
+ if (ts.isEnumDeclaration(node)) return node.name.getText(sourceFile);
4765
+ if (ts.isVariableStatement(node)) return node.declarationList.declarations.map((d) => d.name.getText(sourceFile)).join(", ");
4766
+ if (ts.isExportAssignment(node)) return "default export";
4712
4767
  return "(unknown)";
4713
4768
  }
4714
4769
  function visitTopLevel(node) {
4715
4770
  if (ts.isImportDeclaration(node)) {
4716
- importLines.push({
4717
- start: getLineNumber(node.getStart(sourceFile)),
4718
- end: getLineNumber(node.getEnd())
4719
- });
4771
+ importLines.push({ start: getLineNumber(node.getStart(sourceFile)), end: getLineNumber(node.getEnd()) });
4720
4772
  return;
4721
4773
  }
4722
4774
  if (ts.isFunctionDeclaration(node)) {
4723
- chunks.push({
4724
- kind: "function",
4725
- name: getName(node),
4726
- text: getNodeText(node),
4727
- startLine: getLineNumber(node.getStart(sourceFile)),
4728
- endLine: getLineNumber(node.getEnd()),
4729
- comment: getLeadingComment(node)
4730
- });
4775
+ chunks.push({ kind: "function", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
4731
4776
  return;
4732
4777
  }
4733
4778
  if (ts.isClassDeclaration(node)) {
4734
- chunks.push({
4735
- kind: "class",
4736
- name: getName(node),
4737
- text: getNodeText(node),
4738
- startLine: getLineNumber(node.getStart(sourceFile)),
4739
- endLine: getLineNumber(node.getEnd()),
4740
- comment: getLeadingComment(node)
4741
- });
4779
+ chunks.push({ kind: "class", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
4742
4780
  return;
4743
4781
  }
4744
- if (ts.isInterfaceDeclaration(node)) {
4745
- chunks.push({
4746
- kind: "type",
4747
- name: getName(node),
4748
- text: getNodeText(node),
4749
- startLine: getLineNumber(node.getStart(sourceFile)),
4750
- endLine: getLineNumber(node.getEnd()),
4751
- comment: getLeadingComment(node)
4752
- });
4753
- return;
4754
- }
4755
- if (ts.isTypeAliasDeclaration(node)) {
4756
- chunks.push({
4757
- kind: "type",
4758
- name: getName(node),
4759
- text: getNodeText(node),
4760
- startLine: getLineNumber(node.getStart(sourceFile)),
4761
- endLine: getLineNumber(node.getEnd()),
4762
- comment: getLeadingComment(node)
4763
- });
4764
- return;
4765
- }
4766
- if (ts.isEnumDeclaration(node)) {
4767
- chunks.push({
4768
- kind: "type",
4769
- name: getName(node),
4770
- text: getNodeText(node),
4771
- startLine: getLineNumber(node.getStart(sourceFile)),
4772
- endLine: getLineNumber(node.getEnd()),
4773
- comment: getLeadingComment(node)
4774
- });
4782
+ if (ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node)) {
4783
+ chunks.push({ kind: "type", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
4775
4784
  return;
4776
4785
  }
4777
4786
  if (ts.isVariableStatement(node)) {
4778
- const decls = node.declarationList.declarations;
4779
- const isFnLike = decls.some(
4780
- (d) => d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer))
4781
- );
4782
- chunks.push({
4783
- kind: isFnLike ? "function" : "variable",
4784
- name: getName(node),
4785
- text: getNodeText(node),
4786
- startLine: getLineNumber(node.getStart(sourceFile)),
4787
- endLine: getLineNumber(node.getEnd()),
4788
- comment: getLeadingComment(node)
4789
- });
4787
+ const isFnLike = node.declarationList.declarations.some((d) => d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer)));
4788
+ chunks.push({ kind: isFnLike ? "function" : "variable", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
4790
4789
  return;
4791
4790
  }
4792
4791
  if (ts.isExportAssignment(node)) {
4793
- chunks.push({
4794
- kind: "export",
4795
- name: "default export",
4796
- text: getNodeText(node),
4797
- startLine: getLineNumber(node.getStart(sourceFile)),
4798
- endLine: getLineNumber(node.getEnd()),
4799
- comment: getLeadingComment(node)
4800
- });
4792
+ chunks.push({ kind: "export", name: "default export", text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
4801
4793
  return;
4802
4794
  }
4803
4795
  if (ts.isExpressionStatement(node)) {
4804
4796
  const text = getNodeText(node);
4805
- if (text.length > 10) {
4806
- chunks.push({
4807
- kind: "other",
4808
- name: text.slice(0, 40).replace(/\n/g, " "),
4809
- text,
4810
- startLine: getLineNumber(node.getStart(sourceFile)),
4811
- endLine: getLineNumber(node.getEnd())
4812
- });
4813
- }
4814
- return;
4797
+ if (text.length > 10) chunks.push({ kind: "other", name: text.slice(0, 40).replace(/\n/g, " "), text, startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()) });
4815
4798
  }
4816
4799
  }
4817
4800
  sourceFile.statements.forEach(visitTopLevel);
4818
4801
  if (importLines.length > 0) {
4819
4802
  const startLine = importLines[0].start;
4820
4803
  const endLine = importLines[importLines.length - 1].end;
4821
- const importText = lines.slice(startLine - 1, endLine).join("\n");
4822
- chunks.unshift({
4823
- kind: "import",
4824
- name: `${importLines.length} imports`,
4825
- text: importText,
4826
- startLine,
4804
+ chunks.unshift({ kind: "import", name: `${importLines.length} imports`, text: lines.slice(startLine - 1, endLine).join("\n"), startLine, endLine });
4805
+ }
4806
+ chunks.sort((a, b) => a.startLine - b.startLine);
4807
+ return chunks.length > 0 ? chunks : chunkByWindows(source, 80);
4808
+ }
4809
+ function chunkGenericSource(source, _fileName, language) {
4810
+ const lines = source.split("\n");
4811
+ if (source.trim().length === 0) return [];
4812
+ if (language && TEXT_LIKE_LANGUAGES.has(language)) return chunkTextLike(lines, language);
4813
+ const chunks = [];
4814
+ const patterns = [
4815
+ { kind: "function", regex: /^\s*(?:async\s+)?def\s+([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
4816
+ { kind: "class", regex: /^\s*class\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
4817
+ { kind: "function", regex: /^\s*(?:pub\s+)?fn\s+([A-Za-z_][\w]*)\s*[<(]/, name: (m) => m[1] },
4818
+ { kind: "class", regex: /^\s*(?:pub\s+)?(?:struct|enum|trait)\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
4819
+ { kind: "function", regex: /^\s*func\s+(?:\([^)]*\)\s*)?([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
4820
+ { kind: "function", regex: /^\s*(?:public|private|protected|static|final|suspend|fun|override|open|internal|export|async|func|function|subroutine)\s+.*?([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
4821
+ { kind: "function", regex: /^\s*function\s+([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
4822
+ { kind: "type", regex: /^\s*(?:interface|type|enum|record|data\s+class|case\s+class|contract|library)\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
4823
+ { kind: "section", regex: /^\s{0,3}#{1,6}\s+(.+)$/, name: (m) => m[1].trim() }
4824
+ ];
4825
+ const starts = [];
4826
+ for (let i = 0; i < lines.length; i++) {
4827
+ const line = lines[i];
4828
+ for (const pattern of patterns) {
4829
+ const match = line.match(pattern.regex);
4830
+ if (match) {
4831
+ starts.push({ line: i + 1, kind: pattern.kind, name: pattern.name(match) });
4832
+ break;
4833
+ }
4834
+ }
4835
+ }
4836
+ if (starts.length === 0) return chunkByWindows(source, 80);
4837
+ for (let i = 0; i < starts.length; i++) {
4838
+ const start = starts[i];
4839
+ const next = starts[i + 1]?.line ?? lines.length + 1;
4840
+ const endLine = Math.max(start.line, next - 1);
4841
+ chunks.push({
4842
+ kind: start.kind,
4843
+ name: start.name,
4844
+ text: lines.slice(start.line - 1, endLine).join("\n"),
4845
+ startLine: start.line,
4827
4846
  endLine
4828
4847
  });
4829
4848
  }
4830
- chunks.sort((a, b) => a.startLine - b.startLine);
4849
+ return chunks;
4850
+ }
4851
+ function chunkTextLike(lines, language) {
4852
+ if (language === "markdown" || language === "mdx") {
4853
+ const starts = lines.map((line, i) => ({ line, i })).filter(({ line }) => /^\s{0,3}#{1,6}\s+/.test(line));
4854
+ if (starts.length > 0) {
4855
+ return starts.map((start, idx) => {
4856
+ const end = starts[idx + 1]?.i ?? lines.length;
4857
+ const title = start.line.replace(/^\s{0,3}#{1,6}\s+/, "").trim();
4858
+ return { kind: "section", name: title, text: lines.slice(start.i, end).join("\n"), startLine: start.i + 1, endLine: end };
4859
+ });
4860
+ }
4861
+ }
4862
+ return chunkByWindows(lines.join("\n"), 80);
4863
+ }
4864
+ function chunkByWindows(source, windowLines) {
4865
+ const lines = source.split("\n");
4866
+ const chunks = [];
4867
+ for (let i = 0; i < lines.length; i += windowLines) {
4868
+ const end = Math.min(lines.length, i + windowLines);
4869
+ const text = lines.slice(i, end).join("\n");
4870
+ if (text.trim()) chunks.push({ kind: "other", name: `lines ${i + 1}-${end}`, text, startLine: i + 1, endLine: end });
4871
+ }
4831
4872
  return chunks;
4832
4873
  }
4833
4874
  function isChunkable(filePath) {
4834
- const ext = filePath.split(".").pop()?.toLowerCase();
4835
- return ext === "ts" || ext === "tsx" || ext === "js" || ext === "jsx";
4875
+ return Boolean(languageForFile(filePath));
4836
4876
  }
4837
4877
 
4838
4878
  // src/lib/graph-rag.ts
@@ -4125,6 +4125,12 @@ var init_platform_procedures = __esm({
4125
4125
  priority: "p0",
4126
4126
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4127
4127
  },
4128
+ {
4129
+ title: "Code context first for repository orientation",
4130
+ domain: "workflow",
4131
+ priority: "p1",
4132
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
4133
+ },
4128
4134
  {
4129
4135
  title: "Commit discipline \u2014 never leave verified work floating",
4130
4136
  domain: "workflow",
@@ -4234,6 +4234,12 @@ var init_platform_procedures = __esm({
4234
4234
  priority: "p0",
4235
4235
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4236
4236
  },
4237
+ {
4238
+ title: "Code context first for repository orientation",
4239
+ domain: "workflow",
4240
+ priority: "p1",
4241
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
4242
+ },
4237
4243
  {
4238
4244
  title: "Commit discipline \u2014 never leave verified work floating",
4239
4245
  domain: "workflow",
@@ -0,0 +1,207 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/is-main.ts
4
+ import { realpathSync } from "fs";
5
+ import { fileURLToPath } from "url";
6
+ function isMainModule(importMetaUrl) {
7
+ if (process.argv[1] == null) return false;
8
+ if (process.argv[1].includes("mcp/server")) return false;
9
+ try {
10
+ const scriptPath = realpathSync(process.argv[1]);
11
+ const modulePath = realpathSync(fileURLToPath(importMetaUrl));
12
+ return scriptPath === modulePath;
13
+ } catch {
14
+ return importMetaUrl === `file://${process.argv[1]}` || importMetaUrl === new URL(process.argv[1], "file://").href;
15
+ }
16
+ }
17
+
18
+ // src/lib/registry-proxy.ts
19
+ import { createServer } from "http";
20
+ import { Readable } from "stream";
21
+ function parsePullTokens(raw) {
22
+ return (raw ?? "").split(/[\n,]/).map((s) => s.trim()).filter(Boolean);
23
+ }
24
+ function registryProxyOptionsFromEnv(env = process.env) {
25
+ const upstreamToken = env.EXE_REGISTRY_PROXY_UPSTREAM_TOKEN || env.GHCR_TOKEN || "";
26
+ const pullTokens = parsePullTokens(env.EXE_REGISTRY_PROXY_PULL_TOKENS);
27
+ return {
28
+ port: Number(env.EXE_REGISTRY_PROXY_PORT || 3201),
29
+ host: env.EXE_REGISTRY_PROXY_HOST || "0.0.0.0",
30
+ upstream: env.EXE_REGISTRY_PROXY_UPSTREAM || "https://ghcr.io",
31
+ upstreamUsername: env.EXE_REGISTRY_PROXY_UPSTREAM_USERNAME || env.GHCR_USERNAME || "askexe",
32
+ upstreamToken,
33
+ pullTokens,
34
+ allowedNamespace: env.EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE || "askexe"
35
+ };
36
+ }
37
+ function assertRegistryProxyConfig(options) {
38
+ if (!options.upstreamToken) throw new Error("EXE_REGISTRY_PROXY_UPSTREAM_TOKEN or GHCR_TOKEN is required");
39
+ if (options.pullTokens.length === 0) throw new Error("EXE_REGISTRY_PROXY_PULL_TOKENS is required");
40
+ if (!options.allowedNamespace || !/^[a-z0-9._-]+$/i.test(options.allowedNamespace)) {
41
+ throw new Error("EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE must be a registry-safe namespace");
42
+ }
43
+ }
44
+ function timingSafeIncludes(values, candidate) {
45
+ return values.some((value) => value === candidate);
46
+ }
47
+ function parseBasicAuth(header) {
48
+ if (!header?.startsWith("Basic ")) return null;
49
+ try {
50
+ const decoded = Buffer.from(header.slice("Basic ".length), "base64").toString("utf8");
51
+ const idx = decoded.indexOf(":");
52
+ if (idx < 0) return null;
53
+ return { username: decoded.slice(0, idx), password: decoded.slice(idx + 1) };
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
58
+ function unauthorized(res) {
59
+ res.writeHead(401, {
60
+ "www-authenticate": 'Basic realm="AskExe Registry Proxy"',
61
+ "content-type": "application/json"
62
+ });
63
+ res.end(JSON.stringify({ error: "registry proxy authentication required" }));
64
+ }
65
+ function isAllowedPath(pathname, namespace) {
66
+ if (pathname === "/health") return true;
67
+ if (pathname === "/v2/" || pathname === "/v2") return true;
68
+ const prefix = `/v2/${namespace}/`;
69
+ if (!pathname.startsWith(prefix)) return false;
70
+ if (pathname.includes("..") || /%2f/i.test(pathname)) return false;
71
+ return true;
72
+ }
73
+ function parseBearerChallenge(header) {
74
+ if (!header?.toLowerCase().startsWith("bearer ")) return null;
75
+ const raw = header.slice("Bearer ".length);
76
+ const params = new URLSearchParams();
77
+ for (const part of raw.match(/(?:[^,"]+|"[^"]*")+/g) ?? []) {
78
+ const idx = part.indexOf("=");
79
+ if (idx < 0) continue;
80
+ const key = part.slice(0, idx).trim();
81
+ const value = part.slice(idx + 1).trim().replace(/^"|"$/g, "");
82
+ params.set(key, value);
83
+ }
84
+ const realm = params.get("realm");
85
+ if (!realm) return null;
86
+ params.delete("realm");
87
+ return { realm, params };
88
+ }
89
+ async function fetchUpstreamWithRegistryAuth(url, init, upstreamBasicAuth) {
90
+ const firstHeaders = new Headers(init.headers);
91
+ firstHeaders.set("authorization", `Basic ${upstreamBasicAuth}`);
92
+ const first = await fetch(url, { ...init, headers: firstHeaders });
93
+ if (first.status !== 401) return first;
94
+ const challenge = parseBearerChallenge(first.headers.get("www-authenticate"));
95
+ if (!challenge) return first;
96
+ const tokenUrl = new URL(challenge.realm);
97
+ for (const [key, value] of challenge.params.entries()) tokenUrl.searchParams.set(key, value);
98
+ const tokenRes = await fetch(tokenUrl, { headers: { authorization: `Basic ${upstreamBasicAuth}` } });
99
+ if (!tokenRes.ok) return first;
100
+ const tokenJson = await tokenRes.json();
101
+ const token = tokenJson.token ?? tokenJson.access_token;
102
+ if (!token) return first;
103
+ const retryHeaders = new Headers(init.headers);
104
+ retryHeaders.set("authorization", `Bearer ${token}`);
105
+ return fetch(url, { ...init, headers: retryHeaders });
106
+ }
107
+ function copyResponseHeaders(from, to) {
108
+ for (const [key, value] of from.entries()) {
109
+ const lower = key.toLowerCase();
110
+ if (["connection", "keep-alive", "transfer-encoding", "content-encoding"].includes(lower)) continue;
111
+ to.setHeader(key, value);
112
+ }
113
+ }
114
+ function createRegistryProxyServer(options) {
115
+ assertRegistryProxyConfig(options);
116
+ const upstream = new URL(options.upstream ?? "https://ghcr.io");
117
+ const namespace = options.allowedNamespace ?? "askexe";
118
+ const upstreamAuth = Buffer.from(`${options.upstreamUsername ?? "askexe"}:${options.upstreamToken}`).toString("base64");
119
+ return createServer(async (req, res) => {
120
+ const requestUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
121
+ if (requestUrl.pathname === "/health") {
122
+ res.writeHead(200, { "content-type": "application/json" });
123
+ res.end(JSON.stringify({ ok: true, service: "exe-registry-proxy", upstream: upstream.origin, namespace }));
124
+ return;
125
+ }
126
+ if (!isAllowedPath(requestUrl.pathname, namespace)) {
127
+ res.writeHead(404, { "content-type": "application/json" });
128
+ res.end(JSON.stringify({ error: "registry path not allowed" }));
129
+ return;
130
+ }
131
+ const auth = parseBasicAuth(req.headers.authorization);
132
+ if (!auth || !timingSafeIncludes(options.pullTokens, auth.password)) {
133
+ unauthorized(res);
134
+ return;
135
+ }
136
+ const upstreamUrl = new URL(requestUrl.pathname + requestUrl.search, upstream.origin);
137
+ const headers = new Headers();
138
+ for (const [key, value] of Object.entries(req.headers)) {
139
+ if (!value) continue;
140
+ const lower = key.toLowerCase();
141
+ if (["host", "connection", "authorization", "content-length"].includes(lower)) continue;
142
+ headers.set(key, Array.isArray(value) ? value.join(",") : value);
143
+ }
144
+ headers.set("authorization", `Basic ${upstreamAuth}`);
145
+ try {
146
+ const upstreamRes = await fetchUpstreamWithRegistryAuth(upstreamUrl, {
147
+ method: req.method,
148
+ headers,
149
+ body: req.method === "GET" || req.method === "HEAD" ? void 0 : req,
150
+ // Required by undici when streaming request bodies.
151
+ duplex: "half"
152
+ }, upstreamAuth);
153
+ res.statusCode = upstreamRes.status;
154
+ res.statusMessage = upstreamRes.statusText;
155
+ copyResponseHeaders(upstreamRes.headers, res);
156
+ if (!upstreamRes.body || req.method === "HEAD") {
157
+ res.end();
158
+ return;
159
+ }
160
+ Readable.fromWeb(upstreamRes.body).pipe(res);
161
+ } catch (err) {
162
+ res.writeHead(502, { "content-type": "application/json" });
163
+ res.end(JSON.stringify({ error: "upstream registry proxy failed", detail: err instanceof Error ? err.message : String(err) }));
164
+ }
165
+ });
166
+ }
167
+ async function runRegistryProxy(options = registryProxyOptionsFromEnv()) {
168
+ const server = createRegistryProxyServer(options);
169
+ await new Promise((resolve) => server.listen(options.port, options.host, resolve));
170
+ console.log(`exe-registry-proxy listening on ${options.host ?? "0.0.0.0"}:${options.port}`);
171
+ console.log(`proxying /v2/${options.allowedNamespace ?? "askexe"}/* -> ${options.upstream ?? "https://ghcr.io"}`);
172
+ }
173
+
174
+ // src/bin/registry-proxy.ts
175
+ function printHelp() {
176
+ console.log(`exe-os registry-proxy \u2014 authenticated pull-through proxy for AskExe customer images
177
+
178
+ Environment:
179
+ EXE_REGISTRY_PROXY_PORT=3201
180
+ EXE_REGISTRY_PROXY_HOST=0.0.0.0
181
+ EXE_REGISTRY_PROXY_UPSTREAM=https://ghcr.io
182
+ EXE_REGISTRY_PROXY_UPSTREAM_USERNAME=<github-user>
183
+ EXE_REGISTRY_PROXY_UPSTREAM_TOKEN=<askexe-ghcr-read-token>
184
+ EXE_REGISTRY_PROXY_PULL_TOKENS=<customer-token-1,customer-token-2>
185
+ EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE=askexe
186
+
187
+ Docker image shape for clients:
188
+ registry.askexe.com/askexe/exed:v0.9.3
189
+ registry.askexe.com/askexe/exe-crm:v0.9.3
190
+ `);
191
+ }
192
+ async function main(args = process.argv.slice(2)) {
193
+ if (args.includes("--help") || args.includes("-h")) {
194
+ printHelp();
195
+ return;
196
+ }
197
+ await runRegistryProxy(registryProxyOptionsFromEnv());
198
+ }
199
+ if (isMainModule(import.meta.url)) {
200
+ main().catch((err) => {
201
+ console.error(err instanceof Error ? err.message : String(err));
202
+ process.exit(1);
203
+ });
204
+ }
205
+ export {
206
+ main
207
+ };