@primitive.ai/prim 0.1.0-alpha.90 → 0.1.0-alpha.92

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 (45) hide show
  1. package/README.md +20 -12
  2. package/SKILL.md +6 -6
  3. package/dist/chunk-26P57LAR.js +1491 -0
  4. package/dist/{chunk-LMRYZL3D.js → chunk-5AFRMOPX.js} +1 -1
  5. package/dist/{chunk-RO3F6JYV.js → chunk-5GYQ4J3D.js} +2 -2
  6. package/dist/chunk-5HRR4AOR.js +264 -0
  7. package/dist/{chunk-3EEFL6NJ.js → chunk-67VNLLBN.js} +261 -1
  8. package/dist/{chunk-UZPBB7V4.js → chunk-ADUTW66W.js} +60 -48
  9. package/dist/{chunk-LEMX3IOG.js → chunk-BTNNEH2W.js} +1 -1
  10. package/dist/{chunk-YWO7O6QG.js → chunk-FBAYCS3X.js} +2 -2
  11. package/dist/{chunk-R26A7TWY.js → chunk-FKXFUUWJ.js} +1 -1
  12. package/dist/chunk-H4UNYFUC.js +196 -0
  13. package/dist/{chunk-CUE2LKLR.js → chunk-KFXF2V5G.js} +1 -1
  14. package/dist/{chunk-6IWNH776.js → chunk-LFFLHSQO.js} +4 -3
  15. package/dist/{chunk-C7T7B45R.js → chunk-LGGMJYY4.js} +150 -21
  16. package/dist/{chunk-MAZWKJGL.js → chunk-M6RIJVRE.js} +42 -232
  17. package/dist/{chunk-2JRX7ZR4.js → chunk-NAHHFSLH.js} +16 -5
  18. package/dist/{chunk-FI3LIRCB.js → chunk-OAAP2MY6.js} +2 -2
  19. package/dist/{chunk-Z7YPFWAZ.js → chunk-PCVGBE5B.js} +10 -268
  20. package/dist/chunk-WX52U7Z2.js +112 -0
  21. package/dist/{chunk-PPQYQEIR.js → chunk-ZB4F75SZ.js} +28 -0
  22. package/dist/daemon/server.js +30 -21
  23. package/dist/hook-runtime/daemon/server.js +30 -21
  24. package/dist/hook-runtime/hooks/post-commit.js +20 -20
  25. package/dist/hook-runtime/hooks/post-rewrite.js +20 -20
  26. package/dist/hook-runtime/hooks/post-tool-use.js +666 -147
  27. package/dist/hook-runtime/hooks/pre-tool-use.js +659 -111
  28. package/dist/hook-runtime/hooks/prim-hook.js +627 -111
  29. package/dist/hook-runtime/hooks/session-end.js +610 -27
  30. package/dist/hook-runtime/hooks/session-start.js +1132 -533
  31. package/dist/hook-runtime/index.js +764 -267
  32. package/dist/hook-runtime/statusline-main.js +48 -4
  33. package/dist/hooks/post-commit.js +11 -9
  34. package/dist/hooks/post-rewrite.js +11 -9
  35. package/dist/hooks/post-tool-use.js +73 -48
  36. package/dist/hooks/pre-commit.js +4 -4
  37. package/dist/hooks/pre-tool-use.js +46 -44
  38. package/dist/hooks/prim-hook.js +47 -25
  39. package/dist/hooks/session-end.js +15 -26
  40. package/dist/hooks/session-start.js +59 -32
  41. package/dist/index.js +561 -1430
  42. package/dist/statusline-main.js +48 -4
  43. package/package.json +1 -1
  44. package/dist/chunk-PMRDE2DA.js +0 -310
  45. package/dist/chunk-WB7AUZ4C.js +0 -52
