@c4a/context-cli 0.6.8 → 0.6.10

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 (35) hide show
  1. package/README.md +156 -220
  2. package/README.zh-CN.md +120 -160
  3. package/cli.js +265 -58
  4. package/docs/quickstart.md +57 -70
  5. package/docs/quickstart.zh-CN.md +79 -0
  6. package/package.json +4 -4
  7. package/plugins/.agents/plugins/marketplace.json +1 -1
  8. package/plugins/.claude-plugin/marketplace.json +2 -2
  9. package/plugins/.cursor-plugin/marketplace.json +2 -2
  10. package/plugins/README.md +79 -66
  11. package/plugins/README_CN.md +62 -57
  12. package/plugins/VERSION +1 -1
  13. package/plugins/claude/.claude-plugin/plugin.json +3 -3
  14. package/plugins/claude/commands/context.md +121 -0
  15. package/plugins/codex/.codex-plugin/plugin.json +4 -4
  16. package/plugins/codex/skills/context/SKILL.md +133 -0
  17. package/plugins/cursor/.cursor-plugin/plugin.json +3 -3
  18. package/plugins/cursor/README.md +2 -2
  19. package/plugins/cursor/commands/c4a-context.md +125 -0
  20. package/plugins/skills/c4a-context/SKILL.md +133 -0
  21. package/providers/context/graphs/workspace.yaml +40 -1
  22. package/providers/context/manifest.json +27 -9
  23. package/providers/context/provider.yaml +2 -2
  24. package/providers/context/resources/dialogue/workflow-mode-after-capture.md +22 -0
  25. package/providers/context/resources/dialogue/workflow-mode-after-creation.md +25 -0
  26. package/providers/context/resources/manuals/guides/package-outputs.md +1 -1
  27. package/providers/context/resources/manuals/reference/package-templates.md +1 -1
  28. package/plugins/claude/commands/continue.md +0 -109
  29. package/plugins/claude/commands/init.md +0 -36
  30. package/plugins/codex/skills/continue/SKILL.md +0 -121
  31. package/plugins/codex/skills/init/SKILL.md +0 -48
  32. package/plugins/cursor/commands/context-continue.md +0 -113
  33. package/plugins/cursor/commands/context-init.md +0 -40
  34. package/plugins/skills/context-continue/SKILL.md +0 -121
  35. package/plugins/skills/context-init/SKILL.md +0 -48
package/cli.js CHANGED
@@ -17554,7 +17554,7 @@ async function recordAgentGraphEvaluation(input) {
17554
17554
  ...input.route === undefined ? {} : { routeId: input.route.id, node: input.route.node, reasonCode: input.route.reasonCode }
17555
17555
  };
