@projectctx/agent 0.1.0-alpha.4 → 0.1.0-alpha.5

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 (2) hide show
  1. package/dist/mcp.js +2 -2
  2. package/package.json +3 -3
package/dist/mcp.js CHANGED
@@ -29,7 +29,7 @@ export function createMcpServer(logger) {
29
29
  logger?.debug("creating MCP server");
30
30
  const server = new McpServer({ name: "projectctx-agent", version: "0.1.0-alpha.0" });
31
31
  logger?.debug("registering MCP tool: scan_workspace");
32
- server.tool("scan_workspace", "Scan a local workspace with the ProjectCtx scanner and return structured JSON. Read-only: no memory writes or cloud calls. The result includes auditTargets[]: EVERY content-bearing target — git repos, plain folders (docs, notes, research, campaigns), a root-level loose-file cluster (kind file_cluster), and allowlisted agent/tool dot folders such as .claude, .codex, .agents, .cursor, .windsurf, and .github — each with facts, overview excerpts, importantLookingFiles, and a suggestedReadPlan. Coverage mandate: do not silently skip any audit target, and never infer meaning from folder or file names — meaning comes from reading the actual file contents. If skipped contains beyond maxDepth, re-invoke scan_workspace on that subtree with higher maxDepth; depth is iterative, not a reason to stop. Delegation: <=3 targets inspect inline; 4-15 targets use one focused subagent per target; >15 targets cluster related targets by parent folder at 3-5 targets per subagent; never skip a target to save agents. Each subagent prompt must include the target facts block verbatim, overview excerpts, importantLookingFiles, and suggestedReadPlan as a starting point, then read beyond the plan until it can state what the target is for, what decisions/knowledge it holds, and what would be lost if it vanished. Subagents return memory candidates — never writes — e.g. Project, Person, Decision, Research Thread, Campaign, Experiment, Service, Dataset, Open Question, Source (open-ended; capture other meaningful things too), each with title, type, why it matters, source file path(s), confidence, suggested collection, and suggested relationships. Then run a verification pass: confirm each candidate is supported by cited files, captures meaning rather than file inventory, and is not already in memory. Check existence PER CANDIDATE, not with one broad sweep: for each one, search_memory/query_records by its own distinctive name/identifier (for a repo, its name and externalId such as github:owner/repo) — search_memory is ranked and capped, so a single multi-term query is not a census and must never be the basis for declaring anything 'new' or 'missing'. When results are ambiguous, confirm with get_workspace_schema + get_context before concluding. Treat the preview/apply duplicate-title/externalId warnings as a final backstop, not your primary existence check. Run a completeness critic: every target has candidates or a concrete 'nothing meaningful' explanation, no skipped deep subtree is left unre-scanned, and another bounded round would produce nothing new. Present a coverage table to the user before preview/apply; ask before writing anything; use the preview/apply flow only.", {
32
+ server.tool("scan_workspace", "Scan a local workspace with the ProjectCtx scanner and return structured JSON. Read-only: no memory writes or cloud calls. The result includes auditTargets[]: EVERY content-bearing target — git repos, plain folders (docs, notes, research, campaigns), a root-level loose-file cluster (kind file_cluster), and allowlisted agent/tool dot folders such as .claude, .codex, .agents, .cursor, .windsurf, and .github — each with facts, overview excerpts, importantLookingFiles, and a suggestedReadPlan. Coverage mandate: do not silently skip any audit target, and never infer meaning from folder or file names — meaning comes from reading the actual file contents. If skipped contains beyond maxDepth, re-invoke scan_workspace on that subtree with higher maxDepth; depth is iterative, not a reason to stop. Delegation: <=3 targets inspect inline; 4-15 targets use one focused subagent per target; >15 targets cluster related targets by parent folder at 3-5 targets per subagent; never skip a target to save agents. Each subagent prompt must include the target facts block verbatim, overview excerpts, importantLookingFiles, and suggestedReadPlan as a starting point, then read beyond the plan until it can state what the target is for, what decisions/knowledge it holds, and what would be lost if it vanished. Subagents return memory candidates — never writes — e.g. Project, Person, Decision, Research Thread, Campaign, Experiment, Service, Dataset, Open Question, Source (open-ended; capture other meaningful things too), each with title, type, why it matters, source file path(s), confidence, suggested collection, and suggested relationships. When a candidate warrants a NEW collection, also suggest a concise 3-5 typed snake_case field set for it — durable/queryable/at-a-glance dimensions only (status, owner, stage, dates, links); narrative stays in the record markdown, never in fields. Reuse an existing collection's fields rather than proposing parallel ones. Then run a verification pass: confirm each candidate is supported by cited files, captures meaning rather than file inventory, and is not already in memory. Check existence PER CANDIDATE, not with one broad sweep: for each one, search_memory/query_records by its own distinctive name/identifier (for a repo, its name and externalId such as github:owner/repo) — search_memory is ranked and capped, so a single multi-term query is not a census and must never be the basis for declaring anything 'new' or 'missing'. When results are ambiguous, confirm with get_workspace_schema + get_context before concluding. Treat the preview/apply duplicate-title/externalId warnings as a final backstop, not your primary existence check. Run a completeness critic: every target has candidates or a concrete 'nothing meaningful' explanation, no skipped deep subtree is left unre-scanned, and another bounded round would produce nothing new. Present a coverage table to the user before preview/apply; ask before writing anything; use the preview/apply flow only.", {
33
33
  rootPath: z.string().optional(),
34
34
  maxRepos: z.number().int().positive().optional(),
35
35
  maxTargets: z.number().int().positive().optional(),
@@ -59,7 +59,7 @@ export function createMcpServer(logger) {
59
59
  }
60
60
  });
61
61
  logger?.debug("registering MCP tool: preview_code_memory");
62
- server.tool("preview_code_memory", "Compile codebase scan context and an agent-written code brief into a ProjectCtx memory preview. No durable memory writes are applied. Write each repo brief self-contained: describe the repo on its own terms; do not define it by contrast to sibling records. To group repos, reuse an existing Project rather than forking a parallel one — the compiler reuses an exact-name match and returns warnings that surface similar-named existing projects. Read the returned warnings before you apply. To reuse a surfaced project, pass its externalId as projectExternalId when it has one, or reuse it by its exact title/alias when it does not — projectExternalId accepts only an externalId, never a record id. The flow self-provisions its own code ontology: the Repos and Projects collections and the builds relationship type are reused if they already exist, otherwise created on the fly, and are POPULATED in the same pass (repo + project records, builds links) — so scanning into a brand-new empty workspace needs no seeding. Separately, if the repo context clearly describes an entity type no existing collection covers (e.g. Services, People, Datasets), you may propose it in the optional collections[] input; those emergent collections are created/reconciled by name (exact-name reuse, fuzzy warning) but are NOT populated by code-memory yet they are created empty. Prefer an existing collection; do not propose one just because a topic is mentioned in passing.", previewCodeMemorySchema.shape, async (input) => {
62
+ server.tool("preview_code_memory", "Compile codebase scan context and an agent-written code brief into a ProjectCtx memory preview. No durable memory writes are applied. Write each repo brief self-contained: describe the repo on its own terms; do not define it by contrast to sibling records. To group repos, reuse an existing Project rather than forking a parallel one — the compiler reuses an exact-name match and returns warnings that surface similar-named existing projects. Read the returned warnings before you apply. To reuse a surfaced project, pass its externalId as projectExternalId when it has one, or reuse it by its exact title/alias when it does not — projectExternalId accepts only an externalId, never a record id. The flow self-provisions its own code ontology: the Repos and Projects collections and the builds relationship type are reused if they already exist, otherwise created on the fly, and are POPULATED in the same pass (repo + project records, builds links) — so scanning into a brand-new empty workspace needs no seeding. Fields are agent-authored, with no baked-in defaults: to give Repos/Projects structured fields, include collections[] entries named \"Repos\"/\"Projects\" with a concise fields[] (3-5 typed snake_case fields for durable/queryable dimensions — Repo e.g. primary_language/status/deploy_url; Project e.g. status/stage/owner/next_step). Populate them by passing a repo.fields value map and a repo.project.fields value map whose keys match those fields, and put the project's prose in repo.project.markdownBrief so the Project record is not an empty hub. Separately, if the repo context clearly describes an entity type no existing collection covers (e.g. Services, People, Datasets), you may propose it in the optional collections[] input with its own concise fields[]; those emergent collections are created/reconciled by name (exact-name reuse, fuzzy warning) and their fields reconcile additively (existing fields never change). Keep narrative in markdown, not fields. Prefer an existing collection; do not propose one just because a topic is mentioned in passing.", previewCodeMemorySchema.shape, async (input) => {
63
63
  try {
64
64
  return jsonText(await runPreviewCodeMemory(previewCodeMemorySchema.parse(input), logger));
65
65
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectctx/agent",
3
- "version": "0.1.0-alpha.4",
3
+ "version": "0.1.0-alpha.5",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -29,8 +29,8 @@
29
29
  "pack:verify": "node scripts/verify-package.mjs"
30
30
  },
31
31
  "dependencies": {
32
- "@projectctx/contracts": "0.1.0-alpha.3",
33
- "@projectctx/indexer": "0.1.0-alpha.3",
32
+ "@projectctx/contracts": "0.1.0-alpha.5",
33
+ "@projectctx/indexer": "0.1.0-alpha.5",
34
34
  "@modelcontextprotocol/sdk": "^1.13.1",
35
35
  "@napi-rs/keyring": "^1.3.0",
36
36
  "zod": "^3.25.67"