@@ -4963,7 +4963,7 @@ var require_rc = __commonJS({
4963
4963
  "node_modules/.pnpm/rc@1.2.8/node_modules/rc/index.js"(exports, module) {
4964
4964
  "use strict";
4965
4965
  var cc = require_utils();
4966
- var join27 = __require("path").join;
4966
+ var join28 = __require("path").join;
4967
4967
  var deepExtend = require_deep_extend();
4968
4968
  var etc = "/etc";
4969
4969
  var win = process.platform === "win32";
@@ -4988,15 +4988,15 @@ var require_rc = __commonJS({
4988
4988
  }
4989
4989
  if (!win)
4990
4990
  [
4991
- join27(etc, name, "config"),
4992
- join27(etc, name + "rc")
4991
+ join28(etc, name, "config"),
4992
+ join28(etc, name + "rc")
4993
4993
  ].forEach(addConfigFile);
4994
4994
  if (home)
4995
4995
  [
4996
- join27(home, ".config", name, "config"),
4997
- join27(home, ".config", name),
4998
- join27(home, "." + name, "config"),
4999
- join27(home, "." + name + "rc")
4996
+ join28(home, ".config", name, "config"),
4997
+ join28(home, ".config", name),
4998
+ join28(home, "." + name, "config"),
4999
+ join28(home, "." + name + "rc")
5000
5000
  ].forEach(addConfigFile);
5001
5001
  addConfigFile(cc.find("." + name + "rc"));
5002
5002
  if (env4.config) addConfigFile(env4.config);
@@ -8896,7 +8896,7 @@ var require_ucs2length = __commonJS({
8896
8896
  });
8897
8897
 
8898
8898
  // src/index.ts
8899
- import { readFileSync as readFileSync21 } from "fs";
8899
+ import { readFileSync as readFileSync22 } from "fs";
8900
8900
  import { dirname as dirname18, resolve as resolve10 } from "path";
8901
8901
  import { fileURLToPath as fileURLToPath7 } from "url";
8902
8902
 
@@ -13041,7 +13041,7 @@ var PRIM_REPO_SYNC_REPOSITORY_KEY = "prim.repoSyncRepository";
13041
13041
  var PRIM_REPO_BINDING_STATE_KEY = "prim.repoBindingState";
13042
13042
  var GIT_TIMEOUT_MS2 = 1e3;
13043
13043
  var REPO_SYNC_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
13044
- var PROJECT_INSTALL_FILES = [".claude/settings.json", ".codex/hooks.json"];
13044
+ var PROJECT_INSTALL_FILES = [".claude/settings.json", ".codex/hooks.json", ".cursor/hooks.json"];
13045
13045
  var PRIM_HOOK_BINS = ["prim-hook", "prim-pre-tool-use", "prim-post-tool-use"];
13046
13046
  function repoActiveFlag(cwd) {
13047
13047
  try {
@@ -14850,7 +14850,7 @@ function validate23(data, { instancePath = "", parentData, parentDataProperty, r
14850
14850
  }
14851
14851
  validate23.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
14852
14852
  var isDecisionCollectScopeResponse = validate24;
14853
- var schema39 = { "type": "object", "properties": { "policy": { "anyOf": [{ "type": "object", "properties": { "repositories": { "type": "array", "items": { "type": "string" } }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } }, "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, "updatedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": ["updatedAt"], "additionalProperties": {} }, { "type": "null" }] }, "collectScopeVersion": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "callerIncluded": { "type": "boolean" } }, "required": ["policy", "collectScopeVersion", "callerIncluded"], "additionalProperties": {} };
14853
+ var schema39 = { "type": "object", "properties": { "policy": { "anyOf": [{ "type": "object", "properties": { "repositories": { "type": "array", "items": { "type": "string" } }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } }, "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, "updatedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": ["updatedAt"], "additionalProperties": {} }, { "type": "null" }] }, "collectScopeVersion": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "callerIncluded": { "type": "boolean" } }, "required": ["policy", "collectScopeVersion", "callerIncluded"], "additionalProperties": {} };
14854
14854
  function validate24(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
14855
14855
  ;
14856
14856
  let vErrors = null;
@@ -15401,7 +15401,7 @@ function validate24(data, { instancePath = "", parentData, parentDataProperty, r
15401
15401
  }
15402
15402
  errors++;
15403
15403
  }
15404
- if (!(data18 === "claude_code" || data18 === "codex" || data18 === "hermes")) {
15404
+ if (!(data18 === "claude_code" || data18 === "codex" || data18 === "cursor" || data18 === "hermes")) {
15405
15405
  const err34 = { instancePath: instancePath + "/policy/users/" + i4 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionCollectScopeResponse/properties/policy/anyOf/0/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema39.properties.policy.anyOf[0].properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
15406
15406
  if (vErrors === null) {
15407
15407
  vErrors = [err34];
@@ -16170,7 +16170,7 @@ function validate26(data, { instancePath = "", parentData, parentDataProperty, r
16170
16170
  return errors === 0;
16171
16171
  }
16172
16172
  validate26.evaluated = { "dynamicProps": true, "dynamicItems": false };
16173
- var schema45 = { "type": "object", "properties": { "intent": { "type": "string", "minLength": 1, "maxLength": 500 }, "attribution": { "type": "string", "enum": ["user", "agent", "unknown"] }, "kind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "area": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "files": { "type": "array", "items": { "type": "string" } }, "protocolVersion": { "type": "number", "const": 3 }, "repoSyncId": { "type": "string" }, "scope": { "default": {}, "type": "object", "properties": { "location": { "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, "time": { "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "additionalProperties": {} }, "stageOverride": { "type": "string", "enum": ["candidate", "draft", "adopted"] } }, "required": ["intent"], "additionalProperties": {}, "x-primitive-runtime-refinements": ["degrade_invalid_rollout_fields", "degrade_invalid_location_scope", "degrade_invalid_time_scope"] };
16173
+ var schema45 = { "type": "object", "properties": { "intent": { "type": "string", "minLength": 1, "maxLength": 500 }, "attribution": { "type": "string", "enum": ["user", "agent", "unknown"] }, "kind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "area": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "files": { "type": "array", "items": { "type": "string" } }, "protocolVersion": { "type": "number", "const": 3 }, "repoSyncId": { "type": "string" }, "scope": { "default": {}, "type": "object", "properties": { "location": { "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, "time": { "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "additionalProperties": {} }, "stageOverride": { "type": "string", "enum": ["candidate", "draft", "adopted"] } }, "required": ["intent"], "additionalProperties": {}, "x-primitive-runtime-refinements": ["degrade_invalid_rollout_fields", "degrade_invalid_location_scope", "degrade_invalid_time_scope"] };
16174
16174
  function validate27(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
16175
16175
  ;
16176
16176
  let vErrors = null;
@@ -16874,7 +16874,7 @@ function validate27(data, { instancePath = "", parentData, parentDataProperty, r
16874
16874
  }
16875
16875
  errors++;
16876
16876
  }
16877
- if (!(data34 === "claude_code" || data34 === "codex" || data34 === "hermes")) {
16877
+ if (!(data34 === "claude_code" || data34 === "codex" || data34 === "cursor" || data34 === "hermes")) {
16878
16878
  const err19 = { instancePath: instancePath + "/scope/users/" + i6 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionCreateRequest/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema45.properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
16879
16879
  if (vErrors === null) {
16880
16880
  vErrors = [err19];
@@ -17102,7 +17102,7 @@ function validate27(data, { instancePath = "", parentData, parentDataProperty, r
17102
17102
  return errors === 0;
17103
17103
  }
17104
17104
  validate27.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
17105
- var schema47 = { "type": "object", "properties": { "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "createdAt": { "type": "number" }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["decisionId", "shortId", "createdAt"], "additionalProperties": {} };
17105
+ var schema47 = { "type": "object", "properties": { "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "createdAt": { "type": "number" }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["decisionId", "shortId", "createdAt"], "additionalProperties": {} };
17106
17106
  function validate28(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
17107
17107
  ;
17108
17108
  let vErrors = null;
@@ -17638,7 +17638,7 @@ function validate28(data, { instancePath = "", parentData, parentDataProperty, r
17638
17638
  }
17639
17639
  errors++;
17640
17640
  }
17641
- if (!(data22 === "claude_code" || data22 === "codex" || data22 === "hermes")) {
17641
+ if (!(data22 === "claude_code" || data22 === "codex" || data22 === "cursor" || data22 === "hermes")) {
17642
17642
  const err19 = { instancePath: instancePath + "/scope/users/" + i3 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionCreateResponse/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema47.properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
17643
17643
  if (vErrors === null) {
17644
17644
  vErrors = [err19];
@@ -17870,7 +17870,7 @@ function validate28(data, { instancePath = "", parentData, parentDataProperty, r
17870
17870
  return errors === 0;
17871
17871
  }
17872
17872
  validate28.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
17873
- var schema49 = { "type": "object", "properties": { "decision": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "intentKind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "area": { "type": "string" }, "producerKind": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] }, "supersededBy": { "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "confirmed": { "type": "boolean" }, "respondedAt": { "type": "number" }, "fanOut": { "type": "number" }, "classifiedAt": { "type": "number" }, "authorName": { "type": "string" } }, "required": ["id", "intent", "intentKind", "alternatives", "stage", "status", "supersededBy", "confidence", "classifiedAt", "authorName"], "additionalProperties": {} }, "files": { "type": "array", "items": { "type": "string" } }, "flags": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": ["file_edit", "supersession", "invalidation", "confirmation_request"] }, "file": { "type": "string" }, "flaggedAt": { "type": "number" }, "acknowledgedAt": { "type": "number" }, "gateVerdict": { "type": "string" }, "reason": { "type": "string" } }, "required": ["type", "flaggedAt"], "additionalProperties": {} } }, "dependsOn": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "dependents": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 }, "displayName": { "type": "string" } }, "required": ["kind", "userId", "displayName"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "truncated": { "type": "boolean" } }, "required": ["decision", "files", "flags", "dependsOn", "dependents", "scope", "truncated"], "additionalProperties": {} };
17873
+ var schema49 = { "type": "object", "properties": { "decision": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "intentKind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "area": { "type": "string" }, "producerKind": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] }, "supersededBy": { "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "confirmed": { "type": "boolean" }, "respondedAt": { "type": "number" }, "fanOut": { "type": "number" }, "classifiedAt": { "type": "number" }, "authorName": { "type": "string" } }, "required": ["id", "intent", "intentKind", "alternatives", "stage", "status", "supersededBy", "confidence", "classifiedAt", "authorName"], "additionalProperties": {} }, "files": { "type": "array", "items": { "type": "string" } }, "flags": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": ["file_edit", "supersession", "invalidation", "confirmation_request"] }, "file": { "type": "string" }, "flaggedAt": { "type": "number" }, "acknowledgedAt": { "type": "number" }, "gateVerdict": { "type": "string" }, "reason": { "type": "string" } }, "required": ["type", "flaggedAt"], "additionalProperties": {} } }, "dependsOn": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "dependents": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 }, "displayName": { "type": "string" } }, "required": ["kind", "userId", "displayName"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "truncated": { "type": "boolean" } }, "required": ["decision", "files", "flags", "dependsOn", "dependents", "scope", "truncated"], "additionalProperties": {} };
17874
17874
  function validate29(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
17875
17875
  ;
17876
17876
  let vErrors = null;
@@ -19164,7 +19164,7 @@ function validate29(data, { instancePath = "", parentData, parentDataProperty, r
19164
19164
  }
19165
19165
  errors++;
19166
19166
  }
19167
- if (!(data70 === "claude_code" || data70 === "codex" || data70 === "hermes")) {
19167
+ if (!(data70 === "claude_code" || data70 === "codex" || data70 === "cursor" || data70 === "hermes")) {
19168
19168
  const err24 = { instancePath: instancePath + "/scope/users/" + i9 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionDetailResponse/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema49.properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
19169
19169
  if (vErrors === null) {
19170
19170
  vErrors = [err24];
@@ -19727,7 +19727,7 @@ function validate33(data, { instancePath = "", parentData, parentDataProperty, r
19727
19727
  }
19728
19728
  validate33.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
19729
19729
  var isDecisionRescopeRequest = validate34;
19730
- var schema59 = { "type": "object", "properties": { "id": { "type": "string" }, "location": { "anyOf": [{ "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, { "type": "null" }] }, "time": { "anyOf": [{ "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, { "type": "null" }] }, "users": { "anyOf": [{ "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, { "type": "null" }] } }, "required": ["id"], "additionalProperties": {} };
19730
+ var schema59 = { "type": "object", "properties": { "id": { "type": "string" }, "location": { "anyOf": [{ "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, { "type": "null" }] }, "time": { "anyOf": [{ "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, { "type": "null" }] }, "users": { "anyOf": [{ "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, { "type": "null" }] } }, "required": ["id"], "additionalProperties": {} };
19731
19731
  function validate34(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
19732
19732
  ;
19733
19733
  let vErrors = null;
@@ -20368,7 +20368,7 @@ function validate34(data, { instancePath = "", parentData, parentDataProperty, r
20368
20368
  }
20369
20369
  errors++;
20370
20370
  }
20371
- if (!(data19 === "claude_code" || data19 === "codex" || data19 === "hermes")) {
20371
+ if (!(data19 === "claude_code" || data19 === "codex" || data19 === "cursor" || data19 === "hermes")) {
20372
20372
  const err38 = { instancePath: instancePath + "/users/" + i3 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionRescopeRequest/properties/users/anyOf/0/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema59.properties.users.anyOf[0].items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
20373
20373
  if (vErrors === null) {
20374
20374
  vErrors = [err38];
@@ -20597,7 +20597,7 @@ function validate34(data, { instancePath = "", parentData, parentDataProperty, r
20597
20597
  }
20598
20598
  validate34.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
20599
20599
  var isDecisionRescopeResponse = validate35;
20600
- var schema61 = { "anyOf": [{ "type": "object", "properties": { "outcome": { "type": "string", "const": "no_op" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "stage", "scope"], "additionalProperties": {} }, { "type": "object", "properties": { "outcome": { "type": "string", "const": "ok" }, "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "decisionId", "stage", "scope"], "additionalProperties": {} }] };
20600
+ var schema61 = { "anyOf": [{ "type": "object", "properties": { "outcome": { "type": "string", "const": "no_op" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "stage", "scope"], "additionalProperties": {} }, { "type": "object", "properties": { "outcome": { "type": "string", "const": "ok" }, "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "decisionId", "stage", "scope"], "additionalProperties": {} }] };
20601
20601
  function validate35(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
20602
20602
  ;
20603
20603
  let vErrors = null;
@@ -21235,7 +21235,7 @@ function validate35(data, { instancePath = "", parentData, parentDataProperty, r
21235
21235
  }
21236
21236
  errors++;
21237
21237
  }
21238
- if (!(data21 === "claude_code" || data21 === "codex" || data21 === "hermes")) {
21238
+ if (!(data21 === "claude_code" || data21 === "codex" || data21 === "cursor" || data21 === "hermes")) {
21239
21239
  const err41 = { instancePath: instancePath + "/scope/users/" + i3 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionRescopeResponse/anyOf/0/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema61.anyOf[0].properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
21240
21240
  if (vErrors === null) {
21241
21241
  vErrors = [err41];
@@ -22159,7 +22159,7 @@ function validate35(data, { instancePath = "", parentData, parentDataProperty, r
22159
22159
  }
22160
22160
  errors++;
22161
22161
  }
22162
- if (!(data49 === "claude_code" || data49 === "codex" || data49 === "hermes")) {
22162
+ if (!(data49 === "claude_code" || data49 === "codex" || data49 === "cursor" || data49 === "hermes")) {
22163
22163
  const err100 = { instancePath: instancePath + "/scope/users/" + i8 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionRescopeResponse/anyOf/1/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema61.anyOf[1].properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
22164
22164
  if (vErrors === null) {
22165
22165
  vErrors = [err100];
@@ -27811,7 +27811,7 @@ function validate50(data, { instancePath = "", parentData, parentDataProperty, r
27811
27811
  }
27812
27812
  validate50.evaluated = { "dynamicProps": true, "dynamicItems": false };
27813
27813
  var isMoveIngestRequest = validate51;
27814
- var schema93 = { "type": "object", "properties": { "batch": { "type": "array", "items": { "anyOf": [{ "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "const": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType", "capturedOrganizationId", "captureAuthorityKind", "decisionLifecycleProtocolVersion", "envelopeVersion"], "additionalProperties": {} }, { "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "exclusiveMaximum": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType"], "additionalProperties": {} }] } } }, "required": ["batch"], "additionalProperties": {} };
27814
+ var schema93 = { "type": "object", "properties": { "batch": { "type": "array", "items": { "anyOf": [{ "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "const": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType", "capturedOrganizationId", "captureAuthorityKind", "decisionLifecycleProtocolVersion", "envelopeVersion"], "additionalProperties": {} }, { "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "exclusiveMaximum": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType"], "additionalProperties": {} }] } } }, "required": ["batch"], "additionalProperties": {} };
27815
27815
  var pattern8 = new RegExp("^[A-Za-z0-9_-]+$", "u");
27816
27816
  function validate51(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
27817
27817
  ;
@@ -28065,7 +28065,7 @@ function validate51(data, { instancePath = "", parentData, parentDataProperty, r
28065
28065
  }
28066
28066
  errors++;
28067
28067
  }
28068
- if (!(data10 === "claude_code" || data10 === "codex" || data10 === "hermes")) {
28068
+ if (!(data10 === "claude_code" || data10 === "codex" || data10 === "cursor" || data10 === "hermes")) {
28069
28069
  const err16 = { instancePath: instancePath + "/batch/" + i0 + "/producer", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/MoveIngestRequest/properties/batch/items/anyOf/0/properties/producer/enum", keyword: "enum", params: { allowedValues: schema93.properties.batch.items.anyOf[0].properties.producer.enum }, message: "must be equal to one of the allowed values" };
28070
28070
  if (vErrors === null) {
28071
28071
  vErrors = [err16];
@@ -28377,7 +28377,7 @@ function validate51(data, { instancePath = "", parentData, parentDataProperty, r
28377
28377
  }
28378
28378
  errors++;
28379
28379
  }
28380
- if (!(data21 === "claude_code" || data21 === "codex" || data21 === "hermes")) {
28380
+ if (!(data21 === "claude_code" || data21 === "codex" || data21 === "cursor" || data21 === "hermes")) {
28381
28381
  const err38 = { instancePath: instancePath + "/batch/" + i0 + "/producer", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/MoveIngestRequest/properties/batch/items/anyOf/1/properties/producer/enum", keyword: "enum", params: { allowedValues: schema93.properties.batch.items.anyOf[1].properties.producer.enum }, message: "must be equal to one of the allowed values" };
28382
28382
  if (vErrors === null) {
28383
28383
  vErrors = [err38];
@@ -28514,7 +28514,7 @@ function validate51(data, { instancePath = "", parentData, parentDataProperty, r
28514
28514
  return errors === 0;
28515
28515
  }
28516
28516
  validate51.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
28517
- var schema95 = { "type": "object", "properties": { "protocolVersion": { "type": "number", "const": 3 }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] }, "sessionId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "invocationId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "repoSyncId": { "type": "string", "pattern": "^[A-Za-z0-9]{1,64}$" }, "paths": { "maxItems": 32, "type": "array", "items": { "type": "string" } }, "coverage": { "type": "string", "enum": ["complete", "unverified"] }, "branch": { "type": "string", "maxLength": 255, "pattern": "^(?!@?$)(?!\\/)(?!.*\\/$)(?!.*\\/\\/)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*(?:^|\\/)[^/]*\\.lock(?:\\/|$))(?!.*\\.\\.)(?!.*@\\{)(?!.*[~^:?*\\\\]).+$" }, "clientMode": { "type": "string", "enum": ["block", "warn"] }, "clientVersion": { "type": "string", "maxLength": 32, "pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]*$" }, "proposal": { "type": "string" } }, "required": ["protocolVersion", "agent", "sessionId", "invocationId", "repoSyncId", "paths", "coverage", "proposal"], "additionalProperties": false, "x-primitive-runtime-refinements": ["canonical_repository_paths", "unique_repository_paths", "complete_coverage_requires_path", "proposal_utf8_max_6144", "degrade_invalid_rollout_fields", "degrade_invalid_branch"] };
28517
+ var schema95 = { "type": "object", "properties": { "protocolVersion": { "type": "number", "const": 3 }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] }, "sessionId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "invocationId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "repoSyncId": { "type": "string", "pattern": "^[A-Za-z0-9]{1,64}$" }, "paths": { "maxItems": 32, "type": "array", "items": { "type": "string" } }, "coverage": { "type": "string", "enum": ["complete", "unverified"] }, "branch": { "type": "string", "maxLength": 255, "pattern": "^(?!@?$)(?!\\/)(?!.*\\/$)(?!.*\\/\\/)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*(?:^|\\/)[^/]*\\.lock(?:\\/|$))(?!.*\\.\\.)(?!.*@\\{)(?!.*[~^:?*\\\\]).+$" }, "clientMode": { "type": "string", "enum": ["block", "warn"] }, "clientVersion": { "type": "string", "maxLength": 32, "pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]*$" }, "proposal": { "type": "string" } }, "required": ["protocolVersion", "agent", "sessionId", "invocationId", "repoSyncId", "paths", "coverage", "proposal"], "additionalProperties": false, "x-primitive-runtime-refinements": ["canonical_repository_paths", "unique_repository_paths", "complete_coverage_requires_path", "proposal_utf8_max_6144", "degrade_invalid_rollout_fields", "degrade_invalid_branch"] };
28518
28518
  var pattern10 = new RegExp("^[A-Za-z0-9._:-]{1,128}$", "u");
28519
28519
  var pattern12 = new RegExp("^[A-Za-z0-9]{1,64}$", "u");
28520
28520
  var pattern13 = new RegExp("^(?!@?$)(?!\\/)(?!.*\\/$)(?!.*\\/\\/)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*(?:^|\\/)[^/]*\\.lock(?:\\/|$))(?!.*\\.\\.)(?!.*@\\{)(?!.*[~^:?*\\\\]).+$", "u");
@@ -28570,7 +28570,7 @@ function validate52(data, { instancePath = "", parentData, parentDataProperty, r
28570
28570
  validate52.errors = [{ instancePath: instancePath + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/PreflightRequestV3/properties/agent/type", keyword: "type", params: { type: "string" }, message: "must be string" }];
28571
28571
  return false;
28572
28572
  }
28573
- if (!(data1 === "claude_code" || data1 === "codex" || data1 === "hermes")) {
28573
+ if (!(data1 === "claude_code" || data1 === "codex" || data1 === "cursor" || data1 === "hermes")) {
28574
28574
  validate52.errors = [{ instancePath: instancePath + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/PreflightRequestV3/properties/agent/enum", keyword: "enum", params: { allowedValues: schema95.properties.agent.enum }, message: "must be equal to one of the allowed values" }];
28575
28575
  return false;
28576
28576
  }
@@ -31883,7 +31883,7 @@ function optionalUserScopeMembers(record2) {
31883
31883
  members.push({ kind: "role", role: candidate.role });
31884
31884
  continue;
31885
31885
  }
31886
- if (candidate.kind === "agent" && (candidate.agent === "claude_code" || candidate.agent === "codex" || candidate.agent === "hermes")) {
31886
+ if (candidate.kind === "agent" && (candidate.agent === "claude_code" || candidate.agent === "codex" || candidate.agent === "cursor" || candidate.agent === "hermes")) {
31887
31887
  members.push({ kind: "agent", agent: candidate.agent });
31888
31888
  continue;
31889
31889
  }
@@ -32187,7 +32187,7 @@ function stableHookCommand(bin, args = "") {
32187
32187
  // it as inert data during the rolling window so an older uninstall or
32188
32188
  // reinstall can remove the stable entry without invoking npm or PATH.
32189
32189
  `prim_legacy_reader='-p ${PKG_NAME}@stable prim-shim.sh ${bin} '; `,
32190
- 'prim_absolute() { case "$1" in /*) ;; *) return 1 ;; esac; case "$1" in [[:space:]]*|*[[:space:]]|*//*|*/./*|*/../*|*/.|*/..|?*/) return 1 ;; esac; }; ',
32190
+ 'prim_absolute() { case "$1" in [/]* ) ;; *) return 1 ;; esac; case "$1" in [[:space:]]*|*[[:space:]]|*[/][/]*|*[/].[/]*|*[/]..[/]*|*[/].|*[/]..|?*[/]) return 1 ;; esac; }; ',
32191
32191
  'prim_config=${PRIM_CONFIG_DIR:-}; if ! prim_absolute "$prim_config"; then prim_config=${XDG_CONFIG_HOME:-}; if prim_absolute "$prim_config"; then ',
32192
32192
  'case "$prim_config" in /) prim_config=/prim ;; *) prim_config="$prim_config/prim" ;; esac; ',
32193
32193
  'else prim_home=${HOME:-}; prim_absolute "$prim_home" || exit 78; case "$prim_home" in /) prim_config=/.config/prim ;; *) prim_config="$prim_home/.config/prim" ;; esac; ',
@@ -34963,7 +34963,7 @@ import {
34963
34963
  utimesSync,
34964
34964
  writeFileSync as writeFileSync6
34965
34965
  } from "fs";
34966
- import { dirname as dirname8, isAbsolute as isAbsolute5, join as join10, resolve as resolve5 } from "path";
34966
+ import { delimiter, dirname as dirname8, isAbsolute as isAbsolute5, join as join10, resolve as resolve5 } from "path";
34967
34967
  var HOOK_RUNTIME_SCHEMA_VERSION = 1;
34968
34968
  var DIRECTORY_MODE2 = 448;
34969
34969
  var DATA_FILE_MODE = 384;
@@ -35313,11 +35313,28 @@ function writeRelease(sourceDir, releaseDir, manifest, releasesDir) {
35313
35313
  rmSync4(stagingDir, { recursive: true, force: true });
35314
35314
  }
35315
35315
  }
35316
+ function stableNodePath(execPath = process.execPath, searchPath = process.env.PATH ?? "") {
35317
+ let target;
35318
+ try {
35319
+ target = realpathSync2(execPath);
35320
+ } catch {
35321
+ return execPath;
35322
+ }
35323
+ for (const directory of searchPath.split(delimiter)) {
35324
+ if (!isAbsolute5(directory)) continue;
35325
+ const candidate = join10(directory, "node");
35326
+ try {
35327
+ if (realpathSync2(candidate) === target) return candidate;
35328
+ } catch {
35329
+ }
35330
+ }
35331
+ return execPath;
35332
+ }
35316
35333
  function stageHookRuntime(options = {}) {
35317
35334
  const root = packageRoot();
35318
35335
  const sourceDir = options.sourceDir ?? (root ? join10(root, "dist", "hook-runtime") : null);
35319
35336
  const version = options.version ?? packageVersion();
35320
- const nodePath = resolve5(options.nodePath ?? process.execPath);
35337
+ const nodePath = resolve5(options.nodePath ?? stableNodePath());
35321
35338
  if (!sourceDir || !version || compareSemver(version, version) !== 0 || !isAbsolute5(nodePath) || /[\r\n]/u.test(nodePath)) {
35322
35339
  throw new Error("cannot stage hook runtime: package identity is unavailable");
35323
35340
  }
@@ -35805,7 +35822,7 @@ function performPermissionInstall(scope) {
35805
35822
  };
35806
35823
  }
35807
35824
  function performStatus() {
35808
- const statusFor = (path9) => {
35825
+ const statusFor2 = (path9) => {
35809
35826
  const settings = readSettings(path9);
35810
35827
  return {
35811
35828
  path: path9,
@@ -35818,7 +35835,7 @@ function performStatus() {
35818
35835
  statuslineState: statuslineState(settings)
35819
35836
  };
35820
35837
  };
35821
- return { user: statusFor(USER_SCOPE_PATH), project: statusFor(projectScopePath()) };
35838
+ return { user: statusFor2(USER_SCOPE_PATH), project: statusFor2(projectScopePath()) };
35822
35839
  }
35823
35840
  function resolveScope(input) {
35824
35841
  if (input === void 0 || input === "project") {
@@ -36017,7 +36034,7 @@ function performUninstall2(scope) {
36017
36034
  return resultFor(scope, path9, after, changed);
36018
36035
  }
36019
36036
  function performStatus2() {
36020
- const statusFor = (path9) => {
36037
+ const statusFor2 = (path9) => {
36021
36038
  const settings = readSettings(path9);
36022
36039
  return {
36023
36040
  path: path9,
@@ -36027,7 +36044,7 @@ function performStatus2() {
36027
36044
  complete: hasCompleteHookRegistration2(settings)
36028
36045
  };
36029
36046
  };
36030
- return { user: statusFor(USER_SCOPE_PATH2), project: statusFor(projectScopePath2()) };
36047
+ return { user: statusFor2(USER_SCOPE_PATH2), project: statusFor2(projectScopePath2()) };
36031
36048
  }
36032
36049
  function resolveScope2(input) {
36033
36050
  if (input === void 0 || input === "project") {
@@ -36079,14 +36096,302 @@ ${line("project", result.project)}`);
36079
36096
  });
36080
36097
  }
36081
36098
 
36099
+ // src/commands/cursor-install.ts
36100
+ import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
36101
+ import { homedir as homedir7 } from "os";
36102
+ import { isAbsolute as isAbsolute6, join as join13 } from "path";
36103
+ var CAPTURE_BIN3 = "prim-hook";
36104
+ var GATE_BIN3 = "prim-pre-tool-use";
36105
+ var POST_TOOL_BIN = "prim-post-tool-use";
36106
+ var SESSION_START_BIN3 = "prim-session-start";
36107
+ var SESSION_END_BIN2 = "prim-session-end";
36108
+ var STATUSLINE_BIN2 = "prim-statusline";
36109
+ var PRIM_BINS3 = [CAPTURE_BIN3, GATE_BIN3, POST_TOOL_BIN, SESSION_START_BIN3, SESSION_END_BIN2];
36110
+ var CURSOR_EVENTS = [
36111
+ "sessionStart",
36112
+ "beforeSubmitPrompt",
36113
+ "preToolUse",
36114
+ "postToolUse",
36115
+ "postToolUseFailure",
36116
+ "afterAgentResponse",
36117
+ "subagentStop",
36118
+ "stop",
36119
+ "sessionEnd"
36120
+ ];
36121
+ var REGISTRATIONS2 = [
36122
+ ...CURSOR_EVENTS.map((event) => ({ event, bin: CAPTURE_BIN3 })),
36123
+ { event: "preToolUse", bin: GATE_BIN3, matcher: "Write|Delete|Shell", timeout: 10 },
36124
+ { event: "postToolUse", bin: POST_TOOL_BIN },
36125
+ { event: "postToolUseFailure", bin: POST_TOOL_BIN },
36126
+ { event: "sessionStart", bin: SESSION_START_BIN3 },
36127
+ { event: "sessionEnd", bin: SESSION_END_BIN2 }
36128
+ ];
36129
+ function cursorConfigDirectory(env4 = process.env, home = homedir7(), platform2 = process.platform) {
36130
+ const explicit = env4.CURSOR_CONFIG_DIR?.trim();
36131
+ if (explicit && isAbsolute6(explicit)) return explicit;
36132
+ const xdg = env4.XDG_CONFIG_HOME?.trim();
36133
+ if (platform2 !== "darwin" && xdg && isAbsolute6(xdg)) return join13(xdg, "cursor");
36134
+ return join13(home, ".cursor");
36135
+ }
36136
+ function cursorHooksPath(scope, root = projectRoot()) {
36137
+ return scope === "user" ? join13(cursorConfigDirectory(), "hooks.json") : join13(root, ".cursor", "hooks.json");
36138
+ }
36139
+ function cursorCliConfigPath() {
36140
+ return join13(cursorConfigDirectory(), "cli-config.json");
36141
+ }
36142
+ function plainObject(value) {
36143
+ return typeof value === "object" && value !== null && !Array.isArray(value);
36144
+ }
36145
+ function readCursorHooks(path9) {
36146
+ if (!existsSync10(path9)) return {};
36147
+ let parsed;
36148
+ try {
36149
+ parsed = JSON.parse(readFileSync11(path9, "utf8"));
36150
+ } catch {
36151
+ throw new Error(`invalid Cursor hooks JSON at ${path9}`);
36152
+ }
36153
+ if (!plainObject(parsed)) throw new Error(`Cursor hooks config must be an object: ${path9}`);
36154
+ if (parsed.version !== void 0 && parsed.version !== 1) {
36155
+ throw new Error(`unsupported Cursor hooks version at ${path9} (expected version 1)`);
36156
+ }
36157
+ if (parsed.hooks !== void 0) {
36158
+ if (!plainObject(parsed.hooks)) throw new Error(`Cursor hooks must be an object: ${path9}`);
36159
+ for (const [event, entries] of Object.entries(parsed.hooks)) {
36160
+ if (!Array.isArray(entries) || !entries.every(plainObject)) {
36161
+ throw new Error(`Cursor hook list must contain objects: ${event} in ${path9}`);
36162
+ }
36163
+ }
36164
+ }
36165
+ return parsed;
36166
+ }
36167
+ function readObject(path9) {
36168
+ if (!existsSync10(path9)) return {};
36169
+ let parsed;
36170
+ try {
36171
+ parsed = JSON.parse(readFileSync11(path9, "utf8"));
36172
+ } catch {
36173
+ throw new Error(`invalid Cursor CLI config JSON at ${path9}`);
36174
+ }
36175
+ if (!plainObject(parsed)) throw new Error(`Cursor CLI config must be an object: ${path9}`);
36176
+ return parsed;
36177
+ }
36178
+ function writeJson(path9, value) {
36179
+ atomicWriteFile(path9, `${JSON.stringify(value, null, 2)}
36180
+ `, { ensureParent: true });
36181
+ }
36182
+ function commandFor(registration, scope) {
36183
+ return stableHookCommand(
36184
+ registration.bin,
36185
+ `--agent cursor --event ${registration.event} --scope ${scope}`
36186
+ );
36187
+ }
36188
+ var OWNED_COMMANDS = new Set(
36189
+ ["project", "user"].flatMap(
36190
+ (scope) => REGISTRATIONS2.map((registration) => commandFor(registration, scope))
36191
+ )
36192
+ );
36193
+ function jsoncUnsafeCommand(command) {
36194
+ return command.replace('case "$1" in [/]* ', 'case "$1" in /*').replace("*[/][/]*", "*//*").replace("*[/].[/]*", "*/./*").replace("*[/]..[/]*", "*/../*").replace("*[/].", "*/.").replace("*[/]..", "*/..").replace("?*[/]", "?*/");
36195
+ }
36196
+ var JSONC_UNSAFE_OWNED_COMMANDS = new Set([...OWNED_COMMANDS].map(jsoncUnsafeCommand));
36197
+ function isOwnedCursorHookCommand(command) {
36198
+ return typeof command === "string" && (OWNED_COMMANDS.has(command) || JSONC_UNSAFE_OWNED_COMMANDS.has(command));
36199
+ }
36200
+ function hookFor(registration, scope) {
36201
+ return {
36202
+ command: commandFor(registration, scope),
36203
+ ...registration.matcher ? { matcher: registration.matcher } : {},
36204
+ ...registration.timeout ? { timeout: registration.timeout } : {}
36205
+ };
36206
+ }
36207
+ function exactHook(entry, registration, scope) {
36208
+ return JSON.stringify(entry) === JSON.stringify(hookFor(registration, scope));
36209
+ }
36210
+ function applyCursorInstall(settings, scope) {
36211
+ const hooks = {};
36212
+ for (const [event, entries] of Object.entries(settings.hooks ?? {})) {
36213
+ hooks[event] = entries.filter((entry) => !isOwnedCursorHookCommand(entry.command));
36214
+ }
36215
+ for (const registration of REGISTRATIONS2) {
36216
+ const entries = hooks[registration.event] ?? [];
36217
+ entries.push(hookFor(registration, scope));
36218
+ hooks[registration.event] = entries;
36219
+ }
36220
+ return { ...settings, version: 1, hooks };
36221
+ }
36222
+ function applyCursorUninstall(settings) {
36223
+ const hooks = {};
36224
+ for (const [event, entries] of Object.entries(settings.hooks ?? {})) {
36225
+ const retained = entries.filter((entry) => !isOwnedCursorHookCommand(entry.command));
36226
+ if (retained.length > 0) hooks[event] = retained;
36227
+ }
36228
+ return { ...settings, hooks };
36229
+ }
36230
+ function ownedEntries(settings) {
36231
+ return Object.entries(settings.hooks ?? {}).flatMap(
36232
+ ([event, entries]) => entries.filter((entry) => isOwnedCursorHookCommand(entry.command)).map((entry) => ({ event, entry }))
36233
+ );
36234
+ }
36235
+ function hasExactCursorHandler(settings, event, bin, scope) {
36236
+ const registration = REGISTRATIONS2.find(
36237
+ (candidate) => candidate.event === event && candidate.bin === bin
36238
+ );
36239
+ return registration ? (settings.hooks?.[event] ?? []).some((entry) => exactHook(entry, registration, scope)) : false;
36240
+ }
36241
+ function complete(settings, scope) {
36242
+ const owned = ownedEntries(settings);
36243
+ return owned.length === REGISTRATIONS2.length && REGISTRATIONS2.every(
36244
+ (registration) => owned.filter(
36245
+ ({ event, entry }) => event === registration.event && exactHook(entry, registration, scope)
36246
+ ).length === 1
36247
+ );
36248
+ }
36249
+ function captureInstalled3(settings, scope) {
36250
+ return CURSOR_EVENTS.every((event) => hasExactCursorHandler(settings, event, CAPTURE_BIN3, scope));
36251
+ }
36252
+ function gateInstalled(settings, scope) {
36253
+ return hasExactCursorHandler(settings, "preToolUse", GATE_BIN3, scope);
36254
+ }
36255
+ var FOOTER = {
36256
+ type: "command",
36257
+ command: stableHookCommand(STATUSLINE_BIN2),
36258
+ updateIntervalMs: 1e3,
36259
+ timeoutMs: 2e3
36260
+ };
36261
+ var JSONC_UNSAFE_FOOTER = {
36262
+ ...FOOTER,
36263
+ command: jsoncUnsafeCommand(FOOTER.command)
36264
+ };
36265
+ function exactFooter(value) {
36266
+ return plainObject(value) && JSON.stringify(value) === JSON.stringify(FOOTER);
36267
+ }
36268
+ function jsoncUnsafeFooter(value) {
36269
+ return plainObject(value) && JSON.stringify(value) === JSON.stringify(JSONC_UNSAFE_FOOTER);
36270
+ }
36271
+ function applyCursorFooterInstall(config) {
36272
+ if (config.statusLine === void 0)
36273
+ return { config: { ...config, statusLine: FOOTER }, installed: true, preservedCustom: false };
36274
+ if (exactFooter(config.statusLine)) return { config, installed: true, preservedCustom: false };
36275
+ if (jsoncUnsafeFooter(config.statusLine)) {
36276
+ return { config: { ...config, statusLine: FOOTER }, installed: true, preservedCustom: false };
36277
+ }
36278
+ return { config, installed: false, preservedCustom: true };
36279
+ }
36280
+ function applyCursorFooterUninstall(config) {
36281
+ if (!exactFooter(config.statusLine) && !jsoncUnsafeFooter(config.statusLine)) {
36282
+ return { config, removed: false };
36283
+ }
36284
+ return {
36285
+ config: Object.fromEntries(Object.entries(config).filter(([key]) => key !== "statusLine")),
36286
+ removed: true
36287
+ };
36288
+ }
36289
+ function statusFor(scope, path9 = cursorHooksPath(scope)) {
36290
+ const settings = readCursorHooks(path9);
36291
+ const base = {
36292
+ path: path9,
36293
+ present: ownedEntries(settings).length > 0,
36294
+ gate: gateInstalled(settings, scope),
36295
+ capture: captureInstalled3(settings, scope),
36296
+ complete: complete(settings, scope)
36297
+ };
36298
+ if (scope === "user") {
36299
+ const cliConfig = readObject(cursorCliConfigPath());
36300
+ base.footer = exactFooter(cliConfig.statusLine);
36301
+ base.footerPreservedCustom = cliConfig.statusLine !== void 0 && !base.footer;
36302
+ }
36303
+ return base;
36304
+ }
36305
+ function performInstall3(scope, _force = false) {
36306
+ stageHookRuntime();
36307
+ const path9 = cursorHooksPath(scope);
36308
+ const before = readCursorHooks(path9);
36309
+ const after = applyCursorInstall(before, scope);
36310
+ let changed = JSON.stringify(before) !== JSON.stringify(after);
36311
+ if (changed) writeJson(path9, after);
36312
+ let restartRequired = false;
36313
+ if (scope === "user") {
36314
+ const cliPath = cursorCliConfigPath();
36315
+ const cliBefore = readObject(cliPath);
36316
+ const footer = applyCursorFooterInstall(cliBefore);
36317
+ if (JSON.stringify(cliBefore) !== JSON.stringify(footer.config)) {
36318
+ writeJson(cliPath, footer.config);
36319
+ changed = true;
36320
+ restartRequired = true;
36321
+ }
36322
+ }
36323
+ return { scope, ...statusFor(scope, path9), changed, restartRequired };
36324
+ }
36325
+ function performUninstall3(scope) {
36326
+ const path9 = cursorHooksPath(scope);
36327
+ const before = readCursorHooks(path9);
36328
+ const after = applyCursorUninstall(before);
36329
+ let changed = JSON.stringify(before) !== JSON.stringify(after);
36330
+ if (changed) writeJson(path9, after);
36331
+ let restartRequired = false;
36332
+ if (scope === "user") {
36333
+ const cliPath = cursorCliConfigPath();
36334
+ const cliBefore = readObject(cliPath);
36335
+ const footer = applyCursorFooterUninstall(cliBefore);
36336
+ if (footer.removed) {
36337
+ writeJson(cliPath, footer.config);
36338
+ changed = true;
36339
+ restartRequired = true;
36340
+ }
36341
+ }
36342
+ return { scope, ...statusFor(scope, path9), changed, restartRequired };
36343
+ }
36344
+ function performStatus3() {
36345
+ return { user: statusFor("user"), project: statusFor("project") };
36346
+ }
36347
+ function inspectHookRuntimeResolutions3() {
36348
+ const commands = ["user", "project"].flatMap(
36349
+ (scope) => ownedEntries(readCursorHooks(cursorHooksPath(scope))).map(({ entry }) => entry.command)
36350
+ );
36351
+ return hookCommandResolutions(commands, PRIM_BINS3);
36352
+ }
36353
+ function resolveScope3(input) {
36354
+ if (input === void 0 || input === "project") return "project";
36355
+ if (input === "user") return "user";
36356
+ throw new Error(`unknown --scope "${input}" (expected: user or project)`);
36357
+ }
36358
+ function registerCursorCommands(program3) {
36359
+ const cursor = program3.command("cursor").description("Manage the native Cursor integration (capture, gate, ingest, presence)");
36360
+ cursor.command("install").description("Register Primitive in Cursor's native hooks.json").option("--scope <scope>", "project (default) or user").option("--force", "Repair drifted Primitive entries; custom Cursor fields remain untouched").action((opts) => {
36361
+ const result = performInstall3(resolveScope3(opts.scope), opts.force);
36362
+ console.error(
36363
+ result.changed ? `[prim] Cursor integration installed (${result.scope} scope) at ${result.path}` : `[prim] Cursor integration already present at ${result.path}`
36364
+ );
36365
+ if (result.restartRequired) console.error("[prim] restart Cursor CLI to load the footer");
36366
+ console.log(JSON.stringify(result, null, 2));
36367
+ });
36368
+ cursor.command("uninstall").description("Remove only Primitive-owned Cursor hooks and footer").option("--scope <scope>", "project (default) or user").action((opts) => {
36369
+ const result = performUninstall3(resolveScope3(opts.scope));
36370
+ console.error(
36371
+ result.changed ? `[prim] Cursor integration removed (${result.scope} scope)` : `[prim] no Primitive-owned Cursor integration found (${result.scope} scope)`
36372
+ );
36373
+ if (result.restartRequired) console.error("[prim] restart Cursor CLI to remove the footer");
36374
+ console.log(JSON.stringify(result, null, 2));
36375
+ });
36376
+ cursor.command("status").description("Report native Cursor hook and footer status").action(() => {
36377
+ const result = performStatus3();
36378
+ const mark = (value) => value ? "\u2713" : "\u2717";
36379
+ console.error(
36380
+ `[prim] user: gate ${mark(result.user.gate)} \xB7 capture ${mark(result.user.capture)} \xB7 footer ${mark(result.user.footer)} (${result.user.path})
36381
+ [prim] project: gate ${mark(result.project.gate)} \xB7 capture ${mark(result.project.capture)} (${result.project.path})`
36382
+ );
36383
+ console.log(JSON.stringify(result, null, 2));
36384
+ });
36385
+ }
36386
+
36082
36387
  // src/commands/daemon.ts
36083
36388
  import { spawn as spawn3 } from "child_process";
36084
- import { closeSync as closeSync3, existsSync as existsSync11, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync12, unlinkSync as unlinkSync3 } from "fs";
36085
- import { join as join15 } from "path";
36389
+ import { closeSync as closeSync3, existsSync as existsSync12, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync13, unlinkSync as unlinkSync3 } from "fs";
36390
+ import { join as join16 } from "path";
36086
36391
 
36087
36392
  // src/daemon/latest-bootstrap.ts
36088
36393
  import { spawn as spawn2 } from "child_process";
36089
- import { join as join13 } from "path";
36394
+ import { join as join14 } from "path";
36090
36395
  var LATEST_BOOTSTRAP_TIMEOUT_MS = 45e3;
36091
36396
  var LATEST_BOOTSTRAP_LOCK_NAME = "daemon-latest.lock";
36092
36397
  async function runPinnedEnsure(options) {
@@ -36127,7 +36432,7 @@ async function runPinnedEnsure(options) {
36127
36432
  });
36128
36433
  }
36129
36434
  async function runLatestDaemonBootstrap(ensureCurrent, options = {}) {
36130
- const lockPath = options.lockPath ?? join13(
36435
+ const lockPath = options.lockPath ?? join14(
36131
36436
  primConfigDirectory({ env: options.env, homeDir: options.homeDir }),
36132
36437
  LATEST_BOOTSTRAP_LOCK_NAME
36133
36438
  );
@@ -36157,11 +36462,11 @@ import {
36157
36462
  accessSync as accessSync2,
36158
36463
  chmodSync as chmodSync4,
36159
36464
  copyFileSync as copyFileSync2,
36160
- existsSync as existsSync10,
36465
+ existsSync as existsSync11,
36161
36466
  lstatSync as lstatSync5,
36162
36467
  mkdirSync as mkdirSync8,
36163
36468
  mkdtempSync as mkdtempSync2,
36164
- readFileSync as readFileSync11,
36469
+ readFileSync as readFileSync12,
36165
36470
  readdirSync as readdirSync3,
36166
36471
  readlinkSync,
36167
36472
  realpathSync as realpathSync3,
@@ -36170,8 +36475,8 @@ import {
36170
36475
  symlinkSync,
36171
36476
  writeFileSync as writeFileSync7
36172
36477
  } from "fs";
36173
- import { homedir as homedir7 } from "os";
36174
- import { basename as basename3, dirname as dirname10, isAbsolute as isAbsolute6, join as join14, resolve as resolve6 } from "path";
36478
+ import { homedir as homedir8 } from "os";
36479
+ import { basename as basename3, dirname as dirname10, isAbsolute as isAbsolute7, join as join15, resolve as resolve6 } from "path";
36175
36480
 
36176
36481
  // src/daemon/env-binding.ts
36177
36482
  function normalizeApiUrl(url) {
@@ -36210,31 +36515,31 @@ var LaunchctlError = class extends Error {
36210
36515
  }
36211
36516
  };
36212
36517
  function xdgDataHome(options) {
36213
- const home = options.homeDir ?? homedir7();
36518
+ const home = options.homeDir ?? homedir8();
36214
36519
  const configured = (options.env ?? process.env).XDG_DATA_HOME;
36215
- return configured && isAbsolute6(configured) ? configured : join14(home, ".local", "share");
36520
+ return configured && isAbsolute7(configured) ? configured : join15(home, ".local", "share");
36216
36521
  }
36217
36522
  function runtimePaths(options = {}) {
36218
- const dataDir = join14(xdgDataHome(options), "prim");
36219
- const runtimeDir = join14(dataDir, "runtime");
36220
- const currentLink = join14(runtimeDir, "current");
36523
+ const dataDir = join15(xdgDataHome(options), "prim");
36524
+ const runtimeDir = join15(dataDir, "runtime");
36525
+ const currentLink = join15(runtimeDir, "current");
36221
36526
  return {
36222
36527
  dataDir,
36223
36528
  runtimeDir,
36224
- releasesDir: join14(runtimeDir, "releases"),
36529
+ releasesDir: join15(runtimeDir, "releases"),
36225
36530
  currentLink,
36226
- statuslineLauncher: join14(runtimeDir, "prim-statusline"),
36227
- disabledMarker: join14(dataDir, "daemon.disabled"),
36228
- lifecycleLockDir: join14(dataDir, "daemon.lifecycle.lock")
36531
+ statuslineLauncher: join15(runtimeDir, "prim-statusline"),
36532
+ disabledMarker: join15(dataDir, "daemon.disabled"),
36533
+ lifecycleLockDir: join15(dataDir, "daemon.lifecycle.lock")
36229
36534
  };
36230
36535
  }
36231
36536
  function daemonControlPaths(options = {}) {
36232
36537
  const configDir = primConfigDirectory(options);
36233
36538
  const legacy = runtimePaths(options);
36234
36539
  return {
36235
- launcher: join14(configDir, `prim-daemon-launcher-v${LAUNCHER_SCHEMA_VERSION}`),
36236
- disabledMarker: join14(configDir, "daemon.disabled"),
36237
- lifecycleLockDir: join14(configDir, "daemon.lifecycle.lock"),
36540
+ launcher: join15(configDir, `prim-daemon-launcher-v${LAUNCHER_SCHEMA_VERSION}`),
36541
+ disabledMarker: join15(configDir, "daemon.disabled"),
36542
+ lifecycleLockDir: join15(configDir, "daemon.lifecycle.lock"),
36238
36543
  legacyDisabledMarker: legacy.disabledMarker,
36239
36544
  legacyLifecycleLockDir: legacy.lifecycleLockDir
36240
36545
  };
@@ -36242,10 +36547,10 @@ function daemonControlPaths(options = {}) {
36242
36547
  function findPackageVersion(entryFile) {
36243
36548
  let dir = dirname10(resolve6(entryFile));
36244
36549
  for (let depth = 0; depth < 6; depth++) {
36245
- const packagePath = join14(dir, "package.json");
36246
- if (existsSync10(packagePath)) {
36550
+ const packagePath = join15(dir, "package.json");
36551
+ if (existsSync11(packagePath)) {
36247
36552
  try {
36248
- const manifest = JSON.parse(readFileSync11(packagePath, "utf8"));
36553
+ const manifest = JSON.parse(readFileSync12(packagePath, "utf8"));
36249
36554
  if (manifest.name === "@primitive.ai/prim" && manifest.version) {
36250
36555
  return manifest.version;
36251
36556
  }
@@ -36260,7 +36565,7 @@ function findPackageVersion(entryFile) {
36260
36565
  }
36261
36566
  function readRuntimeManifest(path9) {
36262
36567
  try {
36263
- const parsed = JSON.parse(readFileSync11(path9, "utf8"));
36568
+ const parsed = JSON.parse(readFileSync12(path9, "utf8"));
36264
36569
  if (parsed.schemaVersion !== RUNTIME_SCHEMA_VERSION || typeof parsed.version !== "string" || typeof parsed.nodePath !== "string" || parsed.daemonFile !== "prim-daemon-server" || typeof parsed.daemonSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(parsed.daemonSha256)) {
36265
36570
  return null;
36266
36571
  }
@@ -36276,10 +36581,10 @@ function exactKeys2(value, expected) {
36276
36581
  return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
36277
36582
  }
36278
36583
  function readOwnedRuntimeManifest(releaseDir) {
36279
- const manifestPath = join14(releaseDir, "manifest.json");
36280
- const daemonPath = join14(releaseDir, "prim-daemon-server");
36584
+ const manifestPath = join15(releaseDir, "manifest.json");
36585
+ const daemonPath = join15(releaseDir, "prim-daemon-server");
36281
36586
  try {
36282
- const raw = readFileSync11(manifestPath, "utf8");
36587
+ const raw = readFileSync12(manifestPath, "utf8");
36283
36588
  const parsed = JSON.parse(raw);
36284
36589
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
36285
36590
  if (!exactKeys2(parsed, [
@@ -36293,7 +36598,7 @@ function readOwnedRuntimeManifest(releaseDir) {
36293
36598
  return null;
36294
36599
  }
36295
36600
  const manifest = parsed;
36296
- if (manifest.schemaVersion !== RUNTIME_SCHEMA_VERSION || compareSemver(manifest.version, manifest.version) !== 0 || !isAbsolute6(manifest.nodePath) || /[\r\n]/u.test(manifest.nodePath) || manifest.daemonFile !== "prim-daemon-server" || !/^[0-9a-f]{64}$/u.test(manifest.daemonSha256) || new Date(manifest.stagedAt).toISOString() !== manifest.stagedAt || raw !== `${JSON.stringify(manifest, null, 2)}
36601
+ if (manifest.schemaVersion !== RUNTIME_SCHEMA_VERSION || compareSemver(manifest.version, manifest.version) !== 0 || !isAbsolute7(manifest.nodePath) || /[\r\n]/u.test(manifest.nodePath) || manifest.daemonFile !== "prim-daemon-server" || !/^[0-9a-f]{64}$/u.test(manifest.daemonSha256) || new Date(manifest.stagedAt).toISOString() !== manifest.stagedAt || raw !== `${JSON.stringify(manifest, null, 2)}
36297
36602
  ` || !lstatSync5(daemonPath).isFile() || sha256File(daemonPath) !== manifest.daemonSha256) {
36298
36603
  return null;
36299
36604
  }
@@ -36314,7 +36619,7 @@ function sameRuntime(current, desired, daemonPath) {
36314
36619
  }
36315
36620
  }
36316
36621
  function sha256File(path9) {
36317
- return createHash8("sha256").update(readFileSync11(path9)).digest("hex");
36622
+ return createHash8("sha256").update(readFileSync12(path9)).digest("hex");
36318
36623
  }
36319
36624
  function atomicSymlink(target, linkPath) {
36320
36625
  const tempLink = `${linkPath}.tmp-${process.pid}-${createHash8("sha256").update(`${target}\0${Date.now()}\0${Math.random()}`).digest("hex").slice(0, 12)}`;
@@ -36329,7 +36634,7 @@ function atomicSymlink(target, linkPath) {
36329
36634
  function stageRuntime(options = {}) {
36330
36635
  const paths = runtimePaths(options);
36331
36636
  const daemonSource = options.daemonSource ?? binFile("prim-daemon-server");
36332
- if (!daemonSource || !existsSync10(daemonSource)) {
36637
+ if (!daemonSource || !existsSync11(daemonSource)) {
36333
36638
  throw new Error("cannot stage runtime: prim-daemon-server bundle is unavailable");
36334
36639
  }
36335
36640
  const nodePath = resolve6(options.nodePath ?? process.execPath);
@@ -36347,8 +36652,8 @@ function stageRuntime(options = {}) {
36347
36652
  currentRelease = realpathSync3(paths.currentLink);
36348
36653
  } catch {
36349
36654
  }
36350
- const current = currentRelease ? readRuntimeManifest(join14(currentRelease, "manifest.json")) : null;
36351
- const currentDaemon = currentRelease ? join14(currentRelease, desired.daemonFile) : "";
36655
+ const current = currentRelease ? readRuntimeManifest(join15(currentRelease, "manifest.json")) : null;
36656
+ const currentDaemon = currentRelease ? join15(currentRelease, desired.daemonFile) : "";
36352
36657
  if (currentRelease && sameRuntime(current, desired, currentDaemon)) {
36353
36658
  const manifest = current;
36354
36659
  atomicWrite3(
@@ -36366,17 +36671,17 @@ function stageRuntime(options = {}) {
36366
36671
  mkdirSync8(paths.releasesDir, { recursive: true, mode: RUNTIME_DIR_MODE });
36367
36672
  chmodSync4(paths.runtimeDir, RUNTIME_DIR_MODE);
36368
36673
  chmodSync4(paths.releasesDir, RUNTIME_DIR_MODE);
36369
- const stagingDir = mkdtempSync2(join14(paths.releasesDir, ".stage-"));
36674
+ const stagingDir = mkdtempSync2(join15(paths.releasesDir, ".stage-"));
36370
36675
  chmodSync4(stagingDir, RUNTIME_DIR_MODE);
36371
36676
  let releaseDir;
36372
36677
  try {
36373
- const daemonTarget = join14(stagingDir, desired.daemonFile);
36678
+ const daemonTarget = join15(stagingDir, desired.daemonFile);
36374
36679
  copyFileSync2(daemonSource, daemonTarget);
36375
36680
  chmodSync4(daemonTarget, RUNTIME_FILE_MODE);
36376
36681
  if (sha256File(daemonTarget) !== desired.daemonSha256) {
36377
36682
  throw new Error("cannot stage runtime: daemon bundle changed while it was copied");
36378
36683
  }
36379
- const manifestTarget = join14(stagingDir, "manifest.json");
36684
+ const manifestTarget = join15(stagingDir, "manifest.json");
36380
36685
  writeFileSync7(manifestTarget, `${JSON.stringify(desired, null, 2)}
36381
36686
  `, {
36382
36687
  encoding: "utf8",
@@ -36384,10 +36689,10 @@ function stageRuntime(options = {}) {
36384
36689
  flag: "wx"
36385
36690
  });
36386
36691
  const releaseName = `release-${createHash8("sha256").update(`${version}\0${nodePath}\0${desired.stagedAt}\0${process.pid}\0${Math.random()}`).digest("hex").slice(0, 16)}`;
36387
- releaseDir = join14(paths.releasesDir, releaseName);
36692
+ releaseDir = join15(paths.releasesDir, releaseName);
36388
36693
  renameSync4(stagingDir, releaseDir);
36389
36694
  releaseDir = realpathSync3(releaseDir);
36390
- atomicSymlink(join14("releases", releaseName), paths.currentLink);
36695
+ atomicSymlink(join15("releases", releaseName), paths.currentLink);
36391
36696
  atomicWrite3(
36392
36697
  paths.statuslineLauncher,
36393
36698
  statuslineLauncherContent(desired.version, options),
@@ -36401,14 +36706,14 @@ function stageRuntime(options = {}) {
36401
36706
  changed: true,
36402
36707
  manifest: desired,
36403
36708
  paths,
36404
- daemonPath: join14(releaseDir, desired.daemonFile)
36709
+ daemonPath: join15(releaseDir, desired.daemonFile)
36405
36710
  };
36406
36711
  }
36407
36712
  function shellQuote2(value) {
36408
36713
  return `'${value.replaceAll("'", `'"'"'`)}'`;
36409
36714
  }
36410
36715
  function statuslineLauncherContent(version, options = {}) {
36411
- const socketPath = join14(primConfigDirectory(options), "sock");
36716
+ const socketPath = join15(primConfigDirectory(options), "sock");
36412
36717
  const fallback = `primitive ${version} (daemon: down)`;
36413
36718
  return `#!/bin/sh
36414
36719
  response=$(
@@ -36441,7 +36746,7 @@ function lstatIfPresent3(path9) {
36441
36746
  function assertExactFile(path9, expected, label) {
36442
36747
  if (!lstatIfPresent3(path9)) return;
36443
36748
  assertRegularFile(path9, label);
36444
- if (readFileSync11(path9, "utf8") !== expected) {
36749
+ if (readFileSync12(path9, "utf8") !== expected) {
36445
36750
  throw new Error(`refusing to remove unrecognized ${label} at ${path9}`);
36446
36751
  }
36447
36752
  }
@@ -36450,12 +36755,12 @@ function assertOwnedDaemonRuntime(options) {
36450
36755
  const control = daemonControlPaths(options);
36451
36756
  const configDir = primConfigDirectory(options);
36452
36757
  const service = process.platform === "darwin" ? launchdPaths(options) : void 0;
36453
- const logPath = service?.logPath ?? join14(configDir, "daemon.log");
36758
+ const logPath = service?.logPath ?? join15(configDir, "daemon.log");
36454
36759
  for (const activeArtifact of [
36455
- join14(configDir, "daemon.pid"),
36456
- join14(configDir, "sock"),
36457
- join14(configDir, "daemon.lock"),
36458
- join14(configDir, "client-instance.lock")
36760
+ join15(configDir, "daemon.pid"),
36761
+ join15(configDir, "sock"),
36762
+ join15(configDir, "daemon.lock"),
36763
+ join15(configDir, "client-instance.lock")
36459
36764
  ]) {
36460
36765
  if (lstatIfPresent3(activeArtifact)) {
36461
36766
  throw new Error(`refusing runtime removal while daemon state remains at ${activeArtifact}`);
@@ -36476,17 +36781,17 @@ function assertOwnedDaemonRuntime(options) {
36476
36781
  );
36477
36782
  }
36478
36783
  assertRegularFile(logPath, "daemon log");
36479
- assertRegularFile(join14(configDir, "daemon-health.json"), "daemon health snapshot");
36480
- assertRegularFile(join14(configDir, "client_instance_id"), "daemon client instance id");
36784
+ assertRegularFile(join15(configDir, "daemon-health.json"), "daemon health snapshot");
36785
+ assertRegularFile(join15(configDir, "client_instance_id"), "daemon client instance id");
36481
36786
  if (service && lstatIfPresent3(service.plistPath)) {
36482
36787
  assertRegularFile(service.plistPath, "launchd property list");
36483
36788
  const expected = generateLaunchAgentPlist({
36484
36789
  launcherPath: control.launcher,
36485
36790
  logPath,
36486
- workingDirectory: options.homeDir ?? homedir7(),
36791
+ workingDirectory: options.homeDir ?? homedir8(),
36487
36792
  label: options.label
36488
36793
  });
36489
- if (readFileSync11(service.plistPath, "utf8") !== expected) {
36794
+ if (readFileSync12(service.plistPath, "utf8") !== expected) {
36490
36795
  throw new Error(
36491
36796
  `refusing to remove unrecognized launchd property list at ${service.plistPath}`
36492
36797
  );
@@ -36511,7 +36816,7 @@ function assertOwnedDaemonRuntime(options) {
36511
36816
  throw new Error(`refusing to remove non-directory daemon releases at ${runtime.releasesDir}`);
36512
36817
  }
36513
36818
  for (const entry of readdirSync3(runtime.releasesDir, { withFileTypes: true })) {
36514
- const releaseDir = join14(runtime.releasesDir, entry.name);
36819
+ const releaseDir = join15(runtime.releasesDir, entry.name);
36515
36820
  const manifest = entry.isDirectory() && RUNTIME_RELEASE_RE.test(entry.name) ? readOwnedRuntimeManifest(releaseDir) : null;
36516
36821
  if (!manifest) {
36517
36822
  throw new Error(`refusing to remove unrecognized daemon release ${releaseDir}`);
@@ -36529,7 +36834,7 @@ function assertOwnedDaemonRuntime(options) {
36529
36834
  }
36530
36835
  const target = readlinkSync(runtime.currentLink);
36531
36836
  const releaseName = basename3(target);
36532
- if (target !== join14("releases", releaseName) || !RUNTIME_RELEASE_RE.test(releaseName)) {
36837
+ if (target !== join15("releases", releaseName) || !RUNTIME_RELEASE_RE.test(releaseName)) {
36533
36838
  throw new Error(
36534
36839
  `refusing to remove malformed daemon runtime selector ${runtime.currentLink}`
36535
36840
  );
@@ -36557,7 +36862,7 @@ async function removeDaemonRuntime(options = {}) {
36557
36862
  const control = daemonControlPaths(options);
36558
36863
  const configDir = primConfigDirectory(options);
36559
36864
  const service = process.platform === "darwin" ? launchdPaths(options) : void 0;
36560
- const logPath = service?.logPath ?? join14(configDir, "daemon.log");
36865
+ const logPath = service?.logPath ?? join15(configDir, "daemon.log");
36561
36866
  const ownedArtifacts = [
36562
36867
  runtime.runtimeDir,
36563
36868
  control.launcher,
@@ -36565,8 +36870,8 @@ async function removeDaemonRuntime(options = {}) {
36565
36870
  control.legacyDisabledMarker,
36566
36871
  ...service ? [service.plistPath] : [],
36567
36872
  logPath,
36568
- join14(configDir, "daemon-health.json"),
36569
- join14(configDir, "client_instance_id")
36873
+ join15(configDir, "daemon-health.json"),
36874
+ join15(configDir, "client_instance_id")
36570
36875
  ];
36571
36876
  if (!ownedArtifacts.some((path9) => lstatIfPresent3(path9))) {
36572
36877
  return { changed: false, runtimePaths: runtime };
@@ -36610,11 +36915,11 @@ ${config.configDir ? `export PRIM_CONFIG_DIR=${shellQuote2(config.configDir)}
36610
36915
  }
36611
36916
  function readDaemonLauncher(path9) {
36612
36917
  try {
36613
- const content = readFileSync11(path9, "utf8");
36918
+ const content = readFileSync12(path9, "utf8");
36614
36919
  const encoded = /^# prim-daemon-launcher: ([A-Za-z0-9_-]+)$/mu.exec(content)?.[1];
36615
36920
  if (!encoded) return null;
36616
36921
  const value = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
36617
- if (value.schemaVersion !== LAUNCHER_SCHEMA_VERSION || typeof value.nodePath !== "string" || typeof value.daemonPath !== "string" || typeof value.runtimeVersion !== "string" || value.apiUrl !== null && typeof value.apiUrl !== "string" || value.configDir !== void 0 && (typeof value.configDir !== "string" || !isAbsolute6(value.configDir)) || typeof value.revision !== "string") {
36922
+ if (value.schemaVersion !== LAUNCHER_SCHEMA_VERSION || typeof value.nodePath !== "string" || typeof value.daemonPath !== "string" || typeof value.runtimeVersion !== "string" || value.apiUrl !== null && typeof value.apiUrl !== "string" || value.configDir !== void 0 && (typeof value.configDir !== "string" || !isAbsolute7(value.configDir)) || typeof value.revision !== "string") {
36618
36923
  return null;
36619
36924
  }
36620
36925
  const config = {
@@ -36633,7 +36938,7 @@ function readDaemonLauncher(path9) {
36633
36938
  function readUsableDaemonConfig(path9) {
36634
36939
  const config = readDaemonLauncher(path9);
36635
36940
  if (!config) return null;
36636
- const manifest = readRuntimeManifest(join14(dirname10(config.daemonPath), "manifest.json"));
36941
+ const manifest = readRuntimeManifest(join15(dirname10(config.daemonPath), "manifest.json"));
36637
36942
  try {
36638
36943
  accessSync2(config.nodePath, constants4.X_OK);
36639
36944
  return manifest?.version === config.runtimeVersion && manifest.nodePath === config.nodePath && manifest.daemonSha256 === sha256File(config.daemonPath) ? config : null;
@@ -36678,7 +36983,7 @@ function generateLaunchAgentPlist(config) {
36678
36983
  `;
36679
36984
  }
36680
36985
  function launchdPaths(options = {}) {
36681
- const home = options.homeDir ?? homedir7();
36986
+ const home = options.homeDir ?? homedir8();
36682
36987
  const configDir = primConfigDirectory(options);
36683
36988
  const uid = options.uid ?? process.getuid?.();
36684
36989
  const label = options.label ?? LAUNCHD_LABEL;
@@ -36686,8 +36991,8 @@ function launchdPaths(options = {}) {
36686
36991
  return {
36687
36992
  domainTarget: `gui/${uid}`,
36688
36993
  serviceTarget: `gui/${uid}/${label}`,
36689
- plistPath: join14(home, "Library", "LaunchAgents", `${label}.plist`),
36690
- logPath: join14(configDir, "daemon.log")
36994
+ plistPath: join15(home, "Library", "LaunchAgents", `${label}.plist`),
36995
+ logPath: join15(configDir, "daemon.log")
36691
36996
  };
36692
36997
  }
36693
36998
  var runLaunchctl = (args, timeoutMs2 = COMMAND_TIMEOUT_MS) => {
@@ -36720,7 +37025,7 @@ function getLaunchdService(options = {}) {
36720
37025
  }
36721
37026
  function atomicWrite3(path9, content, mode, validate3) {
36722
37027
  try {
36723
- if (readFileSync11(path9, "utf8") === content) {
37028
+ if (readFileSync12(path9, "utf8") === content) {
36724
37029
  chmodSync4(path9, mode);
36725
37030
  validate3?.(path9, COMMAND_TIMEOUT_MS);
36726
37031
  return false;
@@ -36762,14 +37067,14 @@ async function inspectDaemon(timeoutMs2) {
36762
37067
  function canonicalProspectivePath(path9) {
36763
37068
  const suffix = [];
36764
37069
  let ancestor = resolve6(path9);
36765
- while (!existsSync10(ancestor)) {
37070
+ while (!existsSync11(ancestor)) {
36766
37071
  const parent = dirname10(ancestor);
36767
37072
  if (parent === ancestor) return resolve6(path9);
36768
37073
  suffix.unshift(basename3(ancestor));
36769
37074
  ancestor = parent;
36770
37075
  }
36771
37076
  try {
36772
- return join14(realpathSync3(ancestor), ...suffix);
37077
+ return join15(realpathSync3(ancestor), ...suffix);
36773
37078
  } catch {
36774
37079
  return resolve6(path9);
36775
37080
  }
@@ -36784,10 +37089,10 @@ async function withDaemonLifecycleLock(operation, options = {}) {
36784
37089
  );
36785
37090
  }
36786
37091
  async function stopVerifiedLegacyDaemon(options, deadlineMs, nowMs, sleep2) {
36787
- const pidPath = join14(primConfigDirectory(options), "daemon.pid");
37092
+ const pidPath = join15(primConfigDirectory(options), "daemon.pid");
36788
37093
  let pid;
36789
37094
  try {
36790
- pid = Number(readFileSync11(pidPath, "utf8").trim());
37095
+ pid = Number(readFileSync12(pidPath, "utf8").trim());
36791
37096
  } catch {
36792
37097
  throw new Error("an unsupervised daemon answered, but it has no verifiable pidfile");
36793
37098
  }
@@ -36964,7 +37269,7 @@ async function waitForAbsence(context) {
36964
37269
  }
36965
37270
  function daemonExplicitlyDisabled(options = {}) {
36966
37271
  const paths = daemonControlPaths(options);
36967
- return existsSync10(paths.disabledMarker) || existsSync10(paths.legacyDisabledMarker);
37272
+ return existsSync11(paths.disabledMarker) || existsSync11(paths.legacyDisabledMarker);
36968
37273
  }
36969
37274
  function setDaemonExplicitlyDisabled(disabled, options = {}) {
36970
37275
  const paths = daemonControlPaths(options);
@@ -36987,7 +37292,7 @@ async function ensureMacDaemonLocked(options) {
36987
37292
  let service = getLaunchdService({ ...options, runner });
36988
37293
  if (!options.explicitlyStarted && daemonExplicitlyDisabled(options)) {
36989
37294
  const control2 = daemonControlPaths(options);
36990
- if (!existsSync10(control2.disabledMarker)) {
37295
+ if (!existsSync11(control2.disabledMarker)) {
36991
37296
  atomicWrite3(control2.disabledMarker, "disabled by `prim daemon stop`\n", RUNTIME_FILE_MODE);
36992
37297
  }
36993
37298
  return {
@@ -37014,7 +37319,7 @@ async function ensureMacDaemonLocked(options) {
37014
37319
  const configuredApiUrl = (options.env ?? process.env).PRIM_API_URL;
37015
37320
  const apiUrl = configuredApiUrl ? normalizeApiUrl(configuredApiUrl) || void 0 : void 0;
37016
37321
  const configDir = primConfigDirectory(options);
37017
- const legacyDefaultConfigDir = join14(options.homeDir ?? homedir7(), ".config", "prim");
37322
+ const legacyDefaultConfigDir = join15(options.homeDir ?? homedir8(), ".config", "prim");
37018
37323
  const launcherConfigDir = configDir === legacyDefaultConfigDir ? void 0 : configDir;
37019
37324
  if (retainSelected && selected) {
37020
37325
  const usable = readUsableDaemonConfig(control.launcher);
@@ -37049,7 +37354,7 @@ async function ensureMacDaemonLocked(options) {
37049
37354
  const plist = generateLaunchAgentPlist({
37050
37355
  launcherPath: control.launcher,
37051
37356
  logPath: servicePaths.logPath,
37052
- workingDirectory: options.homeDir ?? homedir7(),
37357
+ workingDirectory: options.homeDir ?? homedir8(),
37053
37358
  label: options.label
37054
37359
  });
37055
37360
  const plistChanged = atomicWrite3(
@@ -37272,9 +37577,9 @@ function formatStatusline(version, snapshot, resolveIngestionStatus, options = {
37272
37577
  // src/commands/daemon.ts
37273
37578
  var DAEMON_BIN = "prim-daemon-server";
37274
37579
  var CONFIG_DIR = primConfigDirectory();
37275
- var PID_PATH = join15(CONFIG_DIR, "daemon.pid");
37276
- var SOCK_PATH2 = join15(CONFIG_DIR, "sock");
37277
- var LOG_PATH = join15(CONFIG_DIR, "daemon.log");
37580
+ var PID_PATH = join16(CONFIG_DIR, "daemon.pid");
37581
+ var SOCK_PATH2 = join16(CONFIG_DIR, "sock");
37582
+ var LOG_PATH = join16(CONFIG_DIR, "daemon.log");
37278
37583
  var CONFIG_DIR_MODE2 = 448;
37279
37584
  var LOG_FILE_MODE = 384;
37280
37585
  var STOP_TIMEOUT_MS = 5e3;
@@ -37312,10 +37617,10 @@ function daemonDegradedReason(snapshot) {
37312
37617
  return "health checks have not recovered";
37313
37618
  }
37314
37619
  function readPidfile() {
37315
- if (!existsSync11(PID_PATH)) {
37620
+ if (!existsSync12(PID_PATH)) {
37316
37621
  return null;
37317
37622
  }
37318
- const raw = readFileSync12(PID_PATH, "utf-8").trim();
37623
+ const raw = readFileSync13(PID_PATH, "utf-8").trim();
37319
37624
  const pid = Number(raw);
37320
37625
  if (!Number.isInteger(pid) || pid <= 0) {
37321
37626
  return null;
@@ -37340,10 +37645,10 @@ function spawnDaemon(options) {
37340
37645
  return file ? spawn3(process.execPath, [file], options) : spawn3(DAEMON_BIN, [], options);
37341
37646
  }
37342
37647
  function openDaemonLog(configDir = CONFIG_DIR) {
37343
- if (!existsSync11(configDir)) {
37648
+ if (!existsSync12(configDir)) {
37344
37649
  mkdirSync9(configDir, { recursive: true, mode: CONFIG_DIR_MODE2 });
37345
37650
  }
37346
- return openSync3(join15(configDir, "daemon.log"), "a", LOG_FILE_MODE);
37651
+ return openSync3(join16(configDir, "daemon.log"), "a", LOG_FILE_MODE);
37347
37652
  }
37348
37653
  async function waitForReady() {
37349
37654
  const deadline = Date.now() + READY_TIMEOUT_MS;
@@ -37477,7 +37782,7 @@ async function detachedDaemonStop() {
37477
37782
  {},
37478
37783
  { timeoutMs: STATUS_PROBE_TIMEOUT_MS }
37479
37784
  );
37480
- if (existsSync11(PID_PATH) || existsSync11(SOCK_PATH2) || socketOwner) {
37785
+ if (existsSync12(PID_PATH) || existsSync12(SOCK_PATH2) || socketOwner) {
37481
37786
  process.stderr.write(
37482
37787
  `[prim] refusing to verify daemon absence: ${socketOwner ? `socket is owned by pid=${socketOwner.pid}` : "daemon artifacts remain"}
37483
37788
  `
@@ -37509,7 +37814,7 @@ async function detachedDaemonStop() {
37509
37814
  {},
37510
37815
  { timeoutMs: STATUS_PROBE_TIMEOUT_MS }
37511
37816
  );
37512
- if (socketOwner || existsSync11(SOCK_PATH2)) {
37817
+ if (socketOwner || existsSync12(SOCK_PATH2)) {
37513
37818
  process.stderr.write(
37514
37819
  `[prim] refusing to clear stale pidfile: ${socketOwner ? `socket is owned by pid=${socketOwner.pid}` : "socket artifact remains"}
37515
37820
  `
@@ -38298,6 +38603,8 @@ function authorLabel(row) {
38298
38603
  return "Your Claude Code";
38299
38604
  case "codex":
38300
38605
  return "Your Codex";
38606
+ case "cursor":
38607
+ return "Your Cursor";
38301
38608
  case "hermes":
38302
38609
  return "Your Hermes";
38303
38610
  case "chat":
@@ -39730,6 +40037,7 @@ function describeAudienceMember(member) {
39730
40037
  return {
39731
40038
  claude_code: "Claude Code agent",
39732
40039
  codex: "Codex agent",
40040
+ cursor: "Cursor agent",
39733
40041
  hermes: "Hermes agent"
39734
40042
  }[member.agent] ?? terminalSafeLine(member.agent);
39735
40043
  case "credential":
@@ -39941,7 +40249,7 @@ var UserScopeInputError = class extends Error {
39941
40249
  }
39942
40250
  };
39943
40251
  var USER_SCOPE_ROLES = /* @__PURE__ */ new Set(["owner", "admin", "member"]);
39944
- var USER_SCOPE_AGENTS = /* @__PURE__ */ new Set(["claude_code", "codex", "hermes"]);
40252
+ var USER_SCOPE_AGENTS = /* @__PURE__ */ new Set(["claude_code", "codex", "cursor", "hermes"]);
39945
40253
  var USER_SCOPE_CREDENTIALS = /* @__PURE__ */ new Set(["workos_jwt", "workos_api_key", "service_token"]);
39946
40254
  function requiredScopeValue(flag, value) {
39947
40255
  const trimmed = value.trim();
@@ -39969,9 +40277,12 @@ function userScopeFromOptions(opts) {
39969
40277
  for (const value of agents) {
39970
40278
  const agent = requiredScopeValue("--for-agent", value);
39971
40279
  if (!USER_SCOPE_AGENTS.has(agent)) {
39972
- throw new UserScopeInputError("--for-agent must be claude_code, codex, or hermes");
40280
+ throw new UserScopeInputError("--for-agent must be claude_code, codex, cursor, or hermes");
39973
40281
  }
39974
- members.push({ kind: "agent", agent });
40282
+ members.push({
40283
+ kind: "agent",
40284
+ agent
40285
+ });
39975
40286
  }
39976
40287
  for (const value of credentials) {
39977
40288
  const credential = requiredScopeValue("--for-credential", value);
@@ -40178,7 +40489,7 @@ function registerDecisionsCommands(program3) {
40178
40489
  []
40179
40490
  ).option(
40180
40491
  "--for-agent <agent>",
40181
- "Include one agent: claude_code | codex | hermes (repeatable)",
40492
+ "Include one agent: claude_code | codex | cursor | hermes (repeatable)",
40182
40493
  collectItem,
40183
40494
  []
40184
40495
  ).option(
@@ -40334,7 +40645,7 @@ function registerDecisionsCommands(program3) {
40334
40645
  []
40335
40646
  ).option(
40336
40647
  "--for-agent <agent>",
40337
- "Set one agent: claude_code | codex | hermes (repeatable)",
40648
+ "Set one agent: claude_code | codex | cursor | hermes (repeatable)",
40338
40649
  collectItem,
40339
40650
  []
40340
40651
  ).option(
@@ -40414,7 +40725,7 @@ function registerDecisionsCommands(program3) {
40414
40725
  }
40415
40726
 
40416
40727
  // src/commands/doctor.ts
40417
- import { existsSync as existsSync14 } from "fs";
40728
+ import { existsSync as existsSync15 } from "fs";
40418
40729
 
40419
40730
  // src/decisions/feedback.ts
40420
40731
  var FEEDBACK_PROTOCOL_VERSION = 2;
@@ -40559,17 +40870,17 @@ async function inspectJournalDelivery(buckets, options = {}) {
40559
40870
  import {
40560
40871
  appendFileSync,
40561
40872
  closeSync as closeSync4,
40562
- existsSync as existsSync12,
40873
+ existsSync as existsSync13,
40563
40874
  fstatSync,
40564
40875
  mkdirSync as mkdirSync10,
40565
40876
  openSync as openSync4,
40566
40877
  opendirSync,
40567
- readFileSync as readFileSync13,
40878
+ readFileSync as readFileSync14,
40568
40879
  readSync,
40569
40880
  readdirSync as readdirSync4
40570
40881
  } from "fs";
40571
- import { dirname as dirname11, join as join16 } from "path";
40572
- var JOURNAL_DIR = join16(primConfigDirectory(), "moves");
40882
+ import { dirname as dirname11, join as join17 } from "path";
40883
+ var JOURNAL_DIR = join17(primConfigDirectory(), "moves");
40573
40884
  var JOURNAL_BASENAME = "journal.ndjson";
40574
40885
  var JOURNAL_STATS_SAMPLE_BYTES = 64 * 1024;
40575
40886
  var PENDING_STATS_MAX_FILES = 128;
@@ -40581,7 +40892,7 @@ function envSlug(apiUrl) {
40581
40892
  return slug;
40582
40893
  }
40583
40894
  function currentEnvDir() {
40584
- return join16(JOURNAL_DIR, envSlug(getSiteUrl()));
40895
+ return join17(JOURNAL_DIR, envSlug(getSiteUrl()));
40585
40896
  }
40586
40897
  function parseMoves(content) {
40587
40898
  const moves = [];
@@ -40597,23 +40908,23 @@ function parseMoves(content) {
40597
40908
  return moves;
40598
40909
  }
40599
40910
  function readMovesFromPath(path9) {
40600
- if (!existsSync12(path9)) {
40911
+ if (!existsSync13(path9)) {
40601
40912
  return [];
40602
40913
  }
40603
- return parseMoves(readFileSync13(path9, "utf-8"));
40914
+ return parseMoves(readFileSync14(path9, "utf-8"));
40604
40915
  }
40605
40916
  function listBuckets() {
40606
40917
  const out = [];
40607
40918
  const envDir = currentEnvDir();
40608
- if (!existsSync12(envDir)) {
40919
+ if (!existsSync13(envDir)) {
40609
40920
  return out;
40610
40921
  }
40611
40922
  for (const entry of readdirSync4(envDir, { withFileTypes: true })) {
40612
40923
  if (!entry.isDirectory()) {
40613
40924
  continue;
40614
40925
  }
40615
- const path9 = join16(envDir, entry.name, JOURNAL_BASENAME);
40616
- if (existsSync12(path9)) {
40926
+ const path9 = join17(envDir, entry.name, JOURNAL_BASENAME);
40927
+ if (existsSync13(path9)) {
40617
40928
  out.push({ bucket: entry.name, path: path9 });
40618
40929
  }
40619
40930
  }
@@ -40673,7 +40984,7 @@ function parseFlushingPid(name) {
40673
40984
  return Number.isSafeInteger(pid) && pid > 0 ? pid : void 0;
40674
40985
  }
40675
40986
  function listFlushingInDir(dir, bucket, options = {}) {
40676
- if (!existsSync12(dir)) {
40987
+ if (!existsSync13(dir)) {
40677
40988
  return [];
40678
40989
  }
40679
40990
  const out = [];
@@ -40687,7 +40998,7 @@ function listFlushingInDir(dir, bucket, options = {}) {
40687
40998
  entry = entries.readSync();
40688
40999
  continue;
40689
41000
  }
40690
- const path9 = join16(dir, entry.name);
41001
+ const path9 = join17(dir, entry.name);
40691
41002
  let sample;
40692
41003
  try {
40693
41004
  sample = sampleJournalFile(path9, remainingBytes);
@@ -40714,7 +41025,7 @@ function listFlushingInDir(dir, bucket, options = {}) {
40714
41025
  }
40715
41026
  function listFlushing(options = {}) {
40716
41027
  const envDir = currentEnvDir();
40717
- if (!existsSync12(envDir)) {
41028
+ if (!existsSync13(envDir)) {
40718
41029
  return [];
40719
41030
  }
40720
41031
  const out = [];
@@ -40725,7 +41036,7 @@ function listFlushing(options = {}) {
40725
41036
  break;
40726
41037
  }
40727
41038
  if (entry.isDirectory()) {
40728
- const found = listFlushingInDir(join16(envDir, entry.name), entry.name, {
41039
+ const found = listFlushingInDir(join17(envDir, entry.name), entry.name, {
40729
41040
  sampleBytes: remainingBytes,
40730
41041
  maxFiles: maxFiles - out.length
40731
41042
  });
@@ -40783,9 +41094,9 @@ function pendingJournalStats() {
40783
41094
  }
40784
41095
 
40785
41096
  // src/commands/hermes-install.ts
40786
- import { existsSync as existsSync13, readFileSync as readFileSync14, rmSync as rmSync6, statSync as statSync3 } from "fs";
40787
- import { homedir as homedir8 } from "os";
40788
- import { join as join17 } from "path";
41097
+ import { existsSync as existsSync14, readFileSync as readFileSync15, rmSync as rmSync6, statSync as statSync3 } from "fs";
41098
+ import { homedir as homedir9 } from "os";
41099
+ import { join as join18 } from "path";
40789
41100
 
40790
41101
  // node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/browser/dist/nodes/identity.js
40791
41102
  var ALIAS = /* @__PURE__ */ Symbol.for("yaml.alias");
@@ -47053,33 +47364,33 @@ function stringify3(value, replacer, options) {
47053
47364
  }
47054
47365
 
47055
47366
  // src/commands/hermes-install.ts
47056
- var CAPTURE_BIN3 = "prim-hook";
47057
- var GATE_BIN3 = "prim-pre-tool-use";
47367
+ var CAPTURE_BIN4 = "prim-hook";
47368
+ var GATE_BIN4 = "prim-pre-tool-use";
47058
47369
  var POST_TOOL_USE_BIN3 = "prim-post-tool-use";
47059
- var SESSION_START_BIN3 = "prim-session-start";
47060
- var SESSION_END_BIN2 = "prim-session-end";
47370
+ var SESSION_START_BIN4 = "prim-session-start";
47371
+ var SESSION_END_BIN3 = "prim-session-end";
47061
47372
  var HERMES_ARGS = "--agent hermes";
47062
47373
  var EDIT_MATCHER = "write_file|patch";
47063
47374
  var JSON_INDENT3 = 2;
47064
47375
  var CONFIG_MODE = 384;
47065
- var PRIM_BINS3 = [CAPTURE_BIN3, GATE_BIN3, POST_TOOL_USE_BIN3, SESSION_START_BIN3, SESSION_END_BIN2];
47376
+ var PRIM_BINS4 = [CAPTURE_BIN4, GATE_BIN4, POST_TOOL_USE_BIN3, SESSION_START_BIN4, SESSION_END_BIN3];
47066
47377
  function hermesHome() {
47067
- return process.env.HERMES_HOME ?? join17(homedir8(), ".hermes");
47378
+ return process.env.HERMES_HOME ?? join18(homedir9(), ".hermes");
47068
47379
  }
47069
47380
  function configPath() {
47070
- return join17(hermesHome(), "config.yaml");
47381
+ return join18(hermesHome(), "config.yaml");
47071
47382
  }
47072
47383
  function legacyShimPath() {
47073
- return join17(hermesHome(), "agent-hooks", "prim-shim.sh");
47384
+ return join18(hermesHome(), "agent-hooks", "prim-shim.sh");
47074
47385
  }
47075
- function commandFor(bin) {
47386
+ function commandFor2(bin) {
47076
47387
  return stableHookCommand(bin, HERMES_ARGS);
47077
47388
  }
47078
47389
  function legacyCommandFor(bin) {
47079
47390
  return `"${legacyShimPath()}" ${bin} ${HERMES_ARGS}`;
47080
47391
  }
47081
47392
  function commandUsesBin(command, bin) {
47082
- return command === commandFor(bin) || command === legacyCommandFor(bin);
47393
+ return command === commandFor2(bin) || command === legacyCommandFor(bin);
47083
47394
  }
47084
47395
  var CAPTURE_EVENTS2 = [
47085
47396
  "on_session_start",
@@ -47091,13 +47402,13 @@ var CAPTURE_EVENTS2 = [
47091
47402
  "subagent_stop"
47092
47403
  ];
47093
47404
  var GATE_TIMEOUT_SECONDS = 10;
47094
- var REGISTRATIONS2 = [
47095
- ...CAPTURE_EVENTS2.map((event) => ({ event, bin: CAPTURE_BIN3 })),
47096
- { event: "pre_tool_call", matcher: EDIT_MATCHER, bin: GATE_BIN3, timeout: GATE_TIMEOUT_SECONDS },
47405
+ var REGISTRATIONS3 = [
47406
+ ...CAPTURE_EVENTS2.map((event) => ({ event, bin: CAPTURE_BIN4 })),
47407
+ { event: "pre_tool_call", matcher: EDIT_MATCHER, bin: GATE_BIN4, timeout: GATE_TIMEOUT_SECONDS },
47097
47408
  { event: "post_tool_call", matcher: EDIT_MATCHER, bin: POST_TOOL_USE_BIN3 },
47098
47409
  { event: "post_approval_response", bin: POST_TOOL_USE_BIN3 },
47099
- { event: "on_session_start", bin: SESSION_START_BIN3 },
47100
- { event: "on_session_end", bin: SESSION_END_BIN2 }
47410
+ { event: "on_session_start", bin: SESSION_START_BIN4 },
47411
+ { event: "on_session_end", bin: SESSION_END_BIN3 }
47101
47412
  ];
47102
47413
  function yamlValue(node) {
47103
47414
  return typeof node?.toJSON === "function" ? node.toJSON?.() : node;
@@ -47107,7 +47418,7 @@ function hookEntry(node) {
47107
47418
  return typeof value === "object" && value !== null && typeof value.command === "string" ? value : null;
47108
47419
  }
47109
47420
  function entryFor(reg) {
47110
- const command = commandFor(reg.bin);
47421
+ const command = commandFor2(reg.bin);
47111
47422
  const entry = reg.matcher ? { matcher: reg.matcher, command } : { command };
47112
47423
  if (reg.timeout !== void 0) {
47113
47424
  entry.timeout = reg.timeout;
@@ -47129,7 +47440,7 @@ function ensureReg(list, reg, force) {
47129
47440
  }
47130
47441
  function applyInstall3(hooks, force) {
47131
47442
  const next = { ...hooks };
47132
- for (const reg of REGISTRATIONS2) {
47443
+ for (const reg of REGISTRATIONS3) {
47133
47444
  next[reg.event] = ensureReg(next[reg.event] ?? [], reg, force);
47134
47445
  }
47135
47446
  return next;
@@ -47138,7 +47449,7 @@ function applyUninstall3(hooks) {
47138
47449
  const next = {};
47139
47450
  for (const [event, list] of Object.entries(hooks)) {
47140
47451
  let kept = list;
47141
- for (const bin of PRIM_BINS3) {
47452
+ for (const bin of PRIM_BINS4) {
47142
47453
  kept = stripBin(kept, bin);
47143
47454
  }
47144
47455
  if (kept.length > 0) {
@@ -47148,15 +47459,15 @@ function applyUninstall3(hooks) {
47148
47459
  return next;
47149
47460
  }
47150
47461
  function isGateInstalled3(hooks) {
47151
- return (hooks.pre_tool_call ?? []).some((e) => commandUsesBin(e.command, GATE_BIN3));
47462
+ return (hooks.pre_tool_call ?? []).some((e) => commandUsesBin(e.command, GATE_BIN4));
47152
47463
  }
47153
47464
  function isCaptureInstalled(hooks) {
47154
47465
  return CAPTURE_EVENTS2.some(
47155
- (event) => (hooks[event] ?? []).some((e) => commandUsesBin(e.command, CAPTURE_BIN3))
47466
+ (event) => (hooks[event] ?? []).some((e) => commandUsesBin(e.command, CAPTURE_BIN4))
47156
47467
  );
47157
47468
  }
47158
47469
  function entryUsesOwnedBin(entry) {
47159
- return PRIM_BINS3.some(
47470
+ return PRIM_BINS4.some(
47160
47471
  (bin) => commandUsesBin(entry.command, bin) || commandMatchesBin(entry.command, bin)
47161
47472
  );
47162
47473
  }
@@ -47171,21 +47482,21 @@ function hasAnyHookRegistration3(hooks) {
47171
47482
  function hookRuntimeResolutions3(hooks) {
47172
47483
  const resolutions = hookCommandResolutions(
47173
47484
  Object.values(hooks).flatMap((entries) => entries.map((entry) => entry.command)),
47174
- PRIM_BINS3
47485
+ PRIM_BINS4
47175
47486
  );
47176
47487
  for (const entries of Object.values(hooks)) {
47177
47488
  for (const entry of entries) {
47178
- for (const bin of PRIM_BINS3) {
47489
+ for (const bin of PRIM_BINS4) {
47179
47490
  if (entry.command === legacyCommandFor(bin)) resolutions.push({ kind: "legacy_path" });
47180
47491
  }
47181
47492
  }
47182
47493
  }
47183
47494
  return resolutions;
47184
47495
  }
47185
- function inspectHookRuntimeResolutions3() {
47496
+ function inspectHookRuntimeResolutions4() {
47186
47497
  const path9 = configPath();
47187
- if (!existsSync13(path9)) return [];
47188
- return hookRuntimeResolutions3(readHooks(parseHermesDocument(readFileSync14(path9, "utf8"))));
47498
+ if (!existsSync14(path9)) return [];
47499
+ return hookRuntimeResolutions3(readHooks(parseHermesDocument(readFileSync15(path9, "utf8"))));
47189
47500
  }
47190
47501
  function entryMatchesRegistration3(owned, registration) {
47191
47502
  const expected = entryFor(registration);
@@ -47193,7 +47504,7 @@ function entryMatchesRegistration3(owned, registration) {
47193
47504
  }
47194
47505
  function hasCompleteHookRegistration3(hooks) {
47195
47506
  const owned = ownedRegistrationEntries3(hooks);
47196
- return owned.length === REGISTRATIONS2.length && REGISTRATIONS2.every(
47507
+ return owned.length === REGISTRATIONS3.length && REGISTRATIONS3.every(
47197
47508
  (registration) => owned.filter((entry) => entryMatchesRegistration3(entry, registration)).length === 1
47198
47509
  );
47199
47510
  }
@@ -47269,7 +47580,7 @@ function serializeHooks(hooks) {
47269
47580
  return stringify3({ hooks }, { lineWidth: 0 });
47270
47581
  }
47271
47582
  function isPrimEntry(entry) {
47272
- return PRIM_BINS3.some((bin) => commandUsesBin(entry.command, bin));
47583
+ return PRIM_BINS4.some((bin) => commandUsesBin(entry.command, bin));
47273
47584
  }
47274
47585
  function entryKey(entry) {
47275
47586
  return JSON.stringify(entry);
@@ -47454,11 +47765,11 @@ function assertMergeValid(before, after, expectedHooks) {
47454
47765
  }
47455
47766
  }
47456
47767
  function readConfigSnapshot(path9) {
47457
- if (!existsSync13(path9)) return { exists: false, mode: CONFIG_MODE, raw: "" };
47768
+ if (!existsSync14(path9)) return { exists: false, mode: CONFIG_MODE, raw: "" };
47458
47769
  return {
47459
47770
  exists: true,
47460
47771
  mode: statSync3(path9).mode & 511,
47461
- raw: readFileSync14(path9, "utf8")
47772
+ raw: readFileSync15(path9, "utf8")
47462
47773
  };
47463
47774
  }
47464
47775
  var CONCURRENT_CONFIG_MESSAGE = "Hermes config changed during update; concurrent changes were preserved, retry the command";
@@ -47467,7 +47778,7 @@ function writeHermesConfigSnapshot(path9, before, after, expectedHooks) {
47467
47778
  ensureParent: true,
47468
47779
  mode: before.mode,
47469
47780
  validate(temporaryPath) {
47470
- const flushed = readFileSync14(temporaryPath, "utf8");
47781
+ const flushed = readFileSync15(temporaryPath, "utf8");
47471
47782
  if (!mergePreservesHermesSemantics(before.raw, flushed, expectedHooks)) {
47472
47783
  throw new Error(INVALID_MERGE_MESSAGE);
47473
47784
  }
@@ -47490,7 +47801,7 @@ function autoAcceptOf(raw) {
47490
47801
  function readHooksFromRaw(raw) {
47491
47802
  return readHooks(parseHermesDocument(raw));
47492
47803
  }
47493
- function performInstall3(opts) {
47804
+ function performInstall4(opts) {
47494
47805
  (opts.stageRuntime ?? stageHookRuntime)();
47495
47806
  const path9 = configPath();
47496
47807
  const snapshot = readConfigSnapshot(path9);
@@ -47518,9 +47829,9 @@ function performInstall3(opts) {
47518
47829
  changed
47519
47830
  };
47520
47831
  }
47521
- function performUninstall3() {
47832
+ function performUninstall4() {
47522
47833
  const path9 = configPath();
47523
- if (!existsSync13(path9)) {
47834
+ if (!existsSync14(path9)) {
47524
47835
  removeLegacyShim();
47525
47836
  return { path: path9, gate: false, capture: false, autoAccept: false, changed: false };
47526
47837
  }
@@ -47543,9 +47854,9 @@ function performUninstall3() {
47543
47854
  changed
47544
47855
  };
47545
47856
  }
47546
- function performStatus3() {
47857
+ function performStatus4() {
47547
47858
  const path9 = configPath();
47548
- const raw = existsSync13(path9) ? readFileSync14(path9, "utf8") : "";
47859
+ const raw = existsSync14(path9) ? readFileSync15(path9, "utf8") : "";
47549
47860
  const hooks = raw ? readHooks(parseHermesDocument(raw)) : {};
47550
47861
  return {
47551
47862
  path: path9,
@@ -47569,7 +47880,7 @@ function registerHermesCommands(program3) {
47569
47880
  const hermes = program3.command("hermes").description("Manage the prim Hermes Agent integration (capture, gate, ingest, presence)");
47570
47881
  hermes.command("install").description("Register the prim hooks in Hermes's ~/.hermes/config.yaml").option("--scope <scope>", "user (default; Hermes config is global-only)").option("--force", "Replace any drifted prim hook entries").option("--auto-accept", "Also set hooks_auto_accept: true so the hooks need no TTY consent").action((opts) => {
47571
47882
  rejectProjectScope(opts.scope);
47572
- const result = performInstall3({
47883
+ const result = performInstall4({
47573
47884
  force: opts.force ?? false,
47574
47885
  autoAccept: opts.autoAccept ?? false
47575
47886
  });
@@ -47580,14 +47891,14 @@ function registerHermesCommands(program3) {
47580
47891
  console.log(JSON.stringify(result, null, JSON_INDENT3));
47581
47892
  });
47582
47893
  hermes.command("uninstall").description("Remove all prim hooks from Hermes's ~/.hermes/config.yaml").action(() => {
47583
- const result = performUninstall3();
47894
+ const result = performUninstall4();
47584
47895
  console.error(
47585
47896
  result.changed ? `[prim] prim hooks removed from ${result.path}` : `[prim] no prim hooks to remove at ${result.path} (nothing changed)`
47586
47897
  );
47587
47898
  console.log(JSON.stringify(result, null, JSON_INDENT3));
47588
47899
  });
47589
47900
  hermes.command("status").description("Report whether each prim surface (gate, capture) is installed").action(() => {
47590
- const result = performStatus3();
47901
+ const result = performStatus4();
47591
47902
  const mark = (b) => b ? "\u2713" : "\u2717";
47592
47903
  console.error(
47593
47904
  `[prim] hermes: gate ${mark(result.gate)} \xB7 capture ${mark(result.capture)} (${result.path})`
@@ -47635,7 +47946,7 @@ function checkAuth() {
47635
47946
  return classifyAuthCredential(
47636
47947
  credential,
47637
47948
  storedCredential ? getTokenExpiresAt() : void 0,
47638
- storedCredential && existsSync14(REFRESH_TOKEN_PATH)
47949
+ storedCredential && existsSync15(REFRESH_TOKEN_PATH)
47639
47950
  );
47640
47951
  }
47641
47952
  function classifyDaemonHealth(snapshot, options = {}) {
@@ -47979,6 +48290,34 @@ function classifyCodexHooks(statuses) {
47979
48290
  detail: "installed; Codex trust is not machine-readable \u2014 verify with `/hooks`"
47980
48291
  };
47981
48292
  }
48293
+ function classifyCursorHooks(statuses) {
48294
+ const installed = statuses.filter((status) => status.present);
48295
+ if (installed.length === 0)
48296
+ return { name: "cursor-hooks", status: "ok", detail: "not installed" };
48297
+ if (installed.some((status) => !status.complete)) {
48298
+ return {
48299
+ name: "cursor-hooks",
48300
+ status: "fail",
48301
+ detail: "incomplete or drifted native lifecycle \u2014 run `prim cursor install --force`"
48302
+ };
48303
+ }
48304
+ const user = statuses.find((status) => status.footer !== void 0);
48305
+ if (user?.present && user.footer === false && !user.footerPreservedCustom) {
48306
+ return {
48307
+ name: "cursor-hooks",
48308
+ status: "fail",
48309
+ detail: "native lifecycle ready but Cursor CLI footer is missing \u2014 run `prim cursor install --scope user --force`"
48310
+ };
48311
+ }
48312
+ if (statuses.some((status) => status.footerPreservedCustom)) {
48313
+ return {
48314
+ name: "cursor-hooks",
48315
+ status: "warn",
48316
+ detail: "native lifecycle ready; custom Cursor CLI footer preserved"
48317
+ };
48318
+ }
48319
+ return { name: "cursor-hooks", status: "ok", detail: "complete native lifecycle ready" };
48320
+ }
47982
48321
  function classifyHermesHooks(status) {
47983
48322
  if (!status.present) {
47984
48323
  return { name: "hermes-hooks", status: "ok", detail: "not installed" };
@@ -48010,7 +48349,18 @@ function checkAgentHooks() {
48010
48349
  });
48011
48350
  }
48012
48351
  try {
48013
- checks.push(classifyHermesHooks(performStatus3()));
48352
+ const status = performStatus3();
48353
+ checks.push(classifyCursorHooks([status.project, status.user]));
48354
+ } catch (error) {
48355
+ const detail = boundedHealthError(error instanceof Error ? error.message : String(error));
48356
+ checks.push({
48357
+ name: "cursor-hooks",
48358
+ status: "fail",
48359
+ detail: detail ?? "hook configuration is unreadable"
48360
+ });
48361
+ }
48362
+ try {
48363
+ checks.push(classifyHermesHooks(performStatus4()));
48014
48364
  } catch (error) {
48015
48365
  const detail = boundedHealthError(error instanceof Error ? error.message : String(error));
48016
48366
  checks.push({
@@ -48120,7 +48470,8 @@ function checkHookRuntime() {
48120
48470
  [
48121
48471
  ...inspectHookRuntimeResolutions(),
48122
48472
  ...inspectHookRuntimeResolutions2(),
48123
- ...inspectHookRuntimeResolutions3()
48473
+ ...inspectHookRuntimeResolutions3(),
48474
+ ...inspectHookRuntimeResolutions4()
48124
48475
  ],
48125
48476
  inspectHookRuntime,
48126
48477
  packageVersion
@@ -48255,12 +48606,12 @@ function registerDoctorCommands(program3) {
48255
48606
  }
48256
48607
 
48257
48608
  // src/commands/moves.ts
48258
- import { existsSync as existsSync16, mkdirSync as mkdirSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
48259
- import { join as join20 } from "path";
48609
+ import { existsSync as existsSync17, mkdirSync as mkdirSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
48610
+ import { join as join21 } from "path";
48260
48611
 
48261
48612
  // src/flusher.ts
48262
48613
  import { createReadStream, renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
48263
- import { dirname as dirname13, join as join19 } from "path";
48614
+ import { dirname as dirname13, join as join20 } from "path";
48264
48615
 
48265
48616
  // src/dead-letter.ts
48266
48617
  import { createHash as createHash9, randomBytes as randomBytes6 } from "crypto";
@@ -48268,7 +48619,7 @@ import {
48268
48619
  constants as constants5,
48269
48620
  chmodSync as chmodSync5,
48270
48621
  closeSync as closeSync5,
48271
- existsSync as existsSync15,
48622
+ existsSync as existsSync16,
48272
48623
  fchmodSync as fchmodSync3,
48273
48624
  fsyncSync as fsyncSync3,
48274
48625
  mkdirSync as mkdirSync11,
@@ -48277,16 +48628,16 @@ import {
48277
48628
  rmSync as rmSync7,
48278
48629
  writeFileSync as writeFileSync8
48279
48630
  } from "fs";
48280
- import { dirname as dirname12, join as join18 } from "path";
48631
+ import { dirname as dirname12, join as join19 } from "path";
48281
48632
  var DIRECTORY_MODE3 = 448;
48282
48633
  var FILE_MODE2 = 384;
48283
48634
  var DEAD_LETTER_DIRNAME = "dead-letter";
48284
48635
  function deadLetterDirectoryForRotation(flushingPath) {
48285
- return join18(dirname12(flushingPath), DEAD_LETTER_DIRNAME);
48636
+ return join19(dirname12(flushingPath), DEAD_LETTER_DIRNAME);
48286
48637
  }
48287
48638
  function deadLetterPathForRawLine(flushingPath, rawLine) {
48288
48639
  const quarantineId = createHash9("sha256").update(rawLine).digest("hex");
48289
- return join18(deadLetterDirectoryForRotation(flushingPath), `raw-${quarantineId}.json`);
48640
+ return join19(deadLetterDirectoryForRotation(flushingPath), `raw-${quarantineId}.json`);
48290
48641
  }
48291
48642
  function ensureDeadLetterDirectory(flushingPath, persistDirectory) {
48292
48643
  const directory = deadLetterDirectoryForRotation(flushingPath);
@@ -48296,11 +48647,11 @@ function ensureDeadLetterDirectory(flushingPath, persistDirectory) {
48296
48647
  return directory;
48297
48648
  }
48298
48649
  function persistDeadLetter(directory, path9, quarantineId, record2, persistDirectory) {
48299
- if (existsSync15(path9)) {
48650
+ if (existsSync16(path9)) {
48300
48651
  persistDirectory(directory);
48301
48652
  return;
48302
48653
  }
48303
- const temporaryPath = join18(
48654
+ const temporaryPath = join19(
48304
48655
  directory,
48305
48656
  `.${quarantineId}.${String(process.pid)}.${randomBytes6(8).toString("hex")}.tmp`
48306
48657
  );
@@ -48332,7 +48683,7 @@ function quarantineMove(flushingPath, move, reason, now = Date.now, options = {}
48332
48683
  reason,
48333
48684
  move
48334
48685
  };
48335
- const path9 = join18(directory, `${record2.quarantineId}.json`);
48686
+ const path9 = join19(directory, `${record2.quarantineId}.json`);
48336
48687
  persistDeadLetter(directory, path9, record2.quarantineId, record2, persistDirectory);
48337
48688
  return record2;
48338
48689
  }
@@ -48437,6 +48788,12 @@ function deadLetterReason(error) {
48437
48788
  }
48438
48789
  return void 0;
48439
48790
  }
48791
+ function mayBeBatchSizeFailure(error) {
48792
+ if (error instanceof HttpError) {
48793
+ return error.status >= 500 && error.status !== 503;
48794
+ }
48795
+ return error instanceof Error && error.name === "TimeoutError";
48796
+ }
48440
48797
  async function* rawJournalLines(input) {
48441
48798
  let pending = [];
48442
48799
  let pendingBytes = 0;
@@ -48478,7 +48835,7 @@ async function drainFlushingPath(flushingPath, client, binding, options = {}) {
48478
48835
  return { flushed: batch2.length, quarantined: 0 };
48479
48836
  } catch (error) {
48480
48837
  const reason = deadLetterReason(error);
48481
- if (!reason) {
48838
+ if (!(reason || mayBeBatchSizeFailure(error))) {
48482
48839
  throw error;
48483
48840
  }
48484
48841
  if (batch2.length > 1) {
@@ -48487,6 +48844,9 @@ async function drainFlushingPath(flushingPath, client, binding, options = {}) {
48487
48844
  const right = await postBatch(batch2.slice(midpoint));
48488
48845
  return addDrainCounts(left, right);
48489
48846
  }
48847
+ if (!reason) {
48848
+ throw error;
48849
+ }
48490
48850
  const [move] = batch2;
48491
48851
  const quarantined = quarantineMove(
48492
48852
  flushingPath,
@@ -48644,7 +49004,7 @@ async function flushOnce() {
48644
49004
  return inspection.retainedBuckets.length > 0 ? { flushed: total, quarantined, retained: inspection.retainedBuckets } : { flushed: total, quarantined };
48645
49005
  }
48646
49006
  var flushInFlight;
48647
- var FLUSH_LOCK_PATH = join19(dirname13(JOURNAL_DIR), ".flush.lock");
49007
+ var FLUSH_LOCK_PATH = join20(dirname13(JOURNAL_DIR), ".flush.lock");
48648
49008
  var FLUSH_LOCK_TIMEOUT_MS = 250;
48649
49009
  function isFlushLockContended(error) {
48650
49010
  return error instanceof Error && error.message.startsWith("timed out waiting for file lock");
@@ -48778,19 +49138,19 @@ function registerMovesCommands(program3) {
48778
49138
  }
48779
49139
  });
48780
49140
  moves.command("bind").description("Pin the current directory to an org via .prim/workspace.json").requiredOption("--orgId <orgId>", "Convex organization id").action((opts) => {
48781
- const dir = join20(process.cwd(), ".prim");
48782
- if (!existsSync16(dir)) {
49141
+ const dir = join21(process.cwd(), ".prim");
49142
+ if (!existsSync17(dir)) {
48783
49143
  mkdirSync12(dir, { recursive: true, mode: DIR_MODE });
48784
49144
  }
48785
- const file = join20(process.cwd(), WORKSPACE_FILE);
49145
+ const file = join21(process.cwd(), WORKSPACE_FILE);
48786
49146
  writeFileSync9(file, JSON.stringify({ orgId: opts.orgId, boundAt: Date.now() }, null, 2), {
48787
49147
  mode: FILE_MODE3
48788
49148
  });
48789
49149
  console.log(`[prim] bound ${process.cwd()} to org ${opts.orgId}`);
48790
49150
  });
48791
49151
  moves.command("drop").description("Remove the .prim/workspace.json binding from the cwd").action(() => {
48792
- const file = join20(process.cwd(), WORKSPACE_FILE);
48793
- if (!existsSync16(file)) {
49152
+ const file = join21(process.cwd(), WORKSPACE_FILE);
49153
+ if (!existsSync17(file)) {
48794
49154
  console.log("[prim] no workspace binding in cwd");
48795
49155
  return;
48796
49156
  }
@@ -48881,31 +49241,31 @@ function registerReconcileCommands(program3) {
48881
49241
 
48882
49242
  // src/commands/session.ts
48883
49243
  import {
48884
- existsSync as existsSync18,
49244
+ existsSync as existsSync19,
48885
49245
  mkdirSync as mkdirSync13,
48886
- readFileSync as readFileSync16,
49246
+ readFileSync as readFileSync17,
48887
49247
  readdirSync as readdirSync5,
48888
49248
  unlinkSync as unlinkSync6,
48889
49249
  writeFileSync as writeFileSync10
48890
49250
  } from "fs";
48891
- import { join as join22 } from "path";
49251
+ import { join as join23 } from "path";
48892
49252
 
48893
49253
  // src/binding.ts
48894
- import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
48895
- import { dirname as dirname14, join as join21 } from "path";
49254
+ import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
49255
+ import { dirname as dirname14, join as join22 } from "path";
48896
49256
  var PRIM_CONFIG_DIR = primConfigDirectory();
48897
- var SESSIONS_DIR = join21(PRIM_CONFIG_DIR, "sessions");
49257
+ var SESSIONS_DIR = join22(PRIM_CONFIG_DIR, "sessions");
48898
49258
 
48899
49259
  // src/commands/session.ts
48900
49260
  var DIR_MODE2 = 448;
48901
49261
  var FILE_MODE4 = 384;
48902
49262
  function ensureDir() {
48903
- if (!existsSync18(SESSIONS_DIR)) {
49263
+ if (!existsSync19(SESSIONS_DIR)) {
48904
49264
  mkdirSync13(SESSIONS_DIR, { recursive: true, mode: DIR_MODE2 });
48905
49265
  }
48906
49266
  }
48907
49267
  function markerPath(sessionId) {
48908
- return join22(SESSIONS_DIR, `${sessionId}.json`);
49268
+ return join23(SESSIONS_DIR, `${sessionId}.json`);
48909
49269
  }
48910
49270
  function registerSessionCommands(program3) {
48911
49271
  const session = program3.command("session").description("Decision Event Pipeline \u2014 session binding markers");
@@ -48921,7 +49281,7 @@ function registerSessionCommands(program3) {
48921
49281
  console.log(`[prim] session ${sessionId} bound to org ${opts.orgId}`);
48922
49282
  });
48923
49283
  session.command("list").description("List active session markers").action(() => {
48924
- if (!existsSync18(SESSIONS_DIR)) {
49284
+ if (!existsSync19(SESSIONS_DIR)) {
48925
49285
  console.log("[prim] no session markers");
48926
49286
  return;
48927
49287
  }
@@ -48933,7 +49293,7 @@ function registerSessionCommands(program3) {
48933
49293
  for (const f of files) {
48934
49294
  const sessionId = f.replace(/\.json$/, "");
48935
49295
  try {
48936
- const m = JSON.parse(readFileSync16(join22(SESSIONS_DIR, f), "utf-8"));
49296
+ const m = JSON.parse(readFileSync17(join23(SESSIONS_DIR, f), "utf-8"));
48937
49297
  console.log(`${sessionId} org=${m.orgId}`);
48938
49298
  } catch {
48939
49299
  }
@@ -48941,7 +49301,7 @@ function registerSessionCommands(program3) {
48941
49301
  });
48942
49302
  session.command("drop <sessionId>").description("Remove a session marker").action((sessionId) => {
48943
49303
  const p = markerPath(sessionId);
48944
- if (!existsSync18(p)) {
49304
+ if (!existsSync19(p)) {
48945
49305
  console.log(`[prim] no marker for session ${sessionId}`);
48946
49306
  return;
48947
49307
  }
@@ -48952,13 +49312,14 @@ function registerSessionCommands(program3) {
48952
49312
 
48953
49313
  // src/commands/setup.ts
48954
49314
  import { spawnSync as spawnSync2 } from "child_process";
48955
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
48956
- import { join as join23 } from "path";
49315
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
49316
+ import { join as join24 } from "path";
48957
49317
  var EXIT_INCOMPLETE = 1;
48958
49318
  var EXIT_USAGE3 = 2;
48959
49319
  var SESSION_LABELS = {
48960
49320
  claude: "Claude Code integration",
48961
49321
  codex: "Codex integration",
49322
+ cursor: "Cursor integration",
48962
49323
  hermes: "Hermes integration"
48963
49324
  };
48964
49325
  function planSetupSteps(opts) {
@@ -49034,8 +49395,8 @@ function detectProjectConflicts(agent, run) {
49034
49395
  }
49035
49396
  try {
49036
49397
  const root = gitToplevel();
49037
- const preCommit = root && join23(root, ".git", "hooks", "pre-commit");
49038
- if (preCommit && existsSync19(preCommit) && readFileSync17(preCommit, "utf-8").includes("prim-pre-commit")) {
49398
+ const preCommit = root && join24(root, ".git", "hooks", "pre-commit");
49399
+ if (preCommit && existsSync20(preCommit) && readFileSync18(preCommit, "utf-8").includes("prim-pre-commit")) {
49039
49400
  conflicts.push(CONFLICT_HOOKS);
49040
49401
  }
49041
49402
  } catch {
@@ -49053,6 +49414,9 @@ function detectAgent(env4) {
49053
49414
  if (env4.HERMES_INTERACTIVE) {
49054
49415
  return "hermes";
49055
49416
  }
49417
+ if (env4.CURSOR_AGENT) {
49418
+ return "cursor";
49419
+ }
49056
49420
  return "claude";
49057
49421
  }
49058
49422
  function resolveAgent(agentFlag, env4) {
@@ -49074,7 +49438,7 @@ function parseSetupAuthStatus(result) {
49074
49438
  function registerSetupCommand(program3, dependencies = {}) {
49075
49439
  program3.command("setup").description(
49076
49440
  "Install everything in one shot (auth, session + git hooks, daemon, skill, welcome)"
49077
- ).option("--agent <agent>", "claude, codex, or hermes (auto-detected when omitted)").option(
49441
+ ).option("--agent <agent>", "claude, codex, cursor, or hermes (auto-detected when omitted)").option(
49078
49442
  "--scope <scope>",
49079
49443
  "user (default \u2014 install once for every repo) or project (this repo only)",
49080
49444
  "user"
@@ -49083,9 +49447,9 @@ function registerSetupCommand(program3, dependencies = {}) {
49083
49447
  "with the default user scope, remove any project-scoped prim config in this repo (else just warn)"
49084
49448
  ).option("--no-daemon", "stop and disable the companion daemon").action((opts) => {
49085
49449
  const { agent: agentInput, detected } = resolveAgent(opts.agent, process.env);
49086
- if (agentInput !== "claude" && agentInput !== "codex" && agentInput !== "hermes") {
49450
+ if (agentInput !== "claude" && agentInput !== "codex" && agentInput !== "cursor" && agentInput !== "hermes") {
49087
49451
  process.stderr.write(
49088
- `[prim] unknown --agent "${agentInput}" (expected claude, codex, or hermes)
49452
+ `[prim] unknown --agent "${agentInput}" (expected claude, codex, cursor, or hermes)
49089
49453
  `
49090
49454
  );
49091
49455
  (dependencies.exit ?? process.exit)(EXIT_USAGE3);
@@ -49196,18 +49560,22 @@ function registerSetupCommand(program3, dependencies = {}) {
49196
49560
  }
49197
49561
 
49198
49562
  // src/commands/skill.ts
49563
+ import { createHash as createHash11 } from "crypto";
49199
49564
  import {
49200
49565
  constants as constants7,
49201
49566
  closeSync as closeSync7,
49202
- existsSync as existsSync21,
49567
+ existsSync as existsSync22,
49203
49568
  fstatSync as fstatSync3,
49204
49569
  lstatSync as lstatSync7,
49205
49570
  openSync as openSync7,
49206
- readFileSync as readFileSync19,
49207
- readSync as readSync3
49571
+ readFileSync as readFileSync20,
49572
+ readSync as readSync3,
49573
+ readdirSync as readdirSync7,
49574
+ rmdirSync as rmdirSync2,
49575
+ unlinkSync as unlinkSync7
49208
49576
  } from "fs";
49209
- import { homedir as homedir10 } from "os";
49210
- import { dirname as dirname16, join as join26, resolve as resolve8 } from "path";
49577
+ import { homedir as homedir11 } from "os";
49578
+ import { dirname as dirname16, join as join27, resolve as resolve8 } from "path";
49211
49579
  import { fileURLToPath as fileURLToPath5 } from "url";
49212
49580
 
49213
49581
  // node_modules/.pnpm/diff@5.2.2/node_modules/diff/lib/index.mjs
@@ -49377,7 +49745,7 @@ Diff.prototype = {
49377
49745
  tokenize: function tokenize(value) {
49378
49746
  return value.split("");
49379
49747
  },
49380
- join: function join24(chars) {
49748
+ join: function join25(chars) {
49381
49749
  return chars.join("");
49382
49750
  }
49383
49751
  };
@@ -49717,28 +50085,28 @@ import { createHash as createHash10 } from "crypto";
49717
50085
  import {
49718
50086
  constants as constants6,
49719
50087
  closeSync as closeSync6,
49720
- existsSync as existsSync20,
50088
+ existsSync as existsSync21,
49721
50089
  fstatSync as fstatSync2,
49722
50090
  lstatSync as lstatSync6,
49723
50091
  mkdirSync as mkdirSync14,
49724
50092
  openSync as openSync6,
49725
- readFileSync as readFileSync18,
50093
+ readFileSync as readFileSync19,
49726
50094
  readSync as readSync2,
49727
50095
  readdirSync as readdirSync6,
49728
50096
  realpathSync as realpathSync4,
49729
50097
  rmSync as rmSync8,
49730
50098
  rmdirSync
49731
50099
  } from "fs";
49732
- import { homedir as homedir9 } from "os";
49733
- import { dirname as dirname15, isAbsolute as isAbsolute7, join as join25, relative as relative2, resolve as resolve7, sep as sep2 } from "path";
50100
+ import { homedir as homedir10 } from "os";
50101
+ import { dirname as dirname15, isAbsolute as isAbsolute8, join as join26, relative as relative2, resolve as resolve7, sep as sep2 } from "path";
49734
50102
  import { fileURLToPath as fileURLToPath4 } from "url";
49735
50103
  var __dirname4 = dirname15(fileURLToPath4(import.meta.url));
49736
50104
  var PLUGIN_DESCRIPTION = "Primitive decision-graph guidance for the prim CLI \u2014 a model-invoked skill installed by prim skill install.";
49737
50105
  var MAX_MANIFEST_BYTES2 = 64 * 1024;
49738
50106
  var MAX_SKILL_BYTES = 1024 * 1024;
49739
50107
  function pluginDirFor(cwd, scope) {
49740
- const base = scope === "user" ? join25(homedir9(), ".claude") : join25(gitToplevel(cwd) ?? cwd, ".claude");
49741
- return join25(base, "skills", "prim");
50108
+ const base = scope === "user" ? join26(homedir10(), ".claude") : join26(gitToplevel(cwd) ?? cwd, ".claude");
50109
+ return join26(base, "skills", "prim");
49742
50110
  }
49743
50111
  function resolvePluginDir(cwd, scope) {
49744
50112
  if (scope && scope !== "user" && scope !== "project") {
@@ -49751,7 +50119,7 @@ function packageVersion2() {
49751
50119
  let dir = __dirname4;
49752
50120
  while (dir !== dirname15(dir)) {
49753
50121
  const p = resolve7(dir, "package.json");
49754
- if (existsSync20(p)) return JSON.parse(readFileSync18(p, "utf-8")).version;
50122
+ if (existsSync21(p)) return JSON.parse(readFileSync19(p, "utf-8")).version;
49755
50123
  dir = dirname15(dir);
49756
50124
  }
49757
50125
  return "0.0.0";
@@ -49766,12 +50134,12 @@ function renderClaudePlugin() {
49766
50134
  return { manifest: pluginManifest(version), skill: loadSkill(), version };
49767
50135
  }
49768
50136
  function removeDirIfEmpty(dir) {
49769
- if (existsSync20(dir) && readdirSync6(dir).length === 0) rmdirSync(dir);
50137
+ if (existsSync21(dir) && readdirSync6(dir).length === 0) rmdirSync(dir);
49770
50138
  }
49771
50139
  function pluginPaths(dir) {
49772
50140
  return {
49773
- manifestPath: join25(dir, ".claude-plugin", "plugin.json"),
49774
- skillPath: join25(dir, "SKILL.md")
50141
+ manifestPath: join26(dir, ".claude-plugin", "plugin.json"),
50142
+ skillPath: join26(dir, "SKILL.md")
49775
50143
  };
49776
50144
  }
49777
50145
  function installClaudePlugin(cwd, opts) {
@@ -49779,8 +50147,8 @@ function installClaudePlugin(cwd, opts) {
49779
50147
  if (dir === null) return 1;
49780
50148
  const { manifestPath, skillPath } = pluginPaths(dir);
49781
50149
  const { manifest, skill } = renderClaudePlugin();
49782
- const manifestCurrent = existsSync20(manifestPath) ? readFileSync18(manifestPath, "utf-8") : null;
49783
- const skillCurrent = existsSync20(skillPath) ? readFileSync18(skillPath, "utf-8") : null;
50150
+ const manifestCurrent = existsSync21(manifestPath) ? readFileSync19(manifestPath, "utf-8") : null;
50151
+ const skillCurrent = existsSync21(skillPath) ? readFileSync19(skillPath, "utf-8") : null;
49784
50152
  if (manifestCurrent === manifest && skillCurrent === skill) {
49785
50153
  console.log("No changes \u2014 prim skill plugin already up to date.");
49786
50154
  return 0;
@@ -49789,7 +50157,7 @@ function installClaudePlugin(cwd, opts) {
49789
50157
  console.log(`Would write plugin to ${dir} (.claude-plugin/plugin.json + SKILL.md)`);
49790
50158
  return 0;
49791
50159
  }
49792
- mkdirSync14(join25(dir, ".claude-plugin"), { recursive: true });
50160
+ mkdirSync14(join26(dir, ".claude-plugin"), { recursive: true });
49793
50161
  atomicWrite4(manifestPath, manifest);
49794
50162
  atomicWrite4(skillPath, skill);
49795
50163
  console.log(`Installed prim skill plugin at ${dir}`);
@@ -49803,13 +50171,13 @@ function uninstallClaudePlugin(cwd, opts) {
49803
50171
  const dir = resolvePluginDir(cwd, opts.scope);
49804
50172
  if (dir === null) return 1;
49805
50173
  const { manifestPath, skillPath } = pluginPaths(dir);
49806
- if (!existsSync20(manifestPath) && !existsSync20(skillPath)) {
50174
+ if (!existsSync21(manifestPath) && !existsSync21(skillPath)) {
49807
50175
  console.log(`prim skill plugin not present at ${dir}`);
49808
50176
  return 0;
49809
50177
  }
49810
50178
  rmSync8(manifestPath, { force: true });
49811
50179
  rmSync8(skillPath, { force: true });
49812
- removeDirIfEmpty(join25(dir, ".claude-plugin"));
50180
+ removeDirIfEmpty(join26(dir, ".claude-plugin"));
49813
50181
  removeDirIfEmpty(dir);
49814
50182
  console.log(`Removed prim skill plugin from ${dir}`);
49815
50183
  return 0;
@@ -49818,7 +50186,7 @@ function statusClaudePlugin(cwd, opts) {
49818
50186
  const dir = resolvePluginDir(cwd, opts.scope);
49819
50187
  if (dir === null) return 1;
49820
50188
  const { skillPath } = pluginPaths(dir);
49821
- const installed = existsSync20(skillPath);
50189
+ const installed = existsSync21(skillPath);
49822
50190
  if (opts.json) {
49823
50191
  printJson({ installed, target: dir });
49824
50192
  return installed ? 0 : 1;
@@ -49853,11 +50221,109 @@ var AGENT_TARGET = {
49853
50221
  codex: "AGENTS.md",
49854
50222
  hermes: ".hermes.md"
49855
50223
  };
50224
+ var CURSOR_SKILL_OWNER = "@primitive.ai/prim";
50225
+ var CURSOR_SKILL_MANIFEST = ".prim-owned.json";
50226
+ function sha2563(content) {
50227
+ return createHash11("sha256").update(content).digest("hex");
50228
+ }
50229
+ function cursorSkillDirectory(cwd, scope) {
50230
+ const base = scope === "user" ? cursorConfigDirectory() : gitToplevel(cwd) ?? cwd;
50231
+ return join27(base, scope === "user" ? "skills" : ".cursor/skills", "prim");
50232
+ }
50233
+ function cursorSkillPaths(cwd, scope) {
50234
+ const directory = cursorSkillDirectory(cwd, scope);
50235
+ return {
50236
+ directory,
50237
+ skill: join27(directory, "SKILL.md"),
50238
+ manifest: join27(directory, CURSOR_SKILL_MANIFEST)
50239
+ };
50240
+ }
50241
+ function readCursorSkillManifest(path9) {
50242
+ try {
50243
+ const value = JSON.parse(readFileSync20(path9, "utf8"));
50244
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
50245
+ const record2 = value;
50246
+ if (record2.version !== 1 || record2.owner !== CURSOR_SKILL_OWNER || typeof record2.contentSha256 !== "string" || !/^[0-9a-f]{64}$/u.test(record2.contentSha256)) {
50247
+ return;
50248
+ }
50249
+ return record2;
50250
+ } catch {
50251
+ return;
50252
+ }
50253
+ }
50254
+ function cursorSkillStatus(cwd, scope) {
50255
+ const paths = cursorSkillPaths(cwd, scope);
50256
+ const manifest = readCursorSkillManifest(paths.manifest);
50257
+ const content = existsSync22(paths.skill) ? readFileSync20(paths.skill, "utf8") : void 0;
50258
+ const owned = manifest !== void 0;
50259
+ const installed = owned && content !== void 0 && sha2563(content) === manifest.contentSha256;
50260
+ return {
50261
+ installed,
50262
+ owned,
50263
+ edited: owned && content !== void 0 && !installed,
50264
+ target: paths.skill
50265
+ };
50266
+ }
50267
+ function validCursorSkillScope(scope) {
50268
+ if (scope === void 0 || scope === "project" || scope === "user") return true;
50269
+ console.error(`Unknown --scope "${scope}" (expected user or project)`);
50270
+ return false;
50271
+ }
50272
+ function installCursorSkill(cwd, opts) {
50273
+ const paths = cursorSkillPaths(cwd, opts.scope);
50274
+ const status = cursorSkillStatus(cwd, opts.scope);
50275
+ const manifestExists = existsSync22(paths.manifest);
50276
+ const skillExists = existsSync22(paths.skill);
50277
+ if (manifestExists && !status.owned || !manifestExists && skillExists || status.edited) {
50278
+ console.error(`Refusing to overwrite a foreign or edited Cursor skill at ${paths.skill}`);
50279
+ return 1;
50280
+ }
50281
+ const content = loadSkill();
50282
+ const manifest = {
50283
+ version: 1,
50284
+ owner: CURSOR_SKILL_OWNER,
50285
+ contentSha256: sha2563(content)
50286
+ };
50287
+ if (status.installed && readFileSync20(paths.skill, "utf8") === content) {
50288
+ console.log(`No changes \u2014 Cursor skill already up to date at ${paths.skill}`);
50289
+ return 0;
50290
+ }
50291
+ if (opts.dryRun) {
50292
+ const existing = skillExists ? readFileSync20(paths.skill, "utf8") : "";
50293
+ process.stdout.write(createPatch(paths.skill, existing, content, "current", "proposed"));
50294
+ return 0;
50295
+ }
50296
+ atomicWriteFile(paths.skill, content, { ensureParent: true });
50297
+ atomicWriteFile(paths.manifest, `${JSON.stringify(manifest, null, 2)}
50298
+ `, { ensureParent: true });
50299
+ console.log(`Installed Cursor skill at ${paths.skill}`);
50300
+ return 0;
50301
+ }
50302
+ function uninstallCursorSkill(cwd, scope) {
50303
+ const paths = cursorSkillPaths(cwd, scope);
50304
+ const status = cursorSkillStatus(cwd, scope);
50305
+ if (!status.owned) {
50306
+ console.log(`No Primitive-owned Cursor skill at ${paths.skill}`);
50307
+ return 0;
50308
+ }
50309
+ if (status.edited) {
50310
+ console.error(`Refusing to remove an edited Cursor skill at ${paths.skill}`);
50311
+ return 1;
50312
+ }
50313
+ if (existsSync22(paths.skill)) unlinkSync7(paths.skill);
50314
+ if (existsSync22(paths.manifest)) unlinkSync7(paths.manifest);
50315
+ try {
50316
+ if (readdirSync7(paths.directory).length === 0) rmdirSync2(paths.directory);
50317
+ } catch {
50318
+ }
50319
+ console.log(`Removed Primitive-owned Cursor skill from ${paths.skill}`);
50320
+ return 0;
50321
+ }
49856
50322
  function userTargetFor(agent) {
49857
- if (agent === "claude") return join26(homedir10(), ".claude", "CLAUDE.md");
49858
- if (agent === "codex") return join26(homedir10(), ".codex", "AGENTS.md");
50323
+ if (agent === "claude") return join27(homedir11(), ".claude", "CLAUDE.md");
50324
+ if (agent === "codex") return join27(homedir11(), ".codex", "AGENTS.md");
49859
50325
  if (agent === "hermes") {
49860
- return join26(process.env.HERMES_HOME ?? join26(homedir10(), ".hermes"), ".hermes.md");
50326
+ return join27(process.env.HERMES_HOME ?? join27(homedir11(), ".hermes"), ".hermes.md");
49861
50327
  }
49862
50328
  return null;
49863
50329
  }
@@ -49865,13 +50331,13 @@ function loadSkill() {
49865
50331
  let dir = __dirname5;
49866
50332
  while (dir !== dirname16(dir)) {
49867
50333
  const p = resolve8(dir, "SKILL.md");
49868
- if (existsSync21(p)) return readFileSync19(p, "utf-8");
50334
+ if (existsSync22(p)) return readFileSync20(p, "utf-8");
49869
50335
  dir = dirname16(dir);
49870
50336
  }
49871
50337
  throw new Error("SKILL.md not found in package");
49872
50338
  }
49873
50339
  function detectTargets(cwd) {
49874
- return TARGET_CANDIDATES.filter((p) => existsSync21(resolve8(cwd, p)));
50340
+ return TARGET_CANDIDATES.filter((p) => existsSync22(resolve8(cwd, p)));
49875
50341
  }
49876
50342
  function detectNewline(content) {
49877
50343
  return content.includes("\r\n") ? "\r\n" : "\n";
@@ -49908,18 +50374,18 @@ function resolveTarget(cwd, opts) {
49908
50374
  if (opts.target) return resolve8(cwd, opts.target);
49909
50375
  if (opts.scope === "user") {
49910
50376
  if (!opts.agent) {
49911
- console.error("--scope user requires --agent (claude, codex, or hermes)");
50377
+ console.error("--scope user requires --agent (claude, codex, cursor, or hermes)");
49912
50378
  return null;
49913
50379
  }
49914
50380
  const userTarget = userTargetFor(opts.agent);
49915
50381
  if (userTarget) return userTarget;
49916
- console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, or hermes)`);
50382
+ console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, cursor, or hermes)`);
49917
50383
  return null;
49918
50384
  }
49919
50385
  if (opts.agent) {
49920
50386
  const mapped = AGENT_TARGET[opts.agent];
49921
50387
  if (typeof mapped === "string") return resolve8(cwd, mapped);
49922
- console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, or hermes)`);
50388
+ console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, cursor, or hermes)`);
49923
50389
  return null;
49924
50390
  }
49925
50391
  const matches = detectTargets(cwd);
@@ -49931,9 +50397,13 @@ function resolveTarget(cwd, opts) {
49931
50397
  }
49932
50398
  function runInstall(cwd, opts) {
49933
50399
  if (opts.agent === "claude" && !opts.target) return installClaudePlugin(cwd, opts);
50400
+ if (opts.agent === "cursor" && !opts.target) {
50401
+ if (!validCursorSkillScope(opts.scope)) return 1;
50402
+ return installCursorSkill(cwd, opts);
50403
+ }
49934
50404
  const target = resolveTarget(cwd, opts);
49935
50405
  if (target === null) return 1;
49936
- const existing = existsSync21(target) ? readFileSync19(target, "utf-8") : "";
50406
+ const existing = existsSync22(target) ? readFileSync20(target, "utf-8") : "";
49937
50407
  const eol = existing ? detectNewline(existing) : "\n";
49938
50408
  const block = composeBlock(loadSkill(), eol);
49939
50409
  const next = applyBlock(existing, block, eol);
@@ -49951,13 +50421,17 @@ function runInstall(cwd, opts) {
49951
50421
  }
49952
50422
  function runUninstall(cwd, opts) {
49953
50423
  if (opts.agent === "claude" && !opts.target) return uninstallClaudePlugin(cwd, opts);
50424
+ if (opts.agent === "cursor" && !opts.target) {
50425
+ if (!validCursorSkillScope(opts.scope)) return 1;
50426
+ return uninstallCursorSkill(cwd, opts.scope);
50427
+ }
49954
50428
  const target = resolveTarget(cwd, opts);
49955
50429
  if (target === null) return 1;
49956
- if (!existsSync21(target)) {
50430
+ if (!existsSync22(target)) {
49957
50431
  console.log(`Skill block not present at ${target}`);
49958
50432
  return 0;
49959
50433
  }
49960
- const existing = readFileSync19(target, "utf-8");
50434
+ const existing = readFileSync20(target, "utf-8");
49961
50435
  const next = removeBlock(existing);
49962
50436
  if (next === null) {
49963
50437
  console.log(`Skill block not present at ${target}`);
@@ -49969,12 +50443,22 @@ function runUninstall(cwd, opts) {
49969
50443
  }
49970
50444
  function runStatus(cwd, opts) {
49971
50445
  if (opts.agent === "claude" && !opts.target) return statusClaudePlugin(cwd, opts);
50446
+ if (opts.agent === "cursor" && !opts.target) {
50447
+ if (!validCursorSkillScope(opts.scope)) return 1;
50448
+ const status = cursorSkillStatus(cwd, opts.scope);
50449
+ if (opts.json) printJson(status);
50450
+ else
50451
+ console.log(
50452
+ status.installed ? `Primitive Cursor skill installed at ${status.target}` : `No intact Primitive-owned Cursor skill at ${status.target}`
50453
+ );
50454
+ return status.installed ? 0 : 1;
50455
+ }
49972
50456
  const target = resolveTarget(cwd, opts);
49973
50457
  if (target === null) return 1;
49974
- const fileExists = existsSync21(target);
50458
+ const fileExists = existsSync22(target);
49975
50459
  let installed = false;
49976
50460
  if (fileExists) {
49977
- const content = readFileSync19(target, "utf-8");
50461
+ const content = readFileSync20(target, "utf-8");
49978
50462
  installed = content.includes(SKILL_BEGIN) && content.includes(SKILL_END);
49979
50463
  }
49980
50464
  if (opts.json) {
@@ -49994,7 +50478,7 @@ function runStatus(cwd, opts) {
49994
50478
  }
49995
50479
  function registerSkillCommands(program3) {
49996
50480
  const skill = program3.command("skill").description("Manage the prim skill in your project rules file");
49997
- skill.command("install").description("Install the prim skill block into your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, or hermes (selects the default rules file)").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").option("--dry-run", "Print a unified diff without writing").action((opts) => {
50481
+ skill.command("install").description("Install the prim skill block into your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, cursor, or hermes").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").option("--dry-run", "Print a unified diff without writing").action((opts) => {
49998
50482
  try {
49999
50483
  process.exit(runInstall(process.cwd(), opts));
50000
50484
  } catch (err) {
@@ -50002,16 +50486,16 @@ function registerSkillCommands(program3) {
50002
50486
  process.exit(2);
50003
50487
  }
50004
50488
  });
50005
- skill.command("uninstall").description("Remove the prim skill block from your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, or hermes (selects the default rules file)").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").action((opts) => {
50489
+ skill.command("uninstall").description("Remove the prim skill block from your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, cursor, or hermes").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").action((opts) => {
50006
50490
  process.exit(runUninstall(process.cwd(), opts));
50007
50491
  });
50008
- skill.command("status").description("Report whether the prim skill block is installed").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, or hermes (selects the default rules file)").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").option("--json", "Output as JSON").action((opts) => {
50492
+ skill.command("status").description("Report whether the prim skill block is installed").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, cursor, or hermes").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").option("--json", "Output as JSON").action((opts) => {
50009
50493
  process.exit(runStatus(process.cwd(), opts));
50010
50494
  });
50011
50495
  }
50012
50496
 
50013
50497
  // src/commands/statusline.ts
50014
- import { readFileSync as readFileSync20 } from "fs";
50498
+ import { readFileSync as readFileSync21 } from "fs";
50015
50499
  import { dirname as dirname17, resolve as resolve9 } from "path";
50016
50500
  import { fileURLToPath as fileURLToPath6 } from "url";
50017
50501
  var STATUSLINE_TIMEOUT_MS = 200;
@@ -50027,7 +50511,7 @@ function readPackageVersion() {
50027
50511
  ];
50028
50512
  for (const path9 of candidates) {
50029
50513
  try {
50030
- const pkg2 = JSON.parse(readFileSync20(path9, "utf-8"));
50514
+ const pkg2 = JSON.parse(readFileSync21(path9, "utf-8"));
50031
50515
  if (pkg2.version) {
50032
50516
  return pkg2.version;
50033
50517
  }
@@ -50044,9 +50528,8 @@ function debug(msg) {
50044
50528
  `);
50045
50529
  }
50046
50530
  }
50047
- async function renderStatusline() {
50531
+ async function renderStatusline(cwd = process.cwd()) {
50048
50532
  const version = readPackageVersion();
50049
- const cwd = process.cwd();
50050
50533
  let ingestion;
50051
50534
  const resolveIngestion = () => {
50052
50535
  ingestion ??= decisionIngestionStatus(cwd);
@@ -50094,6 +50577,11 @@ function planUninstallSteps(inRepository) {
50094
50577
  label: "Codex project integration",
50095
50578
  args: ["codex", "uninstall", "--scope", "project"]
50096
50579
  },
50580
+ {
50581
+ key: "cursor-project",
50582
+ label: "Cursor project integration",
50583
+ args: ["cursor", "uninstall", "--scope", "project"]
50584
+ },
50097
50585
  {
50098
50586
  key: "hooks-project",
50099
50587
  label: "project Git hooks",
@@ -50113,6 +50601,11 @@ function planUninstallSteps(inRepository) {
50113
50601
  label: "Codex user integration",
50114
50602
  args: ["codex", "uninstall", "--scope", "user"]
50115
50603
  },
50604
+ {
50605
+ key: "cursor-user",
50606
+ label: "Cursor user integration",
50607
+ args: ["cursor", "uninstall", "--scope", "user"]
50608
+ },
50116
50609
  { key: "hermes-user", label: "Hermes integration", args: ["hermes", "uninstall"] },
50117
50610
  {
50118
50611
  key: "hooks-user",
@@ -50131,7 +50624,7 @@ function uninstallStepSucceeded(step, result) {
50131
50624
  return false;
50132
50625
  }
50133
50626
  }
50134
- if (!step.key.startsWith("claude-") && !step.key.startsWith("codex-") && step.key !== "hermes-user") {
50627
+ if (!step.key.startsWith("claude-") && !step.key.startsWith("codex-") && !step.key.startsWith("cursor-") && step.key !== "hermes-user") {
50135
50628
  return true;
50136
50629
  }
50137
50630
  try {
@@ -50139,7 +50632,7 @@ function uninstallStepSucceeded(step, result) {
50139
50632
  if (step.key.startsWith("claude-")) {
50140
50633
  return parsed.gate === false && parsed.capture === false && parsed.feedback === false && parsed.statusline === false;
50141
50634
  }
50142
- return parsed.gate === false && parsed.capture === false;
50635
+ return parsed.gate === false && parsed.capture === false && (!step.key.startsWith("cursor-user") || parsed.footer === false);
50143
50636
  } catch {
50144
50637
  return false;
50145
50638
  }
@@ -50254,9 +50747,9 @@ function registerUninstallCommand(program3, dependencies = {}) {
50254
50747
  note(`uninstall \xB7 runtime removal incomplete (unknown state): ${detail}`);
50255
50748
  }
50256
50749
  }
50257
- const complete = failed.length === 0;
50750
+ const complete2 = failed.length === 0;
50258
50751
  const result = {
50259
- uninstalled: complete,
50752
+ uninstalled: complete2,
50260
50753
  projectScopeChecked: inRepository,
50261
50754
  steps: results,
50262
50755
  runtime,
@@ -50270,16 +50763,16 @@ function registerUninstallCommand(program3, dependencies = {}) {
50270
50763
  write(`${JSON.stringify(result, null, 2)}
50271
50764
  `);
50272
50765
  note(
50273
- complete ? "uninstall complete \xB7 credentials and pending journals preserved" : `uninstall incomplete \xB7 failed: ${failed.join(", ")}`
50766
+ complete2 ? "uninstall complete \xB7 credentials and pending journals preserved" : `uninstall incomplete \xB7 failed: ${failed.join(", ")}`
50274
50767
  );
50275
- exit(complete ? 0 : EXIT_INCOMPLETE2);
50768
+ exit(complete2 ? 0 : EXIT_INCOMPLETE2);
50276
50769
  });
50277
50770
  }
50278
50771
 
50279
50772
  // src/commands/welcome.ts
50280
50773
  var CMD_GUTTER = 38;
50281
50774
  var RECENT_LIMIT = 5;
50282
- var WELCOME_AGENTS = ["claude", "codex", "hermes"];
50775
+ var WELCOME_AGENTS = ["claude", "codex", "cursor", "hermes"];
50283
50776
  function resolveWelcomeAgent(agentFlag, env4) {
50284
50777
  if (agentFlag !== void 0 && WELCOME_AGENTS.includes(agentFlag)) {
50285
50778
  return agentFlag;
@@ -50287,6 +50780,9 @@ function resolveWelcomeAgent(agentFlag, env4) {
50287
50780
  if (agentFlag === void 0 && env4.HERMES_INTERACTIVE) {
50288
50781
  return "hermes";
50289
50782
  }
50783
+ if (agentFlag === void 0 && env4.CURSOR_AGENT) {
50784
+ return "cursor";
50785
+ }
50290
50786
  return void 0;
50291
50787
  }
50292
50788
  var CAPTURE_LINES = {
@@ -50295,6 +50791,7 @@ var CAPTURE_LINES = {
50295
50791
  "Capture starts once you trust the prim hooks \u2014 run /hooks in Codex;",
50296
50792
  "until then nothing is recorded."
50297
50793
  ],
50794
+ cursor: ["Capture is automatic in trusted Cursor workspaces; restart Cursor CLI for the footer."],
50298
50795
  hermes: [
50299
50796
  "Capture starts once you approve the prim hooks when Hermes prompts;",
50300
50797
  "until then nothing is recorded."
@@ -50310,6 +50807,7 @@ var PASSIVE_LINES = {
50310
50807
  "Once you trust the prim hooks (/hooks in Codex), Primitive captures",
50311
50808
  "decisions passively while you work."
50312
50809
  ],
50810
+ cursor: ["In trusted Cursor workspaces, Primitive captures decisions passively while you work."],
50313
50811
  hermes: [
50314
50812
  "Once you approve the prim hooks, Primitive captures decisions",
50315
50813
  "passively while you work."
@@ -50322,6 +50820,7 @@ var PASSIVE_LINES = {
50322
50820
  var GUIDANCE_PASSIVE = {
50323
50821
  claude: "Otherwise, Primitive passively captures decisions in the background while you work.",
50324
50822
  codex: "Otherwise, once you trust the prim hooks (run /hooks in Codex), Primitive passively captures decisions in the background while you work.",
50823
+ cursor: "Otherwise, Primitive passively captures decisions in trusted Cursor workspaces while you work.",
50325
50824
  hermes: "Otherwise, once you approve the prim hooks when Hermes prompts, Primitive passively captures decisions in the background while you work.",
50326
50825
  generic: "Otherwise, once your agent's prim hooks are active, Primitive passively captures decisions in the background while you work."
50327
50826
  };
@@ -50416,10 +50915,7 @@ function welcomeJson(state, agent) {
50416
50915
  return { welcomed: true, org: "unknown" };
50417
50916
  }
50418
50917
  function registerWelcomeCommand(program3, deps = { getClient }) {
50419
- program3.command("welcome").description("Print a brief orientation to Primitive's decision graph").option(
50420
- "--agent <agent>",
50421
- "claude, codex, or hermes \u2014 tailors the capture guidance (Hermes auto-detected)"
50422
- ).action(async (options) => {
50918
+ program3.command("welcome").description("Print a brief orientation to Primitive's decision graph").option("--agent <agent>", "claude, codex, cursor, or hermes \u2014 tailors the capture guidance").action(async (options) => {
50423
50919
  const agent = resolveWelcomeAgent(options.agent, process.env);
50424
50920
  const result = await fetchRecent({ limit: RECENT_LIMIT }, deps);
50425
50921
  const state = welcomeStateFromRecent(result);
@@ -50447,7 +50943,7 @@ function runStartupBackgroundWork(argv, env4, work) {
50447
50943
 
50448
50944
  // src/index.ts
50449
50945
  var __dirname6 = dirname18(fileURLToPath7(import.meta.url));
50450
- var pkg = JSON.parse(readFileSync21(resolve10(__dirname6, "../package.json"), "utf-8"));
50946
+ var pkg = JSON.parse(readFileSync22(resolve10(__dirname6, "../package.json"), "utf-8"));
50451
50947
  runStartupBackgroundWork(process.argv.slice(2), process.env, {
50452
50948
  notify: () => updateNotifier({ pkg }).notify(),
50453
50949
  flush: () => flushIfNeeded()
@@ -50466,6 +50962,7 @@ registerSessionCommands(program2);
50466
50962
  registerDecisionsCommands(program2);
50467
50963
  registerClaudeCommands(program2);
50468
50964
  registerCodexCommands(program2);
50965
+ registerCursorCommands(program2);
50469
50966
  registerHermesCommands(program2);
50470
50967
  registerDaemonCommands(program2);
50471
50968
  registerGithubCommands(program2);