17556
17556
  await appendEvent(input.projectRoot, "agent-graph.evaluated", {
17557
- graph: { provider: "c4a/context", graph: "workspace", entry: "continue" },
17557
+ graph: { provider: "c4a/context", graph: "workspace", entry: "context" },
17558
17558
  current: current2,
17559
17559
  ...input.route === undefined ? {} : { selected_route: input.route },
17560
17560
  alternatives: input.alternatives
@@ -24130,7 +24130,7 @@ var require_lib = __commonJS((exports, module) => {
24130
24130
  });
24131
24131
 
24132
24132
  // src/cli.ts
24133
- import { existsSync as existsSync46, readFileSync as readFileSync10, realpathSync } from "node:fs";
24133
+ import { existsSync as existsSync47, readFileSync as readFileSync10, realpathSync } from "node:fs";
24134
24134
  import { dirname as dirname42, join as join71 } from "node:path";
24135
24135
  import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL4 } from "node:url";
24136
24136
 
@@ -24162,7 +24162,7 @@ init_exitCode();
24162
24162
  // src/project/workflow/workflowTypes.ts
24163
24163
  var CONTEXT_WORKFLOW_PROVIDER_ID = "c4a/context";
24164
24164
  var CONTEXT_WORKFLOW_GRAPH_ID = "workspace";
24165
- var CONTEXT_WORKFLOW_ENTRY = "continue";
24165
+ var CONTEXT_WORKFLOW_ENTRY = "context";
24166
24166
  var CONTEXT_WORKFLOW_AUTHORITIES = {
24167
24167
  evidenceMaintenance: "context.evidence-maintenance",
24168
24168
  repositoryRestore: "context.repository-restore",
@@ -24198,7 +24198,7 @@ function mergedWorkflowAuthorities(...values) {
24198
24198
  // src/project/workflow/workflowResource.ts
24199
24199
  import { join as join57 } from "node:path";
24200
24200
 
24201
- // ../../node_modules/.bun/@c4a+agent-graph@0.2.5/node_modules/@c4a/agent-graph/dist/index.js
24201
+ // ../../node_modules/.bun/@c4a+agent-graph@0.2.6/node_modules/@c4a/agent-graph/dist/index.js
24202
24202
  import { createRequire as createRequire2 } from "node:module";
24203
24203
  import { createHash } from "node:crypto";
24204
24204
  import { mkdir, readFile, readdir, realpath, rename, stat, writeFile } from "node:fs/promises";
@@ -38749,6 +38749,15 @@ var graph_schema_default = {
38749
38749
  },
38750
38750
  inspectionAction: { $ref: "#/$defs/relativePath" },
38751
38751
  resolutionAction: { $ref: "#/$defs/relativePath" },
38752
+ delegated: {
38753
+ type: "object",
38754
+ additionalProperties: false,
38755
+ properties: {
38756
+ inspection: { enum: ["required", "skip"], default: "required" },
38757
+ resolutionAction: { $ref: "#/$defs/relativePath" },
38758
+ resources: { $ref: "#/$defs/resources" }
38759
+ }
38760
+ },
38752
38761
  terminalOutcome: { $ref: "#/$defs/outcome" },
38753
38762
  requiresFacts: { type: "array", items: { $ref: "#/$defs/factCheck" } },
38754
38763
  satisfiedBy: { type: "array", minItems: 1, items: { $ref: "#/$defs/factCheck" } },
@@ -38758,7 +38767,7 @@ var graph_schema_default = {
38758
38767
  {
38759
38768
  properties: { kind: { const: "action" } },
38760
38769
  required: ["action", "reasonCode"],
38761
- not: { anyOf: [{ required: ["graph"] }, { required: ["entry"] }, { required: ["gate"] }, { required: ["inspectionAction"] }, { required: ["resolutionAction"] }, { required: ["terminalOutcome"] }] }
38770
+ not: { anyOf: [{ required: ["graph"] }, { required: ["entry"] }, { required: ["gate"] }, { required: ["inspectionAction"] }, { required: ["resolutionAction"] }, { required: ["delegated"] }, { required: ["terminalOutcome"] }] }
38762
38771
  },
38763
38772
  {
38764
38773
  properties: { kind: { const: "gate" } },
@@ -38768,12 +38777,12 @@ var graph_schema_default = {
38768
38777
  {
38769
38778
  properties: { kind: { const: "subgraph" } },
38770
38779
  required: ["graph", "entry"],
38771
- not: { anyOf: [{ required: ["action"] }, { required: ["gate"] }, { required: ["inspectionAction"] }, { required: ["resolutionAction"] }, { required: ["reasonCode"] }, { required: ["terminalOutcome"] }, { required: ["satisfiedBy"] }, { required: ["resources"] }] }
38780
+ not: { anyOf: [{ required: ["action"] }, { required: ["gate"] }, { required: ["inspectionAction"] }, { required: ["resolutionAction"] }, { required: ["delegated"] }, { required: ["reasonCode"] }, { required: ["terminalOutcome"] }, { required: ["satisfiedBy"] }, { required: ["resources"] }] }
38772
38781
  },
38773
38782
  {
38774
38783
  properties: { kind: { const: "terminal" } },
38775
38784
  required: ["terminalOutcome"],
38776
- not: { anyOf: [{ required: ["action"] }, { required: ["graph"] }, { required: ["entry"] }, { required: ["gate"] }, { required: ["inspectionAction"] }, { required: ["resolutionAction"] }, { required: ["reasonCode"] }, { required: ["satisfiedBy"] }, { required: ["resources"] }] }
38785
+ not: { anyOf: [{ required: ["action"] }, { required: ["graph"] }, { required: ["entry"] }, { required: ["gate"] }, { required: ["inspectionAction"] }, { required: ["resolutionAction"] }, { required: ["delegated"] }, { required: ["reasonCode"] }, { required: ["satisfiedBy"] }, { required: ["resources"] }] }
38777
38786
  }
38778
38787
  ]
38779
38788
  },
@@ -39854,6 +39863,20 @@ async function loadProvider(manifestPath) {
39854
39863
  throw new AgentGraphError("gate-inspection-effect-invalid", `Gate ${graphId}/${node.id} inspection Action ${inspection.definition.id} must use effect: read`);
39855
39864
  }
39856
39865
  }
39866
+ if (node.kind === "gate" && node.delegated !== undefined) {
39867
+ if (node.gate.delegatable !== true || node.gate.authority === undefined) {
39868
+ throw new AgentGraphError("gate-delegated-policy-invalid", `Gate ${graphId}/${node.id} declares delegated execution without a delegatable authority`);
39869
+ }
39870
+ if (node.delegated.inspection === "skip" && node.inspectionAction === undefined) {
39871
+ throw new AgentGraphError("gate-delegated-inspection-missing", `Gate ${graphId}/${node.id} skips delegated inspection but has no inspection Action`);
39872
+ }
39873
+ if (node.delegated.resolutionAction !== undefined) {
39874
+ const delegatedResolution = await includeAction(node.delegated.resolutionAction, directFiles, "delegated gate resolution action referenced file");
39875
+ if (delegatedResolution.definition.effect === "read") {
39876
+ throw new AgentGraphError("gate-resolution-effect-invalid", `Gate ${graphId}/${node.id} delegated resolution Action ${delegatedResolution.definition.id} must use effect: write or external`);
39877
+ }
39878
+ }
39879
+ }
39857
39880
  if (node.kind === "gate" && node.resolutionAction) {
39858
39881
  const resolution = await includeAction(node.resolutionAction, directFiles, "gate resolution action referenced file");
39859
39882
  if (resolution.definition.effect === "read") {
@@ -39861,9 +39884,12 @@ async function loadProvider(manifestPath) {
39861
39884
  }
39862
39885
  }
39863
39886
  const nodeResources = node.kind === "action" || node.kind === "gate" ? node.resources : undefined;
39887
+ const delegatedResources = node.kind === "gate" ? node.delegated?.resources : undefined;
39864
39888
  for (const resourceReference of [
39865
39889
  ...nodeResources?.required ?? [],
39866
- ...nodeResources?.recommended ?? []
39890
+ ...nodeResources?.recommended ?? [],
39891
+ ...delegatedResources?.required ?? [],
39892
+ ...delegatedResources?.recommended ?? []
39867
39893
  ]) {
39868
39894
  const resourcePath = resolveContainedPath(root, resourceReference, "resource reference");
39869
39895
  if (!resources.has(resourcePath)) {
@@ -40113,8 +40139,9 @@ async function locateCode(provider, code) {
40113
40139
  };
40114
40140
  }
40115
40141
  async function resourcesForCandidate(provider, candidate, revision) {
40116
- const requiredReferences = [...candidate.node.resources?.required ?? []];
40117
- const recommendedReferences = [...candidate.node.resources?.recommended ?? []];
40142
+ const selectedResources = candidate.node.kind === "gate" && candidate.gateResolution === "session-authority" && candidate.node.delegated?.resources !== undefined ? candidate.node.delegated.resources : candidate.node.resources;
40143
+ const requiredReferences = [...selectedResources?.required ?? []];
40144
+ const recommendedReferences = [...selectedResources?.recommended ?? []];
40118
40145
  const action = candidate.node.kind === "action" ? referencedAction(provider, candidate.node.action) : undefined;
40119
40146
  const required = await Promise.all(requiredReferences.map((reference) => locateResource(provider, reference, revision)));
40120
40147
  const recommended = await Promise.all(recommendedReferences.map((reference) => locateResource(provider, reference, revision)));
@@ -40179,8 +40206,8 @@ async function resolveRoute(provider, graphId, entry2, routeId2, input = {}, exp
40179
40206
  recommended: annotateReadState(locatedResources.recommended, input.resourceReceipts)
40180
40207
  };
40181
40208
  const action = candidate.node.kind === "action" ? referencedAction(provider, candidate.node.action) : undefined;
40182
- const inspectionAction = candidate.node.kind === "gate" ? referencedAction(provider, candidate.node.inspectionAction) : undefined;
40183
- const resolutionAction = candidate.node.kind === "gate" ? referencedAction(provider, candidate.node.resolutionAction) : undefined;
40209
+ const inspectionAction = candidate.node.kind === "gate" && !(candidate.gateResolution === "session-authority" && candidate.node.delegated?.inspection === "skip") ? referencedAction(provider, candidate.node.inspectionAction) : undefined;
40210
+ const resolutionAction = candidate.node.kind === "gate" ? referencedAction(provider, candidate.gateResolution === "session-authority" && candidate.node.delegated?.resolutionAction !== undefined ? candidate.node.delegated.resolutionAction : candidate.node.resolutionAction) : undefined;
40184
40211
  const workspace = input.workspace ?? process.cwd();
40185
40212
  return {
40186
40213
  schema: "agent-graph.route.v1",
@@ -69148,6 +69175,7 @@ var RUNTIME_EVENT_STATE_SCHEMA = "context.runtime-event-state.v1";
69148
69175
  var RUNTIME_EVENT_STATE_FILE = "runtime-event-state.json";
69149
69176
  var RUNTIME_EVENT_SINK_DESCRIPTION_TIMEOUT_MS = 2000;
69150
69177
  var RUNTIME_EVENT_SINK_DESCRIPTION_MAX_BYTES = 16 * 1024;
69178
+ var RUNTIME_EVENTS_DISABLED_ENV = "CONTEXT_RUNTIME_EVENTS_DISABLED";
69151
69179
  var activeScope;
69152
69180
  function isRecord9(value) {
69153
69181
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -69256,7 +69284,7 @@ function readRuntimePackageMetadata() {
69256
69284
  if (isRecord9(parsed)) {
69257
69285
  return {
69258
69286
  contextVersion: typeof parsed.version === "string" ? parsed.version : "unknown",
69259
- sink: parseContextRuntimeEventSink(parsed.contextRuntimeEventSink)
69287
+ sink: process.env[RUNTIME_EVENTS_DISABLED_ENV] === "1" ? null : parseContextRuntimeEventSink(parsed.contextRuntimeEventSink)
69260
69288
  };
69261
69289
  }
69262
69290
  }
@@ -87881,17 +87909,17 @@ function createContextWorkflowFacts(observation, authorities) {
87881
87909
  source_read_resolved: captureComplete || hasAuthority(authorities, CONTEXT_WORKFLOW_AUTHORITIES.sourceRead),
87882
87910
  extraction_scope_resolved: extractDeclarationsComplete,
87883
87911
  document_classification_resolved: documentsClassified,
87884
- structure_confirmation_resolved: structureConfirmed || hasAuthority(authorities, CONTEXT_WORKFLOW_AUTHORITIES.structureConfirmation),
87885
- knowledge_review_resolved: reviewGateIsClear || hasAuthority(authorities, CONTEXT_WORKFLOW_AUTHORITIES.knowledgeReview),
87912
+ structure_confirmation_resolved: structureConfirmed,
87913
+ knowledge_review_resolved: reviewGateIsClear,
87886
87914
  package_output_resolved: packagesDeclared || hasAuthority(authorities, CONTEXT_WORKFLOW_AUTHORITIES.packageOutput)
87887
87915
  },
87888
87916
  resume: {
87889
87917
  prose_declarations_complete: !captureComplete || !documentRoundStarted || activeRoundProseComplete,
87890
87918
  ...structureRefreshRequired ? { structure_refresh_required: true } : {},
87891
- structure_confirmation_resolved: !captureComplete || !documentRoundStarted || structureConfirmed || hasAuthority(authorities, CONTEXT_WORKFLOW_AUTHORITIES.structureConfirmation),
87919
+ structure_confirmation_resolved: !captureComplete || !documentRoundStarted || structureConfirmed,
87892
87920
  structure_confirmed: !captureComplete || !documentRoundStarted || structureConfirmed,
87893
87921
  compile_complete: !captureComplete || !documentRoundStarted || compiled,
87894
- knowledge_review_resolved: !captureComplete || !documentRoundStarted || reviewGateIsClear || hasAuthority(authorities, CONTEXT_WORKFLOW_AUTHORITIES.knowledgeReview),
87922
+ knowledge_review_resolved: !captureComplete || !documentRoundStarted || reviewGateIsClear,
87895
87923
  review_gate_clear: !captureComplete || !documentRoundStarted || reviewGateIsClear
87896
87924
  },
87897
87925
  sources: {
@@ -88927,11 +88955,12 @@ function withContentAddressedWorkflowResources(status, receipts) {
88927
88955
 
88928
88956
  // src/project/workflow/workflowStatusProjection.ts
88929
88957
  function pendingReview(observation, route) {
88930
- const decisionSource = route?.reason_code === "route.review.apply-managed" ? "managed-session" : route?.gate?.id === "knowledge-review" ? "user-review" : undefined;
88958
+ const decisionSource = route?.gate?.id === "knowledge-review" ? route.gate.resolution === "session-authority" ? "managed-session" : "user-review" : route?.reason_code === "route.review.apply-managed" ? "managed-session" : undefined;
88931
88959
  if (decisionSource === undefined || observation.draftCandidates <= 0 || observation.draftCollections.length === 0) {
88932
88960
  return;
88933
88961
  }
88934
88962
  const collections = [...observation.draftCollections];
88963
+ const managedCommand = decisionSource === "managed-session" ? route?.commands.find((item) => item.availability === "immediate" && item.effect === "write")?.command : undefined;
88935
88964
  if (collections.length === 1) {
88936
88965
  const collection = collections[0];
88937
88966
  return {
@@ -88939,7 +88968,7 @@ function pendingReview(observation, route) {
88939
88968
  collections,
88940
88969
  collection,
88941
88970
  count: observation.draftCandidates,
88942
- command: `context review html ${collection} --open`,
88971
+ command: managedCommand ?? `context review html ${collection} --open`,
88943
88972
  decisionSource,
88944
88973
  ...observation.candidateSetDigest === undefined ? {} : { candidateSetDigest: observation.candidateSetDigest }
88945
88974
  };
@@ -88948,7 +88977,7 @@ function pendingReview(observation, route) {
88948
88977
  scope: "all",
88949
88978
  collections,
88950
88979
  count: observation.draftCandidates,
88951
- command: "context review html --all --open",
88980
+ command: managedCommand ?? "context review html --all --open",
88952
88981
  decisionSource,
88953
88982
  ...observation.candidateSetDigest === undefined ? {} : { candidateSetDigest: observation.candidateSetDigest }
88954
88983
  };
@@ -104450,17 +104479,27 @@ function parseRepositoryRecoveryPayload(value) {
104450
104479
  });
104451
104480
  return { schema: RECOVERY_SCHEMA, repositories };
104452
104481
  }
104453
- function canonicalRemote(value) {
104482
+ function trimRepositorySuffix(value) {
104483
+ return value.trim().replace(/^\/+|\/+$/gu, "").replace(/\.git$/iu, "");
104484
+ }
104485
+ function repositoryPathIdentity(value) {
104454
104486
  const trimmed = value.trim().replace(/\/+$/u, "").replace(/\.git$/iu, "");
104455
- const scp = /^(?:[^@]+@)?([^:]+):(.+)$/u.exec(trimmed);
104456
- if (scp !== null)
104457
- return `${scp[1]?.toLowerCase()}/${scp[2]}`;
104458
- try {
104459
- const url = new URL(trimmed);
104460
- return `${url.hostname.toLowerCase()}${url.pathname}`.replace(/\/+$/u, "").replace(/\.git$/iu, "");
104461
- } catch {
104462
- return trimmed;
104487
+ const windowsPath = /^[a-z]:[\\/]/iu.test(trimmed);
104488
+ const urlSyntax = /^[a-z][a-z0-9+.-]*:\/\//iu.test(trimmed);
104489
+ if (!windowsPath && urlSyntax) {
104490
+ try {
104491
+ const url = new URL(trimmed);
104492
+ if (url.hostname.length > 0)
104493
+ return trimRepositorySuffix(url.pathname);
104494
+ return url.pathname.replace(/\/+$/u, "").replace(/\.git$/iu, "");
104495
+ } catch {
104496
+ return trimmed;
104497
+ }
104463
104498
  }
104499
+ const scp = windowsPath ? null : /^(?:[^@/:]+@)?[^/:]+:(.+)$/u.exec(trimmed);
104500
+ if (scp?.[1] !== undefined)
104501
+ return trimRepositorySuffix(scp[1]);
104502
+ return trimmed;
104464
104503
  }
104465
104504
  function repositorySlug(remote) {
104466
104505
  const raw = basename9(remote.replace(/\/+$/u, "").replace(/\.git$/iu, ""));
@@ -104471,7 +104510,7 @@ function groupId(source2) {
104471
104510
  return `${repositorySlug(source2.git.remote)}-${source2.git.ref.slice(0, 12)}`;
104472
104511
  }
104473
104512
  function groupKey(source2) {
104474
- return `${canonicalRemote(source2.git.remote)}\x00${source2.git.ref.toLowerCase()}`;
104513
+ return `${repositoryPathIdentity(source2.git.remote)}\x00${source2.git.ref.toLowerCase()}`;
104475
104514
  }
104476
104515
  function suggestedCloneTarget(source2) {
104477
104516
  return `.tmp/repo/${groupId(source2)}`;
@@ -104551,10 +104590,14 @@ async function resolveGitRoot2(path4) {
104551
104590
  }
104552
104591
  async function verifyCheckout(input) {
104553
104592
  const actualRemote = await git2(input.checkout, ["remote", "get-url", "origin"]);
104554
- if (canonicalRemote(actualRemote) !== canonicalRemote(input.remote)) {
104593
+ const expectedRepository = repositoryPathIdentity(input.remote);
104594
+ const actualRepository = repositoryPathIdentity(actualRemote);
104595
+ if (actualRepository !== expectedRepository) {
104555
104596
  throw userInputError3("local repository origin does not match the registered source", {
104556
104597
  expected_remote: input.remote,
104557
104598
  actual_remote: actualRemote,
104599
+ expected_repository: expectedRepository,
104600
+ actual_repository: actualRepository,
104558
104601
  checkout: input.checkout
104559
104602
  });
104560
104603
  }
@@ -106258,6 +106301,153 @@ init_cliFeedback();
106258
106301
  init_errors();
106259
106302
  init_workspace();
106260
106303
  init_exitCode();
106304
+
106305
+ // src/project/entryCommand.ts
106306
+ init_workspace();
106307
+ import { existsSync as existsSync45 } from "node:fs";
106308
+ import { resolve as resolve30 } from "node:path";
106309
+ function shellQuote9(value) {
106310
+ return /^[A-Za-z0-9._/=-]+$/u.test(value) ? value : `'${value.replaceAll("'", `'"'"'`)}'`;
106311
+ }
106312
+ function workflowCommand(input) {
106313
+ const authorities = input.authorities ?? [];
106314
+ if (input.managed === true) {
106315
+ return [
106316
+ "context run --managed --until blocked-or-complete --format json",
106317
+ ...authorities.map((authority) => `--authority ${shellQuote9(authority)}`)
106318
+ ].join(" ");
106319
+ }
106320
+ return [
106321
+ "context status --format json",
106322
+ ...authorities.map((authority) => `--authority ${shellQuote9(authority)}`)
106323
+ ].join(" ");
106324
+ }
106325
+ function initCommand2(input, projectDir) {
106326
+ const args = [
106327
+ "context",
106328
+ "init",
106329
+ projectDir,
106330
+ "--language",
106331
+ input.language
106332
+ ];
106333
+ if (input.name !== undefined)
106334
+ args.push("--name", input.name);
106335
+ if (input.dev === true)
106336
+ args.push("--dev");
106337
+ if (input.debug === true)
106338
+ args.push("--debug");
106339
+ return args.map(shellQuote9).join(" ");
106340
+ }
106341
+ function readyResult(input, projectRoot, relocation) {
106342
+ const command2 = workflowCommand(input);
106343
+ return {
106344
+ schema: "context.entry.v1",
106345
+ state: relocation ? "workspace-relocation-required" : "workspace-ready",
106346
+ cwd: resolve30(input.cwd),
106347
+ workspace: {
106348
+ root: projectRoot,
106349
+ exists: true
106350
+ },
106351
+ next_action: {
106352
+ kind: relocation ? "enter-workspace" : "evaluate-workflow",
106353
+ command: relocation ? `cd ${shellQuote9(projectRoot)} && ${command2}` : command2,
106354
+ effect: "read",
106355
+ confirmation: "not-required"
106356
+ }
106357
+ };
106358
+ }
106359
+ function resolveContextEntry(input) {
106360
+ const cwd = resolve30(input.cwd);
106361
+ if (input.projectDir !== undefined) {
106362
+ const target2 = resolveContextProjectInitTarget(cwd, input.projectDir);
106363
+ if (existsSync45(target2) && isContextProjectRoot(target2)) {
106364
+ return readyResult(input, target2, target2 !== cwd);
106365
+ }
106366
+ return {
106367
+ schema: "context.entry.v1",
106368
+ state: "workspace-initialization-required",
106369
+ cwd,
106370
+ workspace: {
106371
+ root: target2,
106372
+ exists: existsSync45(target2)
106373
+ },
106374
+ next_action: {
106375
+ kind: "initialize-workspace",
106376
+ command: initCommand2(input, input.projectDir),
106377
+ effect: "write",
106378
+ confirmation: "required-unless-explicitly-requested"
106379
+ }
106380
+ };
106381
+ }
106382
+ const found = findContextProjectRoot(cwd);
106383
+ if (found !== null)
106384
+ return readyResult(input, found.projectRoot, false);
106385
+ const expectation = findContextWorkspaceExpectation(cwd);
106386
+ if (expectation !== null) {
106387
+ if (expectation.exists && isContextProjectRoot(expectation.workspaceRoot)) {
106388
+ return readyResult(input, expectation.workspaceRoot, true);
106389
+ }
106390
+ return {
106391
+ schema: "context.entry.v1",
106392
+ state: "workspace-initialization-required",
106393
+ cwd,
106394
+ workspace: {
106395
+ root: expectation.workspaceRoot,
106396
+ exists: expectation.exists
106397
+ },
106398
+ next_action: {
106399
+ kind: "initialize-workspace",
106400
+ command: `cd ${shellQuote9(expectation.markerRoot)} && ${initCommand2(input, expectation.workspaceDir)}`,
106401
+ effect: "write",
106402
+ confirmation: "required-unless-explicitly-requested"
106403
+ }
106404
+ };
106405
+ }
106406
+ const target = resolveContextProjectInitTarget(cwd, undefined);
106407
+ if (isContextProjectRoot(target)) {
106408
+ return readyResult(input, target, true);
106409
+ }
106410
+ return {
106411
+ schema: "context.entry.v1",
106412
+ state: "workspace-initialization-required",
106413
+ cwd,
106414
+ workspace: {
106415
+ root: target,
106416
+ exists: existsSync45(target)
106417
+ },
106418
+ next_action: {
106419
+ kind: "initialize-workspace",
106420
+ command: initCommand2(input, "context"),
106421
+ effect: "write",
106422
+ confirmation: "required-unless-explicitly-requested"
106423
+ }
106424
+ };
106425
+ }
106426
+ function formatContextEntry(result) {
106427
+ return `${JSON.stringify(result, null, 2)}
106428
+ `;
106429
+ }
106430
+
106431
+ // src/registerProjectLifecycleCommands.ts
106432
+ function registerProjectEntryCommand(program2) {
106433
+ program2.command("entry [project-dir]").description("Resolve the single Context agent entry for initialization or workflow evaluation").option("--name <name>", "display/package name override when initialization is required").option("--language <language>", "workspace and starter-template language: en | zh-CN", "en").option("--dev", "plan initialization with the locally linked @c4a/context SDK").option("--debug", "plan initialization with workspace-local tracing enabled").option("--managed", "use explicit current-conversation managed approval for workflow evaluation").addOption(new Option("--authority <authority>", "current-conversation scoped authority granted by the user; repeatable").argParser(collectWorkflowAuthorityOption).default([])).option("--format <format>", "output format: json", "json").action((projectDir, options) => {
106434
+ if (options.format !== "json") {
106435
+ throw new ContextError(ExitCode.UserError, "--format must be json", {
106436
+ category: ErrorCategory.UserInputInvalid
106437
+ });
106438
+ }
106439
+ process.stdout.write(formatContextEntry(resolveContextEntry({
106440
+ cwd: process.cwd(),
106441
+ ...projectDir === undefined ? {} : { projectDir },
106442
+ ...typeof options.name === "string" ? { name: options.name } : {},
106443
+ language: projectLanguage(options.language),
106444
+ ...options.dev === true ? { dev: true } : {},
106445
+ ...options.debug === true ? { debug: true } : {},
106446
+ ...options.managed === true ? { managed: true } : {},
106447
+ authorities: workflowAuthorities(options.authority)
106448
+ })));
106449
+ });
106450
+ }
106261
106451
  function registerProjectInitCommand(program2) {
106262
106452
  program2.command("init [project-dir]").description("Initialize a project-local context workspace").option("--name <name>", "display/package name override").option("--language <language>", "workspace and starter-template language: en | zh-CN").option("--dev", "initialize with the locally linked @c4a/context SDK").option("--debug", "enable workspace-local command and Agent Graph tracing").option("--allow-nonempty", "after explicit confirmation, preserve existing files and initialize inside a non-empty non-Context directory").action(async (projectDir, options) => {
106263
106453
  const targetRoot = resolveContextProjectInitTarget(process.cwd(), projectDir);
@@ -106385,29 +106575,29 @@ function registerProjectVerifyCommand(program2) {
106385
106575
  init_cliFeedback();
106386
106576
  init_errors();
106387
106577
  init_exitCode();
106388
- import { existsSync as existsSync45 } from "node:fs";
106578
+ import { existsSync as existsSync46 } from "node:fs";
106389
106579
  import { cp, mkdir as mkdir32, readdir as readdir21, readFile as readFile55, rename as rename5, rm as rm19, writeFile as writeFile27 } from "node:fs/promises";
106390
106580
  import { execFile as execFile7 } from "node:child_process";
106391
106581
  import { homedir as homedir2 } from "node:os";
106392
- import { dirname as dirname41, join as join70, resolve as resolve30 } from "node:path";
106582
+ import { dirname as dirname41, join as join70, resolve as resolve31 } from "node:path";
106393
106583
  import { fileURLToPath as fileURLToPath9 } from "node:url";
106394
106584
  import { promisify as promisify7 } from "node:util";
106395
106585
  var execFileAsync7 = promisify7(execFile7);
106396
106586
  var MARKETPLACE_NAME = "c4a";
106397
- var PLUGIN_ID = "context@c4a";
106398
- var PLUGIN_NAME = "context";
106399
- var LEGACY_PLUGIN_NAMES = [];
106587
+ var PLUGIN_ID = "c4a@c4a";
106588
+ var PLUGIN_NAME = "c4a";
106589
+ var LEGACY_PLUGIN_NAMES = ["context"];
106400
106590
  var ORPHAN_MARKER2 = ".orphaned_at";
106401
106591
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV2 = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
106402
106592
  var CLAUDE_PLUGIN_CACHE_HOME_ENV2 = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
106403
106593
  var ANSI_DIM = "\x1B[2m";
106404
106594
  var ANSI_YELLOW = "\x1B[33m";
106405
106595
  var ANSI_RESET = "\x1B[0m";
106406
- function shellQuote9(value) {
106596
+ function shellQuote10(value) {
106407
106597
  return `'${value.replace(/'/g, "'\\''")}'`;
106408
106598
  }
106409
106599
  function commandLine(command2, args) {
106410
- return [command2, ...args.map((arg) => shellQuote9(arg))].join(" ");
106600
+ return [command2, ...args.map((arg) => shellQuote10(arg))].join(" ");
106411
106601
  }
106412
106602
  function dim(value) {
106413
106603
  return `${ANSI_DIM}${value}${ANSI_RESET}`;
@@ -106442,7 +106632,7 @@ function packageCandidateDirs() {
106442
106632
  function pluginRootCandidates() {
106443
106633
  const envRoot = process.env.C4A_CONTEXT_PLUGIN_ROOT?.trim();
106444
106634
  if (envRoot)
106445
- return [resolve30(envRoot)];
106635
+ return [resolve31(envRoot)];
106446
106636
  const candidates = [];
106447
106637
  for (const dir of packageCandidateDirs()) {
106448
106638
  candidates.push(join70(dir, "plugins"));
@@ -106451,7 +106641,7 @@ function pluginRootCandidates() {
106451
106641
  return [...new Set(candidates)];
106452
106642
  }
106453
106643
  function isInstallablePluginRoot(root2) {
106454
- return existsSync45(join70(root2, ".claude-plugin", "marketplace.json")) && existsSync45(join70(root2, ".agents", "plugins", "marketplace.json")) && existsSync45(join70(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync45(join70(root2, "codex", ".codex-plugin", "plugin.json"));
106644
+ return existsSync46(join70(root2, ".claude-plugin", "marketplace.json")) && existsSync46(join70(root2, ".agents", "plugins", "marketplace.json")) && existsSync46(join70(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync46(join70(root2, "codex", ".codex-plugin", "plugin.json"));
106455
106645
  }
106456
106646
  function resolveBundledPluginsRoot() {
106457
106647
  const candidates = pluginRootCandidates();
@@ -106488,13 +106678,13 @@ async function runExternalOptional(command2, args) {
106488
106678
  async function commandAvailable(command2) {
106489
106679
  return runExternalOptional("sh", ["-lc", `command -v ${command2} >/dev/null 2>&1`]);
106490
106680
  }
106491
- async function claudePluginInstalled() {
106681
+ async function claudePluginInstalled(pluginId) {
106492
106682
  try {
106493
106683
  const { stdout } = await execFileAsync7("claude", ["plugin", "list", "--json"], {
106494
106684
  maxBuffer: 1024 * 1024
106495
106685
  });
106496
106686
  const parsed = JSON.parse(stdout);
106497
- return Array.isArray(parsed) && parsed.some((item) => item !== null && typeof item === "object" && ("id" in item) && item.id === PLUGIN_ID);
106687
+ return Array.isArray(parsed) && parsed.some((item) => item !== null && typeof item === "object" && ("id" in item) && item.id === pluginId);
106498
106688
  } catch {
106499
106689
  return false;
106500
106690
  }
@@ -106539,7 +106729,7 @@ function isStaleMarketplaceBlock(header, block) {
106539
106729
  return text5.includes('source_type = "local"') || text5.includes("/c4a-plugins") || text5.includes("context4ai/context");
106540
106730
  }
106541
106731
  function isStalePluginBlock(header) {
106542
- return header === `plugins."context@context"` || header === "plugins.context";
106732
+ return header === `plugins."context@context"` || header === `plugins."context@c4a"` || header === "plugins.context";
106543
106733
  }
106544
106734
  function pruneLegacyCodexConfigContent(content3) {
106545
106735
  const lines = content3.split(`
@@ -106592,7 +106782,7 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
106592
106782
  }
106593
106783
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
106594
106784
  const cacheRoot = join70(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
106595
- if (!existsSync45(cacheRoot))
106785
+ if (!existsSync46(cacheRoot))
106596
106786
  return;
106597
106787
  const versions = (await readdir21(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
106598
106788
  if (versions.length === 0)
@@ -106620,7 +106810,7 @@ async function isEmptyDir2(dir) {
106620
106810
  }
106621
106811
  async function pruneClaudeOrphanContextCache(dryRun, steps) {
106622
106812
  const cacheRoot = claudePluginCacheRoot();
106623
- if (!existsSync45(cacheRoot))
106813
+ if (!existsSync46(cacheRoot))
106624
106814
  return;
106625
106815
  const removed = [];
106626
106816
  const marketplaces = await readdir21(cacheRoot, { withFileTypes: true }).catch(() => []);
@@ -106628,14 +106818,14 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
106628
106818
  if (!marketplace.isDirectory())
106629
106819
  continue;
106630
106820
  const pluginDir = join70(cacheRoot, marketplace.name, PLUGIN_NAME);
106631
- if (!existsSync45(pluginDir))
106821
+ if (!existsSync46(pluginDir))
106632
106822
  continue;
106633
106823
  const versions = await readdir21(pluginDir, { withFileTypes: true }).catch(() => []);
106634
106824
  for (const version3 of versions) {
106635
106825
  if (!version3.isDirectory())
106636
106826
  continue;
106637
106827
  const versionDir = join70(pluginDir, version3.name);
106638
- if (!existsSync45(join70(versionDir, ORPHAN_MARKER2)))
106828
+ if (!existsSync46(join70(versionDir, ORPHAN_MARKER2)))
106639
106829
  continue;
106640
106830
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
106641
106831
  if (!dryRun) {
@@ -106662,12 +106852,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
106662
106852
  if (LEGACY_PLUGIN_NAMES.length === 0)
106663
106853
  return;
106664
106854
  const cacheRoot = claudePluginCacheRoot();
106665
- if (!existsSync45(cacheRoot))
106855
+ if (!existsSync46(cacheRoot))
106666
106856
  return;
106667
106857
  const removed = [];
106668
106858
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
106669
106859
  const pluginDir = join70(cacheRoot, MARKETPLACE_NAME, pluginName);
106670
- if (!existsSync45(pluginDir))
106860
+ if (!existsSync46(pluginDir))
106671
106861
  continue;
106672
106862
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
106673
106863
  if (!dryRun) {
@@ -106794,7 +106984,7 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
106794
106984
  const target = codexPluginCacheDir(version3);
106795
106985
  steps.push({
106796
106986
  agent: "codex",
106797
- command: `materialize Codex plugin cache: ${shellQuote9(source2)} -> ${shellQuote9(target)}`,
106987
+ command: `materialize Codex plugin cache: ${shellQuote10(source2)} -> ${shellQuote10(target)}`,
106798
106988
  status: dryRun ? "planned" : "ran"
106799
106989
  });
106800
106990
  if (dryRun)
@@ -106804,7 +106994,7 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
106804
106994
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
106805
106995
  await rm19(temporary, { recursive: true, force: true });
106806
106996
  await cp(source2, temporary, { recursive: true, force: true });
106807
- const hadPrevious = existsSync45(target);
106997
+ const hadPrevious = existsSync46(target);
106808
106998
  try {
106809
106999
  if (hadPrevious)
106810
107000
  await rename5(target, previous3);
@@ -106813,7 +107003,7 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
106813
107003
  await rm19(previous3, { recursive: true, force: true });
106814
107004
  } catch (error) {
106815
107005
  await rm19(temporary, { recursive: true, force: true });
106816
- if (hadPrevious && !existsSync45(target) && existsSync45(previous3))
107006
+ if (hadPrevious && !existsSync46(target) && existsSync46(previous3))
106817
107007
  await rename5(previous3, target);
106818
107008
  throw error;
106819
107009
  }
@@ -106825,6 +107015,13 @@ async function installClaude(root2, dryRun, steps) {
106825
107015
  const installArgs = ["plugin", "install", PLUGIN_ID, "--scope", "user"];
106826
107016
  steps.push({ agent: "claude", command: commandLine("claude", addArgs), status: dryRun ? "planned" : "ran" });
106827
107017
  if (dryRun) {
107018
+ for (const pluginName of LEGACY_PLUGIN_NAMES) {
107019
+ steps.push({
107020
+ agent: "claude",
107021
+ command: commandLine("claude", ["plugin", "uninstall", `${pluginName}@${MARKETPLACE_NAME}`, "--scope", "user"]),
107022
+ status: "planned"
107023
+ });
107024
+ }
106828
107025
  steps.push({ agent: "claude", command: commandLine("claude", installArgs), status: "planned" });
106829
107026
  return;
106830
107027
  }
@@ -106832,7 +107029,15 @@ async function installClaude(root2, dryRun, steps) {
106832
107029
  if (!added) {
106833
107030
  await runExternal("claude", ["plugin", "marketplace", "update", MARKETPLACE_NAME]);
106834
107031
  }
106835
- if (await claudePluginInstalled()) {
107032
+ for (const pluginName of LEGACY_PLUGIN_NAMES) {
107033
+ const legacyPluginId = `${pluginName}@${MARKETPLACE_NAME}`;
107034
+ if (!await claudePluginInstalled(legacyPluginId))
107035
+ continue;
107036
+ const uninstallArgs = ["plugin", "uninstall", legacyPluginId, "--scope", "user"];
107037
+ steps.push({ agent: "claude", command: commandLine("claude", uninstallArgs), status: "ran" });
107038
+ await runExternal("claude", uninstallArgs);
107039
+ }
107040
+ if (await claudePluginInstalled(PLUGIN_ID)) {
106836
107041
  const uninstallArgs = ["plugin", "uninstall", PLUGIN_ID, "--scope", "user"];
106837
107042
  steps.push({ agent: "claude", command: commandLine("claude", uninstallArgs), status: "ran" });
106838
107043
  await runExternal("claude", uninstallArgs);
@@ -106848,12 +107053,12 @@ async function installCodex(root2, dryRun, steps) {
106848
107053
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
106849
107054
  steps.push({
106850
107055
  agent: "codex",
106851
- command: `ensure ${shellQuote9(join70(codexHome(), "config.toml"))} registers local marketplace ${shellQuote9(MARKETPLACE_NAME)}`,
107056
+ command: `ensure ${shellQuote10(join70(codexHome(), "config.toml"))} registers local marketplace ${shellQuote10(MARKETPLACE_NAME)}`,
106852
107057
  status: dryRun ? "planned" : "ran"
106853
107058
  });
106854
107059
  steps.push({
106855
107060
  agent: "codex",
106856
- command: `ensure ${shellQuote9(join70(codexHome(), "config.toml"))} enables ${shellQuote9(PLUGIN_ID)}`,
107061
+ command: `ensure ${shellQuote10(join70(codexHome(), "config.toml"))} enables ${shellQuote10(PLUGIN_ID)}`,
106857
107062
  status: dryRun ? "planned" : "ran"
106858
107063
  });
106859
107064
  if (dryRun) {
@@ -107034,6 +107239,7 @@ function registerPackageCommands(program2) {
107034
107239
 
107035
107240
  // src/cli.ts
107036
107241
  var TOP_LEVEL_COMMANDS = new Set([
107242
+ "entry",
107037
107243
  "init",
107038
107244
  "plugin",
107039
107245
  "status",
@@ -107072,7 +107278,7 @@ function readPackageVersion() {
107072
107278
  let dir = dirname42(fileURLToPath10(import.meta.url));
107073
107279
  for (let i2 = 0;i2 < 8; i2++) {
107074
107280
  const pkg = join71(dir, "package.json");
107075
- if (existsSync46(pkg)) {
107281
+ if (existsSync47(pkg)) {
107076
107282
  const parsed = JSON.parse(readFileSync10(pkg, "utf8"));
107077
107283
  return parsed.version ?? "unknown";
107078
107284
  }
@@ -107089,10 +107295,10 @@ function readQuickstartPath() {
107089
107295
  let dir = dirname42(fileURLToPath10(import.meta.url));
107090
107296
  for (let i2 = 0;i2 < 8; i2++) {
107091
107297
  const candidate = join71(dir, "docs", "quickstart.md");
107092
- if (existsSync46(candidate))
107298
+ if (existsSync47(candidate))
107093
107299
  return candidate;
107094
107300
  const pkg = join71(dir, "package.json");
107095
- if (existsSync46(pkg))
107301
+ if (existsSync47(pkg))
107096
107302
  return candidate;
107097
107303
  const parent = dirname42(dir);
107098
107304
  if (parent === dir)
@@ -107185,6 +107391,7 @@ function createCliProgram() {
107185
107391
  });
107186
107392
  const baseHelpInformation = program2.helpInformation.bind(program2);
107187
107393
  program2.helpInformation = () => `${headerHelpText()}${baseHelpInformation()}${quickstartHelpText()}`;
107394
+ registerProjectEntryCommand(program2);
107188
107395
  registerProjectInitCommand(program2);
107189
107396
  registerPluginCommands(program2);
107190
107397
  registerDebugCommands(program2);