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

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-LMRYZL3D.js → chunk-5AFRMOPX.js} +1 -1
  4. package/dist/{chunk-RO3F6JYV.js → chunk-5GYQ4J3D.js} +2 -2
  5. package/dist/{chunk-3EEFL6NJ.js → chunk-67VNLLBN.js} +261 -1
  6. package/dist/{chunk-LEMX3IOG.js → chunk-BTNNEH2W.js} +1 -1
  7. package/dist/chunk-EWZMDD44.js +1474 -0
  8. package/dist/{chunk-YWO7O6QG.js → chunk-FBAYCS3X.js} +2 -2
  9. package/dist/{chunk-R26A7TWY.js → chunk-FKXFUUWJ.js} +1 -1
  10. package/dist/{chunk-C7T7B45R.js → chunk-FOLKHXLJ.js} +150 -21
  11. package/dist/chunk-H4UNYFUC.js +196 -0
  12. package/dist/chunk-HU4PW6I6.js +264 -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-MAZWKJGL.js → chunk-M6RIJVRE.js} +42 -232
  16. package/dist/{chunk-2JRX7ZR4.js → chunk-NAHHFSLH.js} +16 -5
  17. package/dist/{chunk-FI3LIRCB.js → chunk-OAAP2MY6.js} +2 -2
  18. package/dist/{chunk-Z7YPFWAZ.js → chunk-PCVGBE5B.js} +10 -268
  19. package/dist/{chunk-UZPBB7V4.js → chunk-VW3FDYRT.js} +60 -48
  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 +20 -20
  23. package/dist/hook-runtime/daemon/server.js +20 -20
  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 +651 -132
  27. package/dist/hook-runtime/hooks/pre-tool-use.js +644 -96
  28. package/dist/hook-runtime/hooks/prim-hook.js +612 -96
  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 +735 -264
  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 +558 -1436
  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; ',
@@ -35805,7 +35805,7 @@ function performPermissionInstall(scope) {
35805
35805
  };
35806
35806
  }
35807
35807
  function performStatus() {
35808
- const statusFor = (path9) => {
35808
+ const statusFor2 = (path9) => {
35809
35809
  const settings = readSettings(path9);
35810
35810
  return {
35811
35811
  path: path9,
@@ -35818,7 +35818,7 @@ function performStatus() {
35818
35818
  statuslineState: statuslineState(settings)
35819
35819
  };
35820
35820
  };
35821
- return { user: statusFor(USER_SCOPE_PATH), project: statusFor(projectScopePath()) };
35821
+ return { user: statusFor2(USER_SCOPE_PATH), project: statusFor2(projectScopePath()) };
35822
35822
  }
35823
35823
  function resolveScope(input) {
35824
35824
  if (input === void 0 || input === "project") {
@@ -36017,7 +36017,7 @@ function performUninstall2(scope) {
36017
36017
  return resultFor(scope, path9, after, changed);
36018
36018
  }
36019
36019
  function performStatus2() {
36020
- const statusFor = (path9) => {
36020
+ const statusFor2 = (path9) => {
36021
36021
  const settings = readSettings(path9);
36022
36022
  return {
36023
36023
  path: path9,
@@ -36027,7 +36027,7 @@ function performStatus2() {
36027
36027
  complete: hasCompleteHookRegistration2(settings)
36028
36028
  };
36029
36029
  };
36030
- return { user: statusFor(USER_SCOPE_PATH2), project: statusFor(projectScopePath2()) };
36030
+ return { user: statusFor2(USER_SCOPE_PATH2), project: statusFor2(projectScopePath2()) };
36031
36031
  }
36032
36032
  function resolveScope2(input) {
36033
36033
  if (input === void 0 || input === "project") {
@@ -36079,14 +36079,302 @@ ${line("project", result.project)}`);
36079
36079
  });
36080
36080
  }
36081
36081
 
36082
+ // src/commands/cursor-install.ts
36083
+ import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
36084
+ import { homedir as homedir7 } from "os";
36085
+ import { isAbsolute as isAbsolute6, join as join13 } from "path";
36086
+ var CAPTURE_BIN3 = "prim-hook";
36087
+ var GATE_BIN3 = "prim-pre-tool-use";
36088
+ var POST_TOOL_BIN = "prim-post-tool-use";
36089
+ var SESSION_START_BIN3 = "prim-session-start";
36090
+ var SESSION_END_BIN2 = "prim-session-end";
36091
+ var STATUSLINE_BIN2 = "prim-statusline";
36092
+ var PRIM_BINS3 = [CAPTURE_BIN3, GATE_BIN3, POST_TOOL_BIN, SESSION_START_BIN3, SESSION_END_BIN2];
36093
+ var CURSOR_EVENTS = [
36094
+ "sessionStart",
36095
+ "beforeSubmitPrompt",
36096
+ "preToolUse",
36097
+ "postToolUse",
36098
+ "postToolUseFailure",
36099
+ "afterAgentResponse",
36100
+ "subagentStop",
36101
+ "stop",
36102
+ "sessionEnd"
36103
+ ];
36104
+ var REGISTRATIONS2 = [
36105
+ ...CURSOR_EVENTS.map((event) => ({ event, bin: CAPTURE_BIN3 })),
36106
+ { event: "preToolUse", bin: GATE_BIN3, matcher: "Write|Delete|Shell", timeout: 10 },
36107
+ { event: "postToolUse", bin: POST_TOOL_BIN },
36108
+ { event: "postToolUseFailure", bin: POST_TOOL_BIN },
36109
+ { event: "sessionStart", bin: SESSION_START_BIN3 },
36110
+ { event: "sessionEnd", bin: SESSION_END_BIN2 }
36111
+ ];
36112
+ function cursorConfigDirectory(env4 = process.env, home = homedir7(), platform2 = process.platform) {
36113
+ const explicit = env4.CURSOR_CONFIG_DIR?.trim();
36114
+ if (explicit && isAbsolute6(explicit)) return explicit;
36115
+ const xdg = env4.XDG_CONFIG_HOME?.trim();
36116
+ if (platform2 !== "darwin" && xdg && isAbsolute6(xdg)) return join13(xdg, "cursor");
36117
+ return join13(home, ".cursor");
36118
+ }
36119
+ function cursorHooksPath(scope, root = projectRoot()) {
36120
+ return scope === "user" ? join13(cursorConfigDirectory(), "hooks.json") : join13(root, ".cursor", "hooks.json");
36121
+ }
36122
+ function cursorCliConfigPath() {
36123
+ return join13(cursorConfigDirectory(), "cli-config.json");
36124
+ }
36125
+ function plainObject(value) {
36126
+ return typeof value === "object" && value !== null && !Array.isArray(value);
36127
+ }
36128
+ function readCursorHooks(path9) {
36129
+ if (!existsSync10(path9)) return {};
36130
+ let parsed;
36131
+ try {
36132
+ parsed = JSON.parse(readFileSync11(path9, "utf8"));
36133
+ } catch {
36134
+ throw new Error(`invalid Cursor hooks JSON at ${path9}`);
36135
+ }
36136
+ if (!plainObject(parsed)) throw new Error(`Cursor hooks config must be an object: ${path9}`);
36137
+ if (parsed.version !== void 0 && parsed.version !== 1) {
36138
+ throw new Error(`unsupported Cursor hooks version at ${path9} (expected version 1)`);
36139
+ }
36140
+ if (parsed.hooks !== void 0) {
36141
+ if (!plainObject(parsed.hooks)) throw new Error(`Cursor hooks must be an object: ${path9}`);
36142
+ for (const [event, entries] of Object.entries(parsed.hooks)) {
36143
+ if (!Array.isArray(entries) || !entries.every(plainObject)) {
36144
+ throw new Error(`Cursor hook list must contain objects: ${event} in ${path9}`);
36145
+ }
36146
+ }
36147
+ }
36148
+ return parsed;
36149
+ }
36150
+ function readObject(path9) {
36151
+ if (!existsSync10(path9)) return {};
36152
+ let parsed;
36153
+ try {
36154
+ parsed = JSON.parse(readFileSync11(path9, "utf8"));
36155
+ } catch {
36156
+ throw new Error(`invalid Cursor CLI config JSON at ${path9}`);
36157
+ }
36158
+ if (!plainObject(parsed)) throw new Error(`Cursor CLI config must be an object: ${path9}`);
36159
+ return parsed;
36160
+ }
36161
+ function writeJson(path9, value) {
36162
+ atomicWriteFile(path9, `${JSON.stringify(value, null, 2)}
36163
+ `, { ensureParent: true });
36164
+ }
36165
+ function commandFor(registration, scope) {
36166
+ return stableHookCommand(
36167
+ registration.bin,
36168
+ `--agent cursor --event ${registration.event} --scope ${scope}`
36169
+ );
36170
+ }
36171
+ var OWNED_COMMANDS = new Set(
36172
+ ["project", "user"].flatMap(
36173
+ (scope) => REGISTRATIONS2.map((registration) => commandFor(registration, scope))
36174
+ )
36175
+ );
36176
+ function jsoncUnsafeCommand(command) {
36177
+ return command.replace('case "$1" in [/]* ', 'case "$1" in /*').replace("*[/][/]*", "*//*").replace("*[/].[/]*", "*/./*").replace("*[/]..[/]*", "*/../*").replace("*[/].", "*/.").replace("*[/]..", "*/..").replace("?*[/]", "?*/");
36178
+ }
36179
+ var JSONC_UNSAFE_OWNED_COMMANDS = new Set([...OWNED_COMMANDS].map(jsoncUnsafeCommand));
36180
+ function isOwnedCursorHookCommand(command) {
36181
+ return typeof command === "string" && (OWNED_COMMANDS.has(command) || JSONC_UNSAFE_OWNED_COMMANDS.has(command));
36182
+ }
36183
+ function hookFor(registration, scope) {
36184
+ return {
36185
+ command: commandFor(registration, scope),
36186
+ ...registration.matcher ? { matcher: registration.matcher } : {},
36187
+ ...registration.timeout ? { timeout: registration.timeout } : {}
36188
+ };
36189
+ }
36190
+ function exactHook(entry, registration, scope) {
36191
+ return JSON.stringify(entry) === JSON.stringify(hookFor(registration, scope));
36192
+ }
36193
+ function applyCursorInstall(settings, scope) {
36194
+ const hooks = {};
36195
+ for (const [event, entries] of Object.entries(settings.hooks ?? {})) {
36196
+ hooks[event] = entries.filter((entry) => !isOwnedCursorHookCommand(entry.command));
36197
+ }
36198
+ for (const registration of REGISTRATIONS2) {
36199
+ const entries = hooks[registration.event] ?? [];
36200
+ entries.push(hookFor(registration, scope));
36201
+ hooks[registration.event] = entries;
36202
+ }
36203
+ return { ...settings, version: 1, hooks };
36204
+ }
36205
+ function applyCursorUninstall(settings) {
36206
+ const hooks = {};
36207
+ for (const [event, entries] of Object.entries(settings.hooks ?? {})) {
36208
+ const retained = entries.filter((entry) => !isOwnedCursorHookCommand(entry.command));
36209
+ if (retained.length > 0) hooks[event] = retained;
36210
+ }
36211
+ return { ...settings, hooks };
36212
+ }
36213
+ function ownedEntries(settings) {
36214
+ return Object.entries(settings.hooks ?? {}).flatMap(
36215
+ ([event, entries]) => entries.filter((entry) => isOwnedCursorHookCommand(entry.command)).map((entry) => ({ event, entry }))
36216
+ );
36217
+ }
36218
+ function hasExactCursorHandler(settings, event, bin, scope) {
36219
+ const registration = REGISTRATIONS2.find(
36220
+ (candidate) => candidate.event === event && candidate.bin === bin
36221
+ );
36222
+ return registration ? (settings.hooks?.[event] ?? []).some((entry) => exactHook(entry, registration, scope)) : false;
36223
+ }
36224
+ function complete(settings, scope) {
36225
+ const owned = ownedEntries(settings);
36226
+ return owned.length === REGISTRATIONS2.length && REGISTRATIONS2.every(
36227
+ (registration) => owned.filter(
36228
+ ({ event, entry }) => event === registration.event && exactHook(entry, registration, scope)
36229
+ ).length === 1
36230
+ );
36231
+ }
36232
+ function captureInstalled3(settings, scope) {
36233
+ return CURSOR_EVENTS.every((event) => hasExactCursorHandler(settings, event, CAPTURE_BIN3, scope));
36234
+ }
36235
+ function gateInstalled(settings, scope) {
36236
+ return hasExactCursorHandler(settings, "preToolUse", GATE_BIN3, scope);
36237
+ }
36238
+ var FOOTER = {
36239
+ type: "command",
36240
+ command: stableHookCommand(STATUSLINE_BIN2),
36241
+ updateIntervalMs: 1e3,
36242
+ timeoutMs: 2e3
36243
+ };
36244
+ var JSONC_UNSAFE_FOOTER = {
36245
+ ...FOOTER,
36246
+ command: jsoncUnsafeCommand(FOOTER.command)
36247
+ };
36248
+ function exactFooter(value) {
36249
+ return plainObject(value) && JSON.stringify(value) === JSON.stringify(FOOTER);
36250
+ }
36251
+ function jsoncUnsafeFooter(value) {
36252
+ return plainObject(value) && JSON.stringify(value) === JSON.stringify(JSONC_UNSAFE_FOOTER);
36253
+ }
36254
+ function applyCursorFooterInstall(config) {
36255
+ if (config.statusLine === void 0)
36256
+ return { config: { ...config, statusLine: FOOTER }, installed: true, preservedCustom: false };
36257
+ if (exactFooter(config.statusLine)) return { config, installed: true, preservedCustom: false };
36258
+ if (jsoncUnsafeFooter(config.statusLine)) {
36259
+ return { config: { ...config, statusLine: FOOTER }, installed: true, preservedCustom: false };
36260
+ }
36261
+ return { config, installed: false, preservedCustom: true };
36262
+ }
36263
+ function applyCursorFooterUninstall(config) {
36264
+ if (!exactFooter(config.statusLine) && !jsoncUnsafeFooter(config.statusLine)) {
36265
+ return { config, removed: false };
36266
+ }
36267
+ return {
36268
+ config: Object.fromEntries(Object.entries(config).filter(([key]) => key !== "statusLine")),
36269
+ removed: true
36270
+ };
36271
+ }
36272
+ function statusFor(scope, path9 = cursorHooksPath(scope)) {
36273
+ const settings = readCursorHooks(path9);
36274
+ const base = {
36275
+ path: path9,
36276
+ present: ownedEntries(settings).length > 0,
36277
+ gate: gateInstalled(settings, scope),
36278
+ capture: captureInstalled3(settings, scope),
36279
+ complete: complete(settings, scope)
36280
+ };
36281
+ if (scope === "user") {
36282
+ const cliConfig = readObject(cursorCliConfigPath());
36283
+ base.footer = exactFooter(cliConfig.statusLine);
36284
+ base.footerPreservedCustom = cliConfig.statusLine !== void 0 && !base.footer;
36285
+ }
36286
+ return base;
36287
+ }
36288
+ function performInstall3(scope, _force = false) {
36289
+ stageHookRuntime();
36290
+ const path9 = cursorHooksPath(scope);
36291
+ const before = readCursorHooks(path9);
36292
+ const after = applyCursorInstall(before, scope);
36293
+ let changed = JSON.stringify(before) !== JSON.stringify(after);
36294
+ if (changed) writeJson(path9, after);
36295
+ let restartRequired = false;
36296
+ if (scope === "user") {
36297
+ const cliPath = cursorCliConfigPath();
36298
+ const cliBefore = readObject(cliPath);
36299
+ const footer = applyCursorFooterInstall(cliBefore);
36300
+ if (JSON.stringify(cliBefore) !== JSON.stringify(footer.config)) {
36301
+ writeJson(cliPath, footer.config);
36302
+ changed = true;
36303
+ restartRequired = true;
36304
+ }
36305
+ }
36306
+ return { scope, ...statusFor(scope, path9), changed, restartRequired };
36307
+ }
36308
+ function performUninstall3(scope) {
36309
+ const path9 = cursorHooksPath(scope);
36310
+ const before = readCursorHooks(path9);
36311
+ const after = applyCursorUninstall(before);
36312
+ let changed = JSON.stringify(before) !== JSON.stringify(after);
36313
+ if (changed) writeJson(path9, after);
36314
+ let restartRequired = false;
36315
+ if (scope === "user") {
36316
+ const cliPath = cursorCliConfigPath();
36317
+ const cliBefore = readObject(cliPath);
36318
+ const footer = applyCursorFooterUninstall(cliBefore);
36319
+ if (footer.removed) {
36320
+ writeJson(cliPath, footer.config);
36321
+ changed = true;
36322
+ restartRequired = true;
36323
+ }
36324
+ }
36325
+ return { scope, ...statusFor(scope, path9), changed, restartRequired };
36326
+ }
36327
+ function performStatus3() {
36328
+ return { user: statusFor("user"), project: statusFor("project") };
36329
+ }
36330
+ function inspectHookRuntimeResolutions3() {
36331
+ const commands = ["user", "project"].flatMap(
36332
+ (scope) => ownedEntries(readCursorHooks(cursorHooksPath(scope))).map(({ entry }) => entry.command)
36333
+ );
36334
+ return hookCommandResolutions(commands, PRIM_BINS3);
36335
+ }
36336
+ function resolveScope3(input) {
36337
+ if (input === void 0 || input === "project") return "project";
36338
+ if (input === "user") return "user";
36339
+ throw new Error(`unknown --scope "${input}" (expected: user or project)`);
36340
+ }
36341
+ function registerCursorCommands(program3) {
36342
+ const cursor = program3.command("cursor").description("Manage the native Cursor integration (capture, gate, ingest, presence)");
36343
+ 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) => {
36344
+ const result = performInstall3(resolveScope3(opts.scope), opts.force);
36345
+ console.error(
36346
+ result.changed ? `[prim] Cursor integration installed (${result.scope} scope) at ${result.path}` : `[prim] Cursor integration already present at ${result.path}`
36347
+ );
36348
+ if (result.restartRequired) console.error("[prim] restart Cursor CLI to load the footer");
36349
+ console.log(JSON.stringify(result, null, 2));
36350
+ });
36351
+ cursor.command("uninstall").description("Remove only Primitive-owned Cursor hooks and footer").option("--scope <scope>", "project (default) or user").action((opts) => {
36352
+ const result = performUninstall3(resolveScope3(opts.scope));
36353
+ console.error(
36354
+ result.changed ? `[prim] Cursor integration removed (${result.scope} scope)` : `[prim] no Primitive-owned Cursor integration found (${result.scope} scope)`
36355
+ );
36356
+ if (result.restartRequired) console.error("[prim] restart Cursor CLI to remove the footer");
36357
+ console.log(JSON.stringify(result, null, 2));
36358
+ });
36359
+ cursor.command("status").description("Report native Cursor hook and footer status").action(() => {
36360
+ const result = performStatus3();
36361
+ const mark = (value) => value ? "\u2713" : "\u2717";
36362
+ console.error(
36363
+ `[prim] user: gate ${mark(result.user.gate)} \xB7 capture ${mark(result.user.capture)} \xB7 footer ${mark(result.user.footer)} (${result.user.path})
36364
+ [prim] project: gate ${mark(result.project.gate)} \xB7 capture ${mark(result.project.capture)} (${result.project.path})`
36365
+ );
36366
+ console.log(JSON.stringify(result, null, 2));
36367
+ });
36368
+ }
36369
+
36082
36370
  // src/commands/daemon.ts
36083
36371
  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";
36372
+ import { closeSync as closeSync3, existsSync as existsSync12, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync13, unlinkSync as unlinkSync3 } from "fs";
36373
+ import { join as join16 } from "path";
36086
36374
 
36087
36375
  // src/daemon/latest-bootstrap.ts
36088
36376
  import { spawn as spawn2 } from "child_process";
36089
- import { join as join13 } from "path";
36377
+ import { join as join14 } from "path";
36090
36378
  var LATEST_BOOTSTRAP_TIMEOUT_MS = 45e3;
36091
36379
  var LATEST_BOOTSTRAP_LOCK_NAME = "daemon-latest.lock";
36092
36380
  async function runPinnedEnsure(options) {
@@ -36127,7 +36415,7 @@ async function runPinnedEnsure(options) {
36127
36415
  });
36128
36416
  }
36129
36417
  async function runLatestDaemonBootstrap(ensureCurrent, options = {}) {
36130
- const lockPath = options.lockPath ?? join13(
36418
+ const lockPath = options.lockPath ?? join14(
36131
36419
  primConfigDirectory({ env: options.env, homeDir: options.homeDir }),
36132
36420
  LATEST_BOOTSTRAP_LOCK_NAME
36133
36421
  );
@@ -36157,11 +36445,11 @@ import {
36157
36445
  accessSync as accessSync2,
36158
36446
  chmodSync as chmodSync4,
36159
36447
  copyFileSync as copyFileSync2,
36160
- existsSync as existsSync10,
36448
+ existsSync as existsSync11,
36161
36449
  lstatSync as lstatSync5,
36162
36450
  mkdirSync as mkdirSync8,
36163
36451
  mkdtempSync as mkdtempSync2,
36164
- readFileSync as readFileSync11,
36452
+ readFileSync as readFileSync12,
36165
36453
  readdirSync as readdirSync3,
36166
36454
  readlinkSync,
36167
36455
  realpathSync as realpathSync3,
@@ -36170,8 +36458,8 @@ import {
36170
36458
  symlinkSync,
36171
36459
  writeFileSync as writeFileSync7
36172
36460
  } 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";
36461
+ import { homedir as homedir8 } from "os";
36462
+ import { basename as basename3, dirname as dirname10, isAbsolute as isAbsolute7, join as join15, resolve as resolve6 } from "path";
36175
36463
 
36176
36464
  // src/daemon/env-binding.ts
36177
36465
  function normalizeApiUrl(url) {
@@ -36210,31 +36498,31 @@ var LaunchctlError = class extends Error {
36210
36498
  }
36211
36499
  };
36212
36500
  function xdgDataHome(options) {
36213
- const home = options.homeDir ?? homedir7();
36501
+ const home = options.homeDir ?? homedir8();
36214
36502
  const configured = (options.env ?? process.env).XDG_DATA_HOME;
36215
- return configured && isAbsolute6(configured) ? configured : join14(home, ".local", "share");
36503
+ return configured && isAbsolute7(configured) ? configured : join15(home, ".local", "share");
36216
36504
  }
36217
36505
  function runtimePaths(options = {}) {
36218
- const dataDir = join14(xdgDataHome(options), "prim");
36219
- const runtimeDir = join14(dataDir, "runtime");
36220
- const currentLink = join14(runtimeDir, "current");
36506
+ const dataDir = join15(xdgDataHome(options), "prim");
36507
+ const runtimeDir = join15(dataDir, "runtime");
36508
+ const currentLink = join15(runtimeDir, "current");
36221
36509
  return {
36222
36510
  dataDir,
36223
36511
  runtimeDir,
36224
- releasesDir: join14(runtimeDir, "releases"),
36512
+ releasesDir: join15(runtimeDir, "releases"),
36225
36513
  currentLink,
36226
- statuslineLauncher: join14(runtimeDir, "prim-statusline"),
36227
- disabledMarker: join14(dataDir, "daemon.disabled"),
36228
- lifecycleLockDir: join14(dataDir, "daemon.lifecycle.lock")
36514
+ statuslineLauncher: join15(runtimeDir, "prim-statusline"),
36515
+ disabledMarker: join15(dataDir, "daemon.disabled"),
36516
+ lifecycleLockDir: join15(dataDir, "daemon.lifecycle.lock")
36229
36517
  };
36230
36518
  }
36231
36519
  function daemonControlPaths(options = {}) {
36232
36520
  const configDir = primConfigDirectory(options);
36233
36521
  const legacy = runtimePaths(options);
36234
36522
  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"),
36523
+ launcher: join15(configDir, `prim-daemon-launcher-v${LAUNCHER_SCHEMA_VERSION}`),
36524
+ disabledMarker: join15(configDir, "daemon.disabled"),
36525
+ lifecycleLockDir: join15(configDir, "daemon.lifecycle.lock"),
36238
36526
  legacyDisabledMarker: legacy.disabledMarker,
36239
36527
  legacyLifecycleLockDir: legacy.lifecycleLockDir
36240
36528
  };
@@ -36242,10 +36530,10 @@ function daemonControlPaths(options = {}) {
36242
36530
  function findPackageVersion(entryFile) {
36243
36531
  let dir = dirname10(resolve6(entryFile));
36244
36532
  for (let depth = 0; depth < 6; depth++) {
36245
- const packagePath = join14(dir, "package.json");
36246
- if (existsSync10(packagePath)) {
36533
+ const packagePath = join15(dir, "package.json");
36534
+ if (existsSync11(packagePath)) {
36247
36535
  try {
36248
- const manifest = JSON.parse(readFileSync11(packagePath, "utf8"));
36536
+ const manifest = JSON.parse(readFileSync12(packagePath, "utf8"));
36249
36537
  if (manifest.name === "@primitive.ai/prim" && manifest.version) {
36250
36538
  return manifest.version;
36251
36539
  }
@@ -36260,7 +36548,7 @@ function findPackageVersion(entryFile) {
36260
36548
  }
36261
36549
  function readRuntimeManifest(path9) {
36262
36550
  try {
36263
- const parsed = JSON.parse(readFileSync11(path9, "utf8"));
36551
+ const parsed = JSON.parse(readFileSync12(path9, "utf8"));
36264
36552
  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
36553
  return null;
36266
36554
  }
@@ -36276,10 +36564,10 @@ function exactKeys2(value, expected) {
36276
36564
  return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
36277
36565
  }
36278
36566
  function readOwnedRuntimeManifest(releaseDir) {
36279
- const manifestPath = join14(releaseDir, "manifest.json");
36280
- const daemonPath = join14(releaseDir, "prim-daemon-server");
36567
+ const manifestPath = join15(releaseDir, "manifest.json");
36568
+ const daemonPath = join15(releaseDir, "prim-daemon-server");
36281
36569
  try {
36282
- const raw = readFileSync11(manifestPath, "utf8");
36570
+ const raw = readFileSync12(manifestPath, "utf8");
36283
36571
  const parsed = JSON.parse(raw);
36284
36572
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
36285
36573
  if (!exactKeys2(parsed, [
@@ -36293,7 +36581,7 @@ function readOwnedRuntimeManifest(releaseDir) {
36293
36581
  return null;
36294
36582
  }
36295
36583
  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)}
36584
+ 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
36585
  ` || !lstatSync5(daemonPath).isFile() || sha256File(daemonPath) !== manifest.daemonSha256) {
36298
36586
  return null;
36299
36587
  }
@@ -36314,7 +36602,7 @@ function sameRuntime(current, desired, daemonPath) {
36314
36602
  }
36315
36603
  }
36316
36604
  function sha256File(path9) {
36317
- return createHash8("sha256").update(readFileSync11(path9)).digest("hex");
36605
+ return createHash8("sha256").update(readFileSync12(path9)).digest("hex");
36318
36606
  }
36319
36607
  function atomicSymlink(target, linkPath) {
36320
36608
  const tempLink = `${linkPath}.tmp-${process.pid}-${createHash8("sha256").update(`${target}\0${Date.now()}\0${Math.random()}`).digest("hex").slice(0, 12)}`;
@@ -36329,7 +36617,7 @@ function atomicSymlink(target, linkPath) {
36329
36617
  function stageRuntime(options = {}) {
36330
36618
  const paths = runtimePaths(options);
36331
36619
  const daemonSource = options.daemonSource ?? binFile("prim-daemon-server");
36332
- if (!daemonSource || !existsSync10(daemonSource)) {
36620
+ if (!daemonSource || !existsSync11(daemonSource)) {
36333
36621
  throw new Error("cannot stage runtime: prim-daemon-server bundle is unavailable");
36334
36622
  }
36335
36623
  const nodePath = resolve6(options.nodePath ?? process.execPath);
@@ -36347,8 +36635,8 @@ function stageRuntime(options = {}) {
36347
36635
  currentRelease = realpathSync3(paths.currentLink);
36348
36636
  } catch {
36349
36637
  }
36350
- const current = currentRelease ? readRuntimeManifest(join14(currentRelease, "manifest.json")) : null;
36351
- const currentDaemon = currentRelease ? join14(currentRelease, desired.daemonFile) : "";
36638
+ const current = currentRelease ? readRuntimeManifest(join15(currentRelease, "manifest.json")) : null;
36639
+ const currentDaemon = currentRelease ? join15(currentRelease, desired.daemonFile) : "";
36352
36640
  if (currentRelease && sameRuntime(current, desired, currentDaemon)) {
36353
36641
  const manifest = current;
36354
36642
  atomicWrite3(
@@ -36366,17 +36654,17 @@ function stageRuntime(options = {}) {
36366
36654
  mkdirSync8(paths.releasesDir, { recursive: true, mode: RUNTIME_DIR_MODE });
36367
36655
  chmodSync4(paths.runtimeDir, RUNTIME_DIR_MODE);
36368
36656
  chmodSync4(paths.releasesDir, RUNTIME_DIR_MODE);
36369
- const stagingDir = mkdtempSync2(join14(paths.releasesDir, ".stage-"));
36657
+ const stagingDir = mkdtempSync2(join15(paths.releasesDir, ".stage-"));
36370
36658
  chmodSync4(stagingDir, RUNTIME_DIR_MODE);
36371
36659
  let releaseDir;
36372
36660
  try {
36373
- const daemonTarget = join14(stagingDir, desired.daemonFile);
36661
+ const daemonTarget = join15(stagingDir, desired.daemonFile);
36374
36662
  copyFileSync2(daemonSource, daemonTarget);
36375
36663
  chmodSync4(daemonTarget, RUNTIME_FILE_MODE);
36376
36664
  if (sha256File(daemonTarget) !== desired.daemonSha256) {
36377
36665
  throw new Error("cannot stage runtime: daemon bundle changed while it was copied");
36378
36666
  }
36379
- const manifestTarget = join14(stagingDir, "manifest.json");
36667
+ const manifestTarget = join15(stagingDir, "manifest.json");
36380
36668
  writeFileSync7(manifestTarget, `${JSON.stringify(desired, null, 2)}
36381
36669
  `, {
36382
36670
  encoding: "utf8",
@@ -36384,10 +36672,10 @@ function stageRuntime(options = {}) {
36384
36672
  flag: "wx"
36385
36673
  });
36386
36674
  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);
36675
+ releaseDir = join15(paths.releasesDir, releaseName);
36388
36676
  renameSync4(stagingDir, releaseDir);
36389
36677
  releaseDir = realpathSync3(releaseDir);
36390
- atomicSymlink(join14("releases", releaseName), paths.currentLink);
36678
+ atomicSymlink(join15("releases", releaseName), paths.currentLink);
36391
36679
  atomicWrite3(
36392
36680
  paths.statuslineLauncher,
36393
36681
  statuslineLauncherContent(desired.version, options),
@@ -36401,14 +36689,14 @@ function stageRuntime(options = {}) {
36401
36689
  changed: true,
36402
36690
  manifest: desired,
36403
36691
  paths,
36404
- daemonPath: join14(releaseDir, desired.daemonFile)
36692
+ daemonPath: join15(releaseDir, desired.daemonFile)
36405
36693
  };
36406
36694
  }
36407
36695
  function shellQuote2(value) {
36408
36696
  return `'${value.replaceAll("'", `'"'"'`)}'`;
36409
36697
  }
36410
36698
  function statuslineLauncherContent(version, options = {}) {
36411
- const socketPath = join14(primConfigDirectory(options), "sock");
36699
+ const socketPath = join15(primConfigDirectory(options), "sock");
36412
36700
  const fallback = `primitive ${version} (daemon: down)`;
36413
36701
  return `#!/bin/sh
36414
36702
  response=$(
@@ -36441,7 +36729,7 @@ function lstatIfPresent3(path9) {
36441
36729
  function assertExactFile(path9, expected, label) {
36442
36730
  if (!lstatIfPresent3(path9)) return;
36443
36731
  assertRegularFile(path9, label);
36444
- if (readFileSync11(path9, "utf8") !== expected) {
36732
+ if (readFileSync12(path9, "utf8") !== expected) {
36445
36733
  throw new Error(`refusing to remove unrecognized ${label} at ${path9}`);
36446
36734
  }
36447
36735
  }
@@ -36450,12 +36738,12 @@ function assertOwnedDaemonRuntime(options) {
36450
36738
  const control = daemonControlPaths(options);
36451
36739
  const configDir = primConfigDirectory(options);
36452
36740
  const service = process.platform === "darwin" ? launchdPaths(options) : void 0;
36453
- const logPath = service?.logPath ?? join14(configDir, "daemon.log");
36741
+ const logPath = service?.logPath ?? join15(configDir, "daemon.log");
36454
36742
  for (const activeArtifact of [
36455
- join14(configDir, "daemon.pid"),
36456
- join14(configDir, "sock"),
36457
- join14(configDir, "daemon.lock"),
36458
- join14(configDir, "client-instance.lock")
36743
+ join15(configDir, "daemon.pid"),
36744
+ join15(configDir, "sock"),
36745
+ join15(configDir, "daemon.lock"),
36746
+ join15(configDir, "client-instance.lock")
36459
36747
  ]) {
36460
36748
  if (lstatIfPresent3(activeArtifact)) {
36461
36749
  throw new Error(`refusing runtime removal while daemon state remains at ${activeArtifact}`);
@@ -36476,17 +36764,17 @@ function assertOwnedDaemonRuntime(options) {
36476
36764
  );
36477
36765
  }
36478
36766
  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");
36767
+ assertRegularFile(join15(configDir, "daemon-health.json"), "daemon health snapshot");
36768
+ assertRegularFile(join15(configDir, "client_instance_id"), "daemon client instance id");
36481
36769
  if (service && lstatIfPresent3(service.plistPath)) {
36482
36770
  assertRegularFile(service.plistPath, "launchd property list");
36483
36771
  const expected = generateLaunchAgentPlist({
36484
36772
  launcherPath: control.launcher,
36485
36773
  logPath,
36486
- workingDirectory: options.homeDir ?? homedir7(),
36774
+ workingDirectory: options.homeDir ?? homedir8(),
36487
36775
  label: options.label
36488
36776
  });
36489
- if (readFileSync11(service.plistPath, "utf8") !== expected) {
36777
+ if (readFileSync12(service.plistPath, "utf8") !== expected) {
36490
36778
  throw new Error(
36491
36779
  `refusing to remove unrecognized launchd property list at ${service.plistPath}`
36492
36780
  );
@@ -36511,7 +36799,7 @@ function assertOwnedDaemonRuntime(options) {
36511
36799
  throw new Error(`refusing to remove non-directory daemon releases at ${runtime.releasesDir}`);
36512
36800
  }
36513
36801
  for (const entry of readdirSync3(runtime.releasesDir, { withFileTypes: true })) {
36514
- const releaseDir = join14(runtime.releasesDir, entry.name);
36802
+ const releaseDir = join15(runtime.releasesDir, entry.name);
36515
36803
  const manifest = entry.isDirectory() && RUNTIME_RELEASE_RE.test(entry.name) ? readOwnedRuntimeManifest(releaseDir) : null;
36516
36804
  if (!manifest) {
36517
36805
  throw new Error(`refusing to remove unrecognized daemon release ${releaseDir}`);
@@ -36529,7 +36817,7 @@ function assertOwnedDaemonRuntime(options) {
36529
36817
  }
36530
36818
  const target = readlinkSync(runtime.currentLink);
36531
36819
  const releaseName = basename3(target);
36532
- if (target !== join14("releases", releaseName) || !RUNTIME_RELEASE_RE.test(releaseName)) {
36820
+ if (target !== join15("releases", releaseName) || !RUNTIME_RELEASE_RE.test(releaseName)) {
36533
36821
  throw new Error(
36534
36822
  `refusing to remove malformed daemon runtime selector ${runtime.currentLink}`
36535
36823
  );
@@ -36557,7 +36845,7 @@ async function removeDaemonRuntime(options = {}) {
36557
36845
  const control = daemonControlPaths(options);
36558
36846
  const configDir = primConfigDirectory(options);
36559
36847
  const service = process.platform === "darwin" ? launchdPaths(options) : void 0;
36560
- const logPath = service?.logPath ?? join14(configDir, "daemon.log");
36848
+ const logPath = service?.logPath ?? join15(configDir, "daemon.log");
36561
36849
  const ownedArtifacts = [
36562
36850
  runtime.runtimeDir,
36563
36851
  control.launcher,
@@ -36565,8 +36853,8 @@ async function removeDaemonRuntime(options = {}) {
36565
36853
  control.legacyDisabledMarker,
36566
36854
  ...service ? [service.plistPath] : [],
36567
36855
  logPath,
36568
- join14(configDir, "daemon-health.json"),
36569
- join14(configDir, "client_instance_id")
36856
+ join15(configDir, "daemon-health.json"),
36857
+ join15(configDir, "client_instance_id")
36570
36858
  ];
36571
36859
  if (!ownedArtifacts.some((path9) => lstatIfPresent3(path9))) {
36572
36860
  return { changed: false, runtimePaths: runtime };
@@ -36610,11 +36898,11 @@ ${config.configDir ? `export PRIM_CONFIG_DIR=${shellQuote2(config.configDir)}
36610
36898
  }
36611
36899
  function readDaemonLauncher(path9) {
36612
36900
  try {
36613
- const content = readFileSync11(path9, "utf8");
36901
+ const content = readFileSync12(path9, "utf8");
36614
36902
  const encoded = /^# prim-daemon-launcher: ([A-Za-z0-9_-]+)$/mu.exec(content)?.[1];
36615
36903
  if (!encoded) return null;
36616
36904
  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") {
36905
+ 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
36906
  return null;
36619
36907
  }
36620
36908
  const config = {
@@ -36633,7 +36921,7 @@ function readDaemonLauncher(path9) {
36633
36921
  function readUsableDaemonConfig(path9) {
36634
36922
  const config = readDaemonLauncher(path9);
36635
36923
  if (!config) return null;
36636
- const manifest = readRuntimeManifest(join14(dirname10(config.daemonPath), "manifest.json"));
36924
+ const manifest = readRuntimeManifest(join15(dirname10(config.daemonPath), "manifest.json"));
36637
36925
  try {
36638
36926
  accessSync2(config.nodePath, constants4.X_OK);
36639
36927
  return manifest?.version === config.runtimeVersion && manifest.nodePath === config.nodePath && manifest.daemonSha256 === sha256File(config.daemonPath) ? config : null;
@@ -36678,7 +36966,7 @@ function generateLaunchAgentPlist(config) {
36678
36966
  `;
36679
36967
  }
36680
36968
  function launchdPaths(options = {}) {
36681
- const home = options.homeDir ?? homedir7();
36969
+ const home = options.homeDir ?? homedir8();
36682
36970
  const configDir = primConfigDirectory(options);
36683
36971
  const uid = options.uid ?? process.getuid?.();
36684
36972
  const label = options.label ?? LAUNCHD_LABEL;
@@ -36686,8 +36974,8 @@ function launchdPaths(options = {}) {
36686
36974
  return {
36687
36975
  domainTarget: `gui/${uid}`,
36688
36976
  serviceTarget: `gui/${uid}/${label}`,
36689
- plistPath: join14(home, "Library", "LaunchAgents", `${label}.plist`),
36690
- logPath: join14(configDir, "daemon.log")
36977
+ plistPath: join15(home, "Library", "LaunchAgents", `${label}.plist`),
36978
+ logPath: join15(configDir, "daemon.log")
36691
36979
  };
36692
36980
  }
36693
36981
  var runLaunchctl = (args, timeoutMs2 = COMMAND_TIMEOUT_MS) => {
@@ -36720,7 +37008,7 @@ function getLaunchdService(options = {}) {
36720
37008
  }
36721
37009
  function atomicWrite3(path9, content, mode, validate3) {
36722
37010
  try {
36723
- if (readFileSync11(path9, "utf8") === content) {
37011
+ if (readFileSync12(path9, "utf8") === content) {
36724
37012
  chmodSync4(path9, mode);
36725
37013
  validate3?.(path9, COMMAND_TIMEOUT_MS);
36726
37014
  return false;
@@ -36762,14 +37050,14 @@ async function inspectDaemon(timeoutMs2) {
36762
37050
  function canonicalProspectivePath(path9) {
36763
37051
  const suffix = [];
36764
37052
  let ancestor = resolve6(path9);
36765
- while (!existsSync10(ancestor)) {
37053
+ while (!existsSync11(ancestor)) {
36766
37054
  const parent = dirname10(ancestor);
36767
37055
  if (parent === ancestor) return resolve6(path9);
36768
37056
  suffix.unshift(basename3(ancestor));
36769
37057
  ancestor = parent;
36770
37058
  }
36771
37059
  try {
36772
- return join14(realpathSync3(ancestor), ...suffix);
37060
+ return join15(realpathSync3(ancestor), ...suffix);
36773
37061
  } catch {
36774
37062
  return resolve6(path9);
36775
37063
  }
@@ -36784,10 +37072,10 @@ async function withDaemonLifecycleLock(operation, options = {}) {
36784
37072
  );
36785
37073
  }
36786
37074
  async function stopVerifiedLegacyDaemon(options, deadlineMs, nowMs, sleep2) {
36787
- const pidPath = join14(primConfigDirectory(options), "daemon.pid");
37075
+ const pidPath = join15(primConfigDirectory(options), "daemon.pid");
36788
37076
  let pid;
36789
37077
  try {
36790
- pid = Number(readFileSync11(pidPath, "utf8").trim());
37078
+ pid = Number(readFileSync12(pidPath, "utf8").trim());
36791
37079
  } catch {
36792
37080
  throw new Error("an unsupervised daemon answered, but it has no verifiable pidfile");
36793
37081
  }
@@ -36964,7 +37252,7 @@ async function waitForAbsence(context) {
36964
37252
  }
36965
37253
  function daemonExplicitlyDisabled(options = {}) {
36966
37254
  const paths = daemonControlPaths(options);
36967
- return existsSync10(paths.disabledMarker) || existsSync10(paths.legacyDisabledMarker);
37255
+ return existsSync11(paths.disabledMarker) || existsSync11(paths.legacyDisabledMarker);
36968
37256
  }
36969
37257
  function setDaemonExplicitlyDisabled(disabled, options = {}) {
36970
37258
  const paths = daemonControlPaths(options);
@@ -36987,7 +37275,7 @@ async function ensureMacDaemonLocked(options) {
36987
37275
  let service = getLaunchdService({ ...options, runner });
36988
37276
  if (!options.explicitlyStarted && daemonExplicitlyDisabled(options)) {
36989
37277
  const control2 = daemonControlPaths(options);
36990
- if (!existsSync10(control2.disabledMarker)) {
37278
+ if (!existsSync11(control2.disabledMarker)) {
36991
37279
  atomicWrite3(control2.disabledMarker, "disabled by `prim daemon stop`\n", RUNTIME_FILE_MODE);
36992
37280
  }
36993
37281
  return {
@@ -37014,7 +37302,7 @@ async function ensureMacDaemonLocked(options) {
37014
37302
  const configuredApiUrl = (options.env ?? process.env).PRIM_API_URL;
37015
37303
  const apiUrl = configuredApiUrl ? normalizeApiUrl(configuredApiUrl) || void 0 : void 0;
37016
37304
  const configDir = primConfigDirectory(options);
37017
- const legacyDefaultConfigDir = join14(options.homeDir ?? homedir7(), ".config", "prim");
37305
+ const legacyDefaultConfigDir = join15(options.homeDir ?? homedir8(), ".config", "prim");
37018
37306
  const launcherConfigDir = configDir === legacyDefaultConfigDir ? void 0 : configDir;
37019
37307
  if (retainSelected && selected) {
37020
37308
  const usable = readUsableDaemonConfig(control.launcher);
@@ -37049,7 +37337,7 @@ async function ensureMacDaemonLocked(options) {
37049
37337
  const plist = generateLaunchAgentPlist({
37050
37338
  launcherPath: control.launcher,
37051
37339
  logPath: servicePaths.logPath,
37052
- workingDirectory: options.homeDir ?? homedir7(),
37340
+ workingDirectory: options.homeDir ?? homedir8(),
37053
37341
  label: options.label
37054
37342
  });
37055
37343
  const plistChanged = atomicWrite3(
@@ -37272,9 +37560,9 @@ function formatStatusline(version, snapshot, resolveIngestionStatus, options = {
37272
37560
  // src/commands/daemon.ts
37273
37561
  var DAEMON_BIN = "prim-daemon-server";
37274
37562
  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");
37563
+ var PID_PATH = join16(CONFIG_DIR, "daemon.pid");
37564
+ var SOCK_PATH2 = join16(CONFIG_DIR, "sock");
37565
+ var LOG_PATH = join16(CONFIG_DIR, "daemon.log");
37278
37566
  var CONFIG_DIR_MODE2 = 448;
37279
37567
  var LOG_FILE_MODE = 384;
37280
37568
  var STOP_TIMEOUT_MS = 5e3;
@@ -37312,10 +37600,10 @@ function daemonDegradedReason(snapshot) {
37312
37600
  return "health checks have not recovered";
37313
37601
  }
37314
37602
  function readPidfile() {
37315
- if (!existsSync11(PID_PATH)) {
37603
+ if (!existsSync12(PID_PATH)) {
37316
37604
  return null;
37317
37605
  }
37318
- const raw = readFileSync12(PID_PATH, "utf-8").trim();
37606
+ const raw = readFileSync13(PID_PATH, "utf-8").trim();
37319
37607
  const pid = Number(raw);
37320
37608
  if (!Number.isInteger(pid) || pid <= 0) {
37321
37609
  return null;
@@ -37340,10 +37628,10 @@ function spawnDaemon(options) {
37340
37628
  return file ? spawn3(process.execPath, [file], options) : spawn3(DAEMON_BIN, [], options);
37341
37629
  }
37342
37630
  function openDaemonLog(configDir = CONFIG_DIR) {
37343
- if (!existsSync11(configDir)) {
37631
+ if (!existsSync12(configDir)) {
37344
37632
  mkdirSync9(configDir, { recursive: true, mode: CONFIG_DIR_MODE2 });
37345
37633
  }
37346
- return openSync3(join15(configDir, "daemon.log"), "a", LOG_FILE_MODE);
37634
+ return openSync3(join16(configDir, "daemon.log"), "a", LOG_FILE_MODE);
37347
37635
  }
37348
37636
  async function waitForReady() {
37349
37637
  const deadline = Date.now() + READY_TIMEOUT_MS;
@@ -37477,7 +37765,7 @@ async function detachedDaemonStop() {
37477
37765
  {},
37478
37766
  { timeoutMs: STATUS_PROBE_TIMEOUT_MS }
37479
37767
  );
37480
- if (existsSync11(PID_PATH) || existsSync11(SOCK_PATH2) || socketOwner) {
37768
+ if (existsSync12(PID_PATH) || existsSync12(SOCK_PATH2) || socketOwner) {
37481
37769
  process.stderr.write(
37482
37770
  `[prim] refusing to verify daemon absence: ${socketOwner ? `socket is owned by pid=${socketOwner.pid}` : "daemon artifacts remain"}
37483
37771
  `
@@ -37509,7 +37797,7 @@ async function detachedDaemonStop() {
37509
37797
  {},
37510
37798
  { timeoutMs: STATUS_PROBE_TIMEOUT_MS }
37511
37799
  );
37512
- if (socketOwner || existsSync11(SOCK_PATH2)) {
37800
+ if (socketOwner || existsSync12(SOCK_PATH2)) {
37513
37801
  process.stderr.write(
37514
37802
  `[prim] refusing to clear stale pidfile: ${socketOwner ? `socket is owned by pid=${socketOwner.pid}` : "socket artifact remains"}
37515
37803
  `
@@ -38298,6 +38586,8 @@ function authorLabel(row) {
38298
38586
  return "Your Claude Code";
38299
38587
  case "codex":
38300
38588
  return "Your Codex";
38589
+ case "cursor":
38590
+ return "Your Cursor";
38301
38591
  case "hermes":
38302
38592
  return "Your Hermes";
38303
38593
  case "chat":
@@ -39730,6 +40020,7 @@ function describeAudienceMember(member) {
39730
40020
  return {
39731
40021
  claude_code: "Claude Code agent",
39732
40022
  codex: "Codex agent",
40023
+ cursor: "Cursor agent",
39733
40024
  hermes: "Hermes agent"
39734
40025
  }[member.agent] ?? terminalSafeLine(member.agent);
39735
40026
  case "credential":
@@ -39941,7 +40232,7 @@ var UserScopeInputError = class extends Error {
39941
40232
  }
39942
40233
  };
39943
40234
  var USER_SCOPE_ROLES = /* @__PURE__ */ new Set(["owner", "admin", "member"]);
39944
- var USER_SCOPE_AGENTS = /* @__PURE__ */ new Set(["claude_code", "codex", "hermes"]);
40235
+ var USER_SCOPE_AGENTS = /* @__PURE__ */ new Set(["claude_code", "codex", "cursor", "hermes"]);
39945
40236
  var USER_SCOPE_CREDENTIALS = /* @__PURE__ */ new Set(["workos_jwt", "workos_api_key", "service_token"]);
39946
40237
  function requiredScopeValue(flag, value) {
39947
40238
  const trimmed = value.trim();
@@ -39969,9 +40260,12 @@ function userScopeFromOptions(opts) {
39969
40260
  for (const value of agents) {
39970
40261
  const agent = requiredScopeValue("--for-agent", value);
39971
40262
  if (!USER_SCOPE_AGENTS.has(agent)) {
39972
- throw new UserScopeInputError("--for-agent must be claude_code, codex, or hermes");
40263
+ throw new UserScopeInputError("--for-agent must be claude_code, codex, cursor, or hermes");
39973
40264
  }
39974
- members.push({ kind: "agent", agent });
40265
+ members.push({
40266
+ kind: "agent",
40267
+ agent
40268
+ });
39975
40269
  }
39976
40270
  for (const value of credentials) {
39977
40271
  const credential = requiredScopeValue("--for-credential", value);
@@ -40178,7 +40472,7 @@ function registerDecisionsCommands(program3) {
40178
40472
  []
40179
40473
  ).option(
40180
40474
  "--for-agent <agent>",
40181
- "Include one agent: claude_code | codex | hermes (repeatable)",
40475
+ "Include one agent: claude_code | codex | cursor | hermes (repeatable)",
40182
40476
  collectItem,
40183
40477
  []
40184
40478
  ).option(
@@ -40334,7 +40628,7 @@ function registerDecisionsCommands(program3) {
40334
40628
  []
40335
40629
  ).option(
40336
40630
  "--for-agent <agent>",
40337
- "Set one agent: claude_code | codex | hermes (repeatable)",
40631
+ "Set one agent: claude_code | codex | cursor | hermes (repeatable)",
40338
40632
  collectItem,
40339
40633
  []
40340
40634
  ).option(
@@ -40414,7 +40708,7 @@ function registerDecisionsCommands(program3) {
40414
40708
  }
40415
40709
 
40416
40710
  // src/commands/doctor.ts
40417
- import { existsSync as existsSync14 } from "fs";
40711
+ import { existsSync as existsSync15 } from "fs";
40418
40712
 
40419
40713
  // src/decisions/feedback.ts
40420
40714
  var FEEDBACK_PROTOCOL_VERSION = 2;
@@ -40559,17 +40853,17 @@ async function inspectJournalDelivery(buckets, options = {}) {
40559
40853
  import {
40560
40854
  appendFileSync,
40561
40855
  closeSync as closeSync4,
40562
- existsSync as existsSync12,
40856
+ existsSync as existsSync13,
40563
40857
  fstatSync,
40564
40858
  mkdirSync as mkdirSync10,
40565
40859
  openSync as openSync4,
40566
40860
  opendirSync,
40567
- readFileSync as readFileSync13,
40861
+ readFileSync as readFileSync14,
40568
40862
  readSync,
40569
40863
  readdirSync as readdirSync4
40570
40864
  } from "fs";
40571
- import { dirname as dirname11, join as join16 } from "path";
40572
- var JOURNAL_DIR = join16(primConfigDirectory(), "moves");
40865
+ import { dirname as dirname11, join as join17 } from "path";
40866
+ var JOURNAL_DIR = join17(primConfigDirectory(), "moves");
40573
40867
  var JOURNAL_BASENAME = "journal.ndjson";
40574
40868
  var JOURNAL_STATS_SAMPLE_BYTES = 64 * 1024;
40575
40869
  var PENDING_STATS_MAX_FILES = 128;
@@ -40581,7 +40875,7 @@ function envSlug(apiUrl) {
40581
40875
  return slug;
40582
40876
  }
40583
40877
  function currentEnvDir() {
40584
- return join16(JOURNAL_DIR, envSlug(getSiteUrl()));
40878
+ return join17(JOURNAL_DIR, envSlug(getSiteUrl()));
40585
40879
  }
40586
40880
  function parseMoves(content) {
40587
40881
  const moves = [];
@@ -40597,23 +40891,23 @@ function parseMoves(content) {
40597
40891
  return moves;
40598
40892
  }
40599
40893
  function readMovesFromPath(path9) {
40600
- if (!existsSync12(path9)) {
40894
+ if (!existsSync13(path9)) {
40601
40895
  return [];
40602
40896
  }
40603
- return parseMoves(readFileSync13(path9, "utf-8"));
40897
+ return parseMoves(readFileSync14(path9, "utf-8"));
40604
40898
  }
40605
40899
  function listBuckets() {
40606
40900
  const out = [];
40607
40901
  const envDir = currentEnvDir();
40608
- if (!existsSync12(envDir)) {
40902
+ if (!existsSync13(envDir)) {
40609
40903
  return out;
40610
40904
  }
40611
40905
  for (const entry of readdirSync4(envDir, { withFileTypes: true })) {
40612
40906
  if (!entry.isDirectory()) {
40613
40907
  continue;
40614
40908
  }
40615
- const path9 = join16(envDir, entry.name, JOURNAL_BASENAME);
40616
- if (existsSync12(path9)) {
40909
+ const path9 = join17(envDir, entry.name, JOURNAL_BASENAME);
40910
+ if (existsSync13(path9)) {
40617
40911
  out.push({ bucket: entry.name, path: path9 });
40618
40912
  }
40619
40913
  }
@@ -40673,7 +40967,7 @@ function parseFlushingPid(name) {
40673
40967
  return Number.isSafeInteger(pid) && pid > 0 ? pid : void 0;
40674
40968
  }
40675
40969
  function listFlushingInDir(dir, bucket, options = {}) {
40676
- if (!existsSync12(dir)) {
40970
+ if (!existsSync13(dir)) {
40677
40971
  return [];
40678
40972
  }
40679
40973
  const out = [];
@@ -40687,7 +40981,7 @@ function listFlushingInDir(dir, bucket, options = {}) {
40687
40981
  entry = entries.readSync();
40688
40982
  continue;
40689
40983
  }
40690
- const path9 = join16(dir, entry.name);
40984
+ const path9 = join17(dir, entry.name);
40691
40985
  let sample;
40692
40986
  try {
40693
40987
  sample = sampleJournalFile(path9, remainingBytes);
@@ -40714,7 +41008,7 @@ function listFlushingInDir(dir, bucket, options = {}) {
40714
41008
  }
40715
41009
  function listFlushing(options = {}) {
40716
41010
  const envDir = currentEnvDir();
40717
- if (!existsSync12(envDir)) {
41011
+ if (!existsSync13(envDir)) {
40718
41012
  return [];
40719
41013
  }
40720
41014
  const out = [];
@@ -40725,7 +41019,7 @@ function listFlushing(options = {}) {
40725
41019
  break;
40726
41020
  }
40727
41021
  if (entry.isDirectory()) {
40728
- const found = listFlushingInDir(join16(envDir, entry.name), entry.name, {
41022
+ const found = listFlushingInDir(join17(envDir, entry.name), entry.name, {
40729
41023
  sampleBytes: remainingBytes,
40730
41024
  maxFiles: maxFiles - out.length
40731
41025
  });
@@ -40783,9 +41077,9 @@ function pendingJournalStats() {
40783
41077
  }
40784
41078
 
40785
41079
  // 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";
41080
+ import { existsSync as existsSync14, readFileSync as readFileSync15, rmSync as rmSync6, statSync as statSync3 } from "fs";
41081
+ import { homedir as homedir9 } from "os";
41082
+ import { join as join18 } from "path";
40789
41083
 
40790
41084
  // node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/browser/dist/nodes/identity.js
40791
41085
  var ALIAS = /* @__PURE__ */ Symbol.for("yaml.alias");
@@ -47053,33 +47347,33 @@ function stringify3(value, replacer, options) {
47053
47347
  }
47054
47348
 
47055
47349
  // src/commands/hermes-install.ts
47056
- var CAPTURE_BIN3 = "prim-hook";
47057
- var GATE_BIN3 = "prim-pre-tool-use";
47350
+ var CAPTURE_BIN4 = "prim-hook";
47351
+ var GATE_BIN4 = "prim-pre-tool-use";
47058
47352
  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";
47353
+ var SESSION_START_BIN4 = "prim-session-start";
47354
+ var SESSION_END_BIN3 = "prim-session-end";
47061
47355
  var HERMES_ARGS = "--agent hermes";
47062
47356
  var EDIT_MATCHER = "write_file|patch";
47063
47357
  var JSON_INDENT3 = 2;
47064
47358
  var CONFIG_MODE = 384;
47065
- var PRIM_BINS3 = [CAPTURE_BIN3, GATE_BIN3, POST_TOOL_USE_BIN3, SESSION_START_BIN3, SESSION_END_BIN2];
47359
+ var PRIM_BINS4 = [CAPTURE_BIN4, GATE_BIN4, POST_TOOL_USE_BIN3, SESSION_START_BIN4, SESSION_END_BIN3];
47066
47360
  function hermesHome() {
47067
- return process.env.HERMES_HOME ?? join17(homedir8(), ".hermes");
47361
+ return process.env.HERMES_HOME ?? join18(homedir9(), ".hermes");
47068
47362
  }
47069
47363
  function configPath() {
47070
- return join17(hermesHome(), "config.yaml");
47364
+ return join18(hermesHome(), "config.yaml");
47071
47365
  }
47072
47366
  function legacyShimPath() {
47073
- return join17(hermesHome(), "agent-hooks", "prim-shim.sh");
47367
+ return join18(hermesHome(), "agent-hooks", "prim-shim.sh");
47074
47368
  }
47075
- function commandFor(bin) {
47369
+ function commandFor2(bin) {
47076
47370
  return stableHookCommand(bin, HERMES_ARGS);
47077
47371
  }
47078
47372
  function legacyCommandFor(bin) {
47079
47373
  return `"${legacyShimPath()}" ${bin} ${HERMES_ARGS}`;
47080
47374
  }
47081
47375
  function commandUsesBin(command, bin) {
47082
- return command === commandFor(bin) || command === legacyCommandFor(bin);
47376
+ return command === commandFor2(bin) || command === legacyCommandFor(bin);
47083
47377
  }
47084
47378
  var CAPTURE_EVENTS2 = [
47085
47379
  "on_session_start",
@@ -47091,13 +47385,13 @@ var CAPTURE_EVENTS2 = [
47091
47385
  "subagent_stop"
47092
47386
  ];
47093
47387
  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 },
47388
+ var REGISTRATIONS3 = [
47389
+ ...CAPTURE_EVENTS2.map((event) => ({ event, bin: CAPTURE_BIN4 })),
47390
+ { event: "pre_tool_call", matcher: EDIT_MATCHER, bin: GATE_BIN4, timeout: GATE_TIMEOUT_SECONDS },
47097
47391
  { event: "post_tool_call", matcher: EDIT_MATCHER, bin: POST_TOOL_USE_BIN3 },
47098
47392
  { 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 }
47393
+ { event: "on_session_start", bin: SESSION_START_BIN4 },
47394
+ { event: "on_session_end", bin: SESSION_END_BIN3 }
47101
47395
  ];
47102
47396
  function yamlValue(node) {
47103
47397
  return typeof node?.toJSON === "function" ? node.toJSON?.() : node;
@@ -47107,7 +47401,7 @@ function hookEntry(node) {
47107
47401
  return typeof value === "object" && value !== null && typeof value.command === "string" ? value : null;
47108
47402
  }
47109
47403
  function entryFor(reg) {
47110
- const command = commandFor(reg.bin);
47404
+ const command = commandFor2(reg.bin);
47111
47405
  const entry = reg.matcher ? { matcher: reg.matcher, command } : { command };
47112
47406
  if (reg.timeout !== void 0) {
47113
47407
  entry.timeout = reg.timeout;
@@ -47129,7 +47423,7 @@ function ensureReg(list, reg, force) {
47129
47423
  }
47130
47424
  function applyInstall3(hooks, force) {
47131
47425
  const next = { ...hooks };
47132
- for (const reg of REGISTRATIONS2) {
47426
+ for (const reg of REGISTRATIONS3) {
47133
47427
  next[reg.event] = ensureReg(next[reg.event] ?? [], reg, force);
47134
47428
  }
47135
47429
  return next;
@@ -47138,7 +47432,7 @@ function applyUninstall3(hooks) {
47138
47432
  const next = {};
47139
47433
  for (const [event, list] of Object.entries(hooks)) {
47140
47434
  let kept = list;
47141
- for (const bin of PRIM_BINS3) {
47435
+ for (const bin of PRIM_BINS4) {
47142
47436
  kept = stripBin(kept, bin);
47143
47437
  }
47144
47438
  if (kept.length > 0) {
@@ -47148,15 +47442,15 @@ function applyUninstall3(hooks) {
47148
47442
  return next;
47149
47443
  }
47150
47444
  function isGateInstalled3(hooks) {
47151
- return (hooks.pre_tool_call ?? []).some((e) => commandUsesBin(e.command, GATE_BIN3));
47445
+ return (hooks.pre_tool_call ?? []).some((e) => commandUsesBin(e.command, GATE_BIN4));
47152
47446
  }
47153
47447
  function isCaptureInstalled(hooks) {
47154
47448
  return CAPTURE_EVENTS2.some(
47155
- (event) => (hooks[event] ?? []).some((e) => commandUsesBin(e.command, CAPTURE_BIN3))
47449
+ (event) => (hooks[event] ?? []).some((e) => commandUsesBin(e.command, CAPTURE_BIN4))
47156
47450
  );
47157
47451
  }
47158
47452
  function entryUsesOwnedBin(entry) {
47159
- return PRIM_BINS3.some(
47453
+ return PRIM_BINS4.some(
47160
47454
  (bin) => commandUsesBin(entry.command, bin) || commandMatchesBin(entry.command, bin)
47161
47455
  );
47162
47456
  }
@@ -47171,21 +47465,21 @@ function hasAnyHookRegistration3(hooks) {
47171
47465
  function hookRuntimeResolutions3(hooks) {
47172
47466
  const resolutions = hookCommandResolutions(
47173
47467
  Object.values(hooks).flatMap((entries) => entries.map((entry) => entry.command)),
47174
- PRIM_BINS3
47468
+ PRIM_BINS4
47175
47469
  );
47176
47470
  for (const entries of Object.values(hooks)) {
47177
47471
  for (const entry of entries) {
47178
- for (const bin of PRIM_BINS3) {
47472
+ for (const bin of PRIM_BINS4) {
47179
47473
  if (entry.command === legacyCommandFor(bin)) resolutions.push({ kind: "legacy_path" });
47180
47474
  }
47181
47475
  }
47182
47476
  }
47183
47477
  return resolutions;
47184
47478
  }
47185
- function inspectHookRuntimeResolutions3() {
47479
+ function inspectHookRuntimeResolutions4() {
47186
47480
  const path9 = configPath();
47187
- if (!existsSync13(path9)) return [];
47188
- return hookRuntimeResolutions3(readHooks(parseHermesDocument(readFileSync14(path9, "utf8"))));
47481
+ if (!existsSync14(path9)) return [];
47482
+ return hookRuntimeResolutions3(readHooks(parseHermesDocument(readFileSync15(path9, "utf8"))));
47189
47483
  }
47190
47484
  function entryMatchesRegistration3(owned, registration) {
47191
47485
  const expected = entryFor(registration);
@@ -47193,7 +47487,7 @@ function entryMatchesRegistration3(owned, registration) {
47193
47487
  }
47194
47488
  function hasCompleteHookRegistration3(hooks) {
47195
47489
  const owned = ownedRegistrationEntries3(hooks);
47196
- return owned.length === REGISTRATIONS2.length && REGISTRATIONS2.every(
47490
+ return owned.length === REGISTRATIONS3.length && REGISTRATIONS3.every(
47197
47491
  (registration) => owned.filter((entry) => entryMatchesRegistration3(entry, registration)).length === 1
47198
47492
  );
47199
47493
  }
@@ -47269,7 +47563,7 @@ function serializeHooks(hooks) {
47269
47563
  return stringify3({ hooks }, { lineWidth: 0 });
47270
47564
  }
47271
47565
  function isPrimEntry(entry) {
47272
- return PRIM_BINS3.some((bin) => commandUsesBin(entry.command, bin));
47566
+ return PRIM_BINS4.some((bin) => commandUsesBin(entry.command, bin));
47273
47567
  }
47274
47568
  function entryKey(entry) {
47275
47569
  return JSON.stringify(entry);
@@ -47454,11 +47748,11 @@ function assertMergeValid(before, after, expectedHooks) {
47454
47748
  }
47455
47749
  }
47456
47750
  function readConfigSnapshot(path9) {
47457
- if (!existsSync13(path9)) return { exists: false, mode: CONFIG_MODE, raw: "" };
47751
+ if (!existsSync14(path9)) return { exists: false, mode: CONFIG_MODE, raw: "" };
47458
47752
  return {
47459
47753
  exists: true,
47460
47754
  mode: statSync3(path9).mode & 511,
47461
- raw: readFileSync14(path9, "utf8")
47755
+ raw: readFileSync15(path9, "utf8")
47462
47756
  };
47463
47757
  }
47464
47758
  var CONCURRENT_CONFIG_MESSAGE = "Hermes config changed during update; concurrent changes were preserved, retry the command";
@@ -47467,7 +47761,7 @@ function writeHermesConfigSnapshot(path9, before, after, expectedHooks) {
47467
47761
  ensureParent: true,
47468
47762
  mode: before.mode,
47469
47763
  validate(temporaryPath) {
47470
- const flushed = readFileSync14(temporaryPath, "utf8");
47764
+ const flushed = readFileSync15(temporaryPath, "utf8");
47471
47765
  if (!mergePreservesHermesSemantics(before.raw, flushed, expectedHooks)) {
47472
47766
  throw new Error(INVALID_MERGE_MESSAGE);
47473
47767
  }
@@ -47490,7 +47784,7 @@ function autoAcceptOf(raw) {
47490
47784
  function readHooksFromRaw(raw) {
47491
47785
  return readHooks(parseHermesDocument(raw));
47492
47786
  }
47493
- function performInstall3(opts) {
47787
+ function performInstall4(opts) {
47494
47788
  (opts.stageRuntime ?? stageHookRuntime)();
47495
47789
  const path9 = configPath();
47496
47790
  const snapshot = readConfigSnapshot(path9);
@@ -47518,9 +47812,9 @@ function performInstall3(opts) {
47518
47812
  changed
47519
47813
  };
47520
47814
  }
47521
- function performUninstall3() {
47815
+ function performUninstall4() {
47522
47816
  const path9 = configPath();
47523
- if (!existsSync13(path9)) {
47817
+ if (!existsSync14(path9)) {
47524
47818
  removeLegacyShim();
47525
47819
  return { path: path9, gate: false, capture: false, autoAccept: false, changed: false };
47526
47820
  }
@@ -47543,9 +47837,9 @@ function performUninstall3() {
47543
47837
  changed
47544
47838
  };
47545
47839
  }
47546
- function performStatus3() {
47840
+ function performStatus4() {
47547
47841
  const path9 = configPath();
47548
- const raw = existsSync13(path9) ? readFileSync14(path9, "utf8") : "";
47842
+ const raw = existsSync14(path9) ? readFileSync15(path9, "utf8") : "";
47549
47843
  const hooks = raw ? readHooks(parseHermesDocument(raw)) : {};
47550
47844
  return {
47551
47845
  path: path9,
@@ -47569,7 +47863,7 @@ function registerHermesCommands(program3) {
47569
47863
  const hermes = program3.command("hermes").description("Manage the prim Hermes Agent integration (capture, gate, ingest, presence)");
47570
47864
  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
47865
  rejectProjectScope(opts.scope);
47572
- const result = performInstall3({
47866
+ const result = performInstall4({
47573
47867
  force: opts.force ?? false,
47574
47868
  autoAccept: opts.autoAccept ?? false
47575
47869
  });
@@ -47580,14 +47874,14 @@ function registerHermesCommands(program3) {
47580
47874
  console.log(JSON.stringify(result, null, JSON_INDENT3));
47581
47875
  });
47582
47876
  hermes.command("uninstall").description("Remove all prim hooks from Hermes's ~/.hermes/config.yaml").action(() => {
47583
- const result = performUninstall3();
47877
+ const result = performUninstall4();
47584
47878
  console.error(
47585
47879
  result.changed ? `[prim] prim hooks removed from ${result.path}` : `[prim] no prim hooks to remove at ${result.path} (nothing changed)`
47586
47880
  );
47587
47881
  console.log(JSON.stringify(result, null, JSON_INDENT3));
47588
47882
  });
47589
47883
  hermes.command("status").description("Report whether each prim surface (gate, capture) is installed").action(() => {
47590
- const result = performStatus3();
47884
+ const result = performStatus4();
47591
47885
  const mark = (b) => b ? "\u2713" : "\u2717";
47592
47886
  console.error(
47593
47887
  `[prim] hermes: gate ${mark(result.gate)} \xB7 capture ${mark(result.capture)} (${result.path})`
@@ -47635,7 +47929,7 @@ function checkAuth() {
47635
47929
  return classifyAuthCredential(
47636
47930
  credential,
47637
47931
  storedCredential ? getTokenExpiresAt() : void 0,
47638
- storedCredential && existsSync14(REFRESH_TOKEN_PATH)
47932
+ storedCredential && existsSync15(REFRESH_TOKEN_PATH)
47639
47933
  );
47640
47934
  }
47641
47935
  function classifyDaemonHealth(snapshot, options = {}) {
@@ -47979,6 +48273,34 @@ function classifyCodexHooks(statuses) {
47979
48273
  detail: "installed; Codex trust is not machine-readable \u2014 verify with `/hooks`"
47980
48274
  };
47981
48275
  }
48276
+ function classifyCursorHooks(statuses) {
48277
+ const installed = statuses.filter((status) => status.present);
48278
+ if (installed.length === 0)
48279
+ return { name: "cursor-hooks", status: "ok", detail: "not installed" };
48280
+ if (installed.some((status) => !status.complete)) {
48281
+ return {
48282
+ name: "cursor-hooks",
48283
+ status: "fail",
48284
+ detail: "incomplete or drifted native lifecycle \u2014 run `prim cursor install --force`"
48285
+ };
48286
+ }
48287
+ const user = statuses.find((status) => status.footer !== void 0);
48288
+ if (user?.present && user.footer === false && !user.footerPreservedCustom) {
48289
+ return {
48290
+ name: "cursor-hooks",
48291
+ status: "fail",
48292
+ detail: "native lifecycle ready but Cursor CLI footer is missing \u2014 run `prim cursor install --scope user --force`"
48293
+ };
48294
+ }
48295
+ if (statuses.some((status) => status.footerPreservedCustom)) {
48296
+ return {
48297
+ name: "cursor-hooks",
48298
+ status: "warn",
48299
+ detail: "native lifecycle ready; custom Cursor CLI footer preserved"
48300
+ };
48301
+ }
48302
+ return { name: "cursor-hooks", status: "ok", detail: "complete native lifecycle ready" };
48303
+ }
47982
48304
  function classifyHermesHooks(status) {
47983
48305
  if (!status.present) {
47984
48306
  return { name: "hermes-hooks", status: "ok", detail: "not installed" };
@@ -48010,7 +48332,18 @@ function checkAgentHooks() {
48010
48332
  });
48011
48333
  }
48012
48334
  try {
48013
- checks.push(classifyHermesHooks(performStatus3()));
48335
+ const status = performStatus3();
48336
+ checks.push(classifyCursorHooks([status.project, status.user]));
48337
+ } catch (error) {
48338
+ const detail = boundedHealthError(error instanceof Error ? error.message : String(error));
48339
+ checks.push({
48340
+ name: "cursor-hooks",
48341
+ status: "fail",
48342
+ detail: detail ?? "hook configuration is unreadable"
48343
+ });
48344
+ }
48345
+ try {
48346
+ checks.push(classifyHermesHooks(performStatus4()));
48014
48347
  } catch (error) {
48015
48348
  const detail = boundedHealthError(error instanceof Error ? error.message : String(error));
48016
48349
  checks.push({
@@ -48120,7 +48453,8 @@ function checkHookRuntime() {
48120
48453
  [
48121
48454
  ...inspectHookRuntimeResolutions(),
48122
48455
  ...inspectHookRuntimeResolutions2(),
48123
- ...inspectHookRuntimeResolutions3()
48456
+ ...inspectHookRuntimeResolutions3(),
48457
+ ...inspectHookRuntimeResolutions4()
48124
48458
  ],
48125
48459
  inspectHookRuntime,
48126
48460
  packageVersion
@@ -48255,12 +48589,12 @@ function registerDoctorCommands(program3) {
48255
48589
  }
48256
48590
 
48257
48591
  // 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";
48592
+ import { existsSync as existsSync17, mkdirSync as mkdirSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
48593
+ import { join as join21 } from "path";
48260
48594
 
48261
48595
  // src/flusher.ts
48262
48596
  import { createReadStream, renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
48263
- import { dirname as dirname13, join as join19 } from "path";
48597
+ import { dirname as dirname13, join as join20 } from "path";
48264
48598
 
48265
48599
  // src/dead-letter.ts
48266
48600
  import { createHash as createHash9, randomBytes as randomBytes6 } from "crypto";
@@ -48268,7 +48602,7 @@ import {
48268
48602
  constants as constants5,
48269
48603
  chmodSync as chmodSync5,
48270
48604
  closeSync as closeSync5,
48271
- existsSync as existsSync15,
48605
+ existsSync as existsSync16,
48272
48606
  fchmodSync as fchmodSync3,
48273
48607
  fsyncSync as fsyncSync3,
48274
48608
  mkdirSync as mkdirSync11,
@@ -48277,16 +48611,16 @@ import {
48277
48611
  rmSync as rmSync7,
48278
48612
  writeFileSync as writeFileSync8
48279
48613
  } from "fs";
48280
- import { dirname as dirname12, join as join18 } from "path";
48614
+ import { dirname as dirname12, join as join19 } from "path";
48281
48615
  var DIRECTORY_MODE3 = 448;
48282
48616
  var FILE_MODE2 = 384;
48283
48617
  var DEAD_LETTER_DIRNAME = "dead-letter";
48284
48618
  function deadLetterDirectoryForRotation(flushingPath) {
48285
- return join18(dirname12(flushingPath), DEAD_LETTER_DIRNAME);
48619
+ return join19(dirname12(flushingPath), DEAD_LETTER_DIRNAME);
48286
48620
  }
48287
48621
  function deadLetterPathForRawLine(flushingPath, rawLine) {
48288
48622
  const quarantineId = createHash9("sha256").update(rawLine).digest("hex");
48289
- return join18(deadLetterDirectoryForRotation(flushingPath), `raw-${quarantineId}.json`);
48623
+ return join19(deadLetterDirectoryForRotation(flushingPath), `raw-${quarantineId}.json`);
48290
48624
  }
48291
48625
  function ensureDeadLetterDirectory(flushingPath, persistDirectory) {
48292
48626
  const directory = deadLetterDirectoryForRotation(flushingPath);
@@ -48296,11 +48630,11 @@ function ensureDeadLetterDirectory(flushingPath, persistDirectory) {
48296
48630
  return directory;
48297
48631
  }
48298
48632
  function persistDeadLetter(directory, path9, quarantineId, record2, persistDirectory) {
48299
- if (existsSync15(path9)) {
48633
+ if (existsSync16(path9)) {
48300
48634
  persistDirectory(directory);
48301
48635
  return;
48302
48636
  }
48303
- const temporaryPath = join18(
48637
+ const temporaryPath = join19(
48304
48638
  directory,
48305
48639
  `.${quarantineId}.${String(process.pid)}.${randomBytes6(8).toString("hex")}.tmp`
48306
48640
  );
@@ -48332,7 +48666,7 @@ function quarantineMove(flushingPath, move, reason, now = Date.now, options = {}
48332
48666
  reason,
48333
48667
  move
48334
48668
  };
48335
- const path9 = join18(directory, `${record2.quarantineId}.json`);
48669
+ const path9 = join19(directory, `${record2.quarantineId}.json`);
48336
48670
  persistDeadLetter(directory, path9, record2.quarantineId, record2, persistDirectory);
48337
48671
  return record2;
48338
48672
  }
@@ -48644,7 +48978,7 @@ async function flushOnce() {
48644
48978
  return inspection.retainedBuckets.length > 0 ? { flushed: total, quarantined, retained: inspection.retainedBuckets } : { flushed: total, quarantined };
48645
48979
  }
48646
48980
  var flushInFlight;
48647
- var FLUSH_LOCK_PATH = join19(dirname13(JOURNAL_DIR), ".flush.lock");
48981
+ var FLUSH_LOCK_PATH = join20(dirname13(JOURNAL_DIR), ".flush.lock");
48648
48982
  var FLUSH_LOCK_TIMEOUT_MS = 250;
48649
48983
  function isFlushLockContended(error) {
48650
48984
  return error instanceof Error && error.message.startsWith("timed out waiting for file lock");
@@ -48778,19 +49112,19 @@ function registerMovesCommands(program3) {
48778
49112
  }
48779
49113
  });
48780
49114
  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)) {
49115
+ const dir = join21(process.cwd(), ".prim");
49116
+ if (!existsSync17(dir)) {
48783
49117
  mkdirSync12(dir, { recursive: true, mode: DIR_MODE });
48784
49118
  }
48785
- const file = join20(process.cwd(), WORKSPACE_FILE);
49119
+ const file = join21(process.cwd(), WORKSPACE_FILE);
48786
49120
  writeFileSync9(file, JSON.stringify({ orgId: opts.orgId, boundAt: Date.now() }, null, 2), {
48787
49121
  mode: FILE_MODE3
48788
49122
  });
48789
49123
  console.log(`[prim] bound ${process.cwd()} to org ${opts.orgId}`);
48790
49124
  });
48791
49125
  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)) {
49126
+ const file = join21(process.cwd(), WORKSPACE_FILE);
49127
+ if (!existsSync17(file)) {
48794
49128
  console.log("[prim] no workspace binding in cwd");
48795
49129
  return;
48796
49130
  }
@@ -48881,31 +49215,31 @@ function registerReconcileCommands(program3) {
48881
49215
 
48882
49216
  // src/commands/session.ts
48883
49217
  import {
48884
- existsSync as existsSync18,
49218
+ existsSync as existsSync19,
48885
49219
  mkdirSync as mkdirSync13,
48886
- readFileSync as readFileSync16,
49220
+ readFileSync as readFileSync17,
48887
49221
  readdirSync as readdirSync5,
48888
49222
  unlinkSync as unlinkSync6,
48889
49223
  writeFileSync as writeFileSync10
48890
49224
  } from "fs";
48891
- import { join as join22 } from "path";
49225
+ import { join as join23 } from "path";
48892
49226
 
48893
49227
  // src/binding.ts
48894
- import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
48895
- import { dirname as dirname14, join as join21 } from "path";
49228
+ import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
49229
+ import { dirname as dirname14, join as join22 } from "path";
48896
49230
  var PRIM_CONFIG_DIR = primConfigDirectory();
48897
- var SESSIONS_DIR = join21(PRIM_CONFIG_DIR, "sessions");
49231
+ var SESSIONS_DIR = join22(PRIM_CONFIG_DIR, "sessions");
48898
49232
 
48899
49233
  // src/commands/session.ts
48900
49234
  var DIR_MODE2 = 448;
48901
49235
  var FILE_MODE4 = 384;
48902
49236
  function ensureDir() {
48903
- if (!existsSync18(SESSIONS_DIR)) {
49237
+ if (!existsSync19(SESSIONS_DIR)) {
48904
49238
  mkdirSync13(SESSIONS_DIR, { recursive: true, mode: DIR_MODE2 });
48905
49239
  }
48906
49240
  }
48907
49241
  function markerPath(sessionId) {
48908
- return join22(SESSIONS_DIR, `${sessionId}.json`);
49242
+ return join23(SESSIONS_DIR, `${sessionId}.json`);
48909
49243
  }
48910
49244
  function registerSessionCommands(program3) {
48911
49245
  const session = program3.command("session").description("Decision Event Pipeline \u2014 session binding markers");
@@ -48921,7 +49255,7 @@ function registerSessionCommands(program3) {
48921
49255
  console.log(`[prim] session ${sessionId} bound to org ${opts.orgId}`);
48922
49256
  });
48923
49257
  session.command("list").description("List active session markers").action(() => {
48924
- if (!existsSync18(SESSIONS_DIR)) {
49258
+ if (!existsSync19(SESSIONS_DIR)) {
48925
49259
  console.log("[prim] no session markers");
48926
49260
  return;
48927
49261
  }
@@ -48933,7 +49267,7 @@ function registerSessionCommands(program3) {
48933
49267
  for (const f of files) {
48934
49268
  const sessionId = f.replace(/\.json$/, "");
48935
49269
  try {
48936
- const m = JSON.parse(readFileSync16(join22(SESSIONS_DIR, f), "utf-8"));
49270
+ const m = JSON.parse(readFileSync17(join23(SESSIONS_DIR, f), "utf-8"));
48937
49271
  console.log(`${sessionId} org=${m.orgId}`);
48938
49272
  } catch {
48939
49273
  }
@@ -48941,7 +49275,7 @@ function registerSessionCommands(program3) {
48941
49275
  });
48942
49276
  session.command("drop <sessionId>").description("Remove a session marker").action((sessionId) => {
48943
49277
  const p = markerPath(sessionId);
48944
- if (!existsSync18(p)) {
49278
+ if (!existsSync19(p)) {
48945
49279
  console.log(`[prim] no marker for session ${sessionId}`);
48946
49280
  return;
48947
49281
  }
@@ -48952,13 +49286,14 @@ function registerSessionCommands(program3) {
48952
49286
 
48953
49287
  // src/commands/setup.ts
48954
49288
  import { spawnSync as spawnSync2 } from "child_process";
48955
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
48956
- import { join as join23 } from "path";
49289
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
49290
+ import { join as join24 } from "path";
48957
49291
  var EXIT_INCOMPLETE = 1;
48958
49292
  var EXIT_USAGE3 = 2;
48959
49293
  var SESSION_LABELS = {
48960
49294
  claude: "Claude Code integration",
48961
49295
  codex: "Codex integration",
49296
+ cursor: "Cursor integration",
48962
49297
  hermes: "Hermes integration"
48963
49298
  };
48964
49299
  function planSetupSteps(opts) {
@@ -49034,8 +49369,8 @@ function detectProjectConflicts(agent, run) {
49034
49369
  }
49035
49370
  try {
49036
49371
  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")) {
49372
+ const preCommit = root && join24(root, ".git", "hooks", "pre-commit");
49373
+ if (preCommit && existsSync20(preCommit) && readFileSync18(preCommit, "utf-8").includes("prim-pre-commit")) {
49039
49374
  conflicts.push(CONFLICT_HOOKS);
49040
49375
  }
49041
49376
  } catch {
@@ -49053,6 +49388,9 @@ function detectAgent(env4) {
49053
49388
  if (env4.HERMES_INTERACTIVE) {
49054
49389
  return "hermes";
49055
49390
  }
49391
+ if (env4.CURSOR_AGENT) {
49392
+ return "cursor";
49393
+ }
49056
49394
  return "claude";
49057
49395
  }
49058
49396
  function resolveAgent(agentFlag, env4) {
@@ -49074,7 +49412,7 @@ function parseSetupAuthStatus(result) {
49074
49412
  function registerSetupCommand(program3, dependencies = {}) {
49075
49413
  program3.command("setup").description(
49076
49414
  "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(
49415
+ ).option("--agent <agent>", "claude, codex, cursor, or hermes (auto-detected when omitted)").option(
49078
49416
  "--scope <scope>",
49079
49417
  "user (default \u2014 install once for every repo) or project (this repo only)",
49080
49418
  "user"
@@ -49083,9 +49421,9 @@ function registerSetupCommand(program3, dependencies = {}) {
49083
49421
  "with the default user scope, remove any project-scoped prim config in this repo (else just warn)"
49084
49422
  ).option("--no-daemon", "stop and disable the companion daemon").action((opts) => {
49085
49423
  const { agent: agentInput, detected } = resolveAgent(opts.agent, process.env);
49086
- if (agentInput !== "claude" && agentInput !== "codex" && agentInput !== "hermes") {
49424
+ if (agentInput !== "claude" && agentInput !== "codex" && agentInput !== "cursor" && agentInput !== "hermes") {
49087
49425
  process.stderr.write(
49088
- `[prim] unknown --agent "${agentInput}" (expected claude, codex, or hermes)
49426
+ `[prim] unknown --agent "${agentInput}" (expected claude, codex, cursor, or hermes)
49089
49427
  `
49090
49428
  );
49091
49429
  (dependencies.exit ?? process.exit)(EXIT_USAGE3);
@@ -49196,18 +49534,22 @@ function registerSetupCommand(program3, dependencies = {}) {
49196
49534
  }
49197
49535
 
49198
49536
  // src/commands/skill.ts
49537
+ import { createHash as createHash11 } from "crypto";
49199
49538
  import {
49200
49539
  constants as constants7,
49201
49540
  closeSync as closeSync7,
49202
- existsSync as existsSync21,
49541
+ existsSync as existsSync22,
49203
49542
  fstatSync as fstatSync3,
49204
49543
  lstatSync as lstatSync7,
49205
49544
  openSync as openSync7,
49206
- readFileSync as readFileSync19,
49207
- readSync as readSync3
49545
+ readFileSync as readFileSync20,
49546
+ readSync as readSync3,
49547
+ readdirSync as readdirSync7,
49548
+ rmdirSync as rmdirSync2,
49549
+ unlinkSync as unlinkSync7
49208
49550
  } from "fs";
49209
- import { homedir as homedir10 } from "os";
49210
- import { dirname as dirname16, join as join26, resolve as resolve8 } from "path";
49551
+ import { homedir as homedir11 } from "os";
49552
+ import { dirname as dirname16, join as join27, resolve as resolve8 } from "path";
49211
49553
  import { fileURLToPath as fileURLToPath5 } from "url";
49212
49554
 
49213
49555
  // node_modules/.pnpm/diff@5.2.2/node_modules/diff/lib/index.mjs
@@ -49377,7 +49719,7 @@ Diff.prototype = {
49377
49719
  tokenize: function tokenize(value) {
49378
49720
  return value.split("");
49379
49721
  },
49380
- join: function join24(chars) {
49722
+ join: function join25(chars) {
49381
49723
  return chars.join("");
49382
49724
  }
49383
49725
  };
@@ -49717,28 +50059,28 @@ import { createHash as createHash10 } from "crypto";
49717
50059
  import {
49718
50060
  constants as constants6,
49719
50061
  closeSync as closeSync6,
49720
- existsSync as existsSync20,
50062
+ existsSync as existsSync21,
49721
50063
  fstatSync as fstatSync2,
49722
50064
  lstatSync as lstatSync6,
49723
50065
  mkdirSync as mkdirSync14,
49724
50066
  openSync as openSync6,
49725
- readFileSync as readFileSync18,
50067
+ readFileSync as readFileSync19,
49726
50068
  readSync as readSync2,
49727
50069
  readdirSync as readdirSync6,
49728
50070
  realpathSync as realpathSync4,
49729
50071
  rmSync as rmSync8,
49730
50072
  rmdirSync
49731
50073
  } 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";
50074
+ import { homedir as homedir10 } from "os";
50075
+ import { dirname as dirname15, isAbsolute as isAbsolute8, join as join26, relative as relative2, resolve as resolve7, sep as sep2 } from "path";
49734
50076
  import { fileURLToPath as fileURLToPath4 } from "url";
49735
50077
  var __dirname4 = dirname15(fileURLToPath4(import.meta.url));
49736
50078
  var PLUGIN_DESCRIPTION = "Primitive decision-graph guidance for the prim CLI \u2014 a model-invoked skill installed by prim skill install.";
49737
50079
  var MAX_MANIFEST_BYTES2 = 64 * 1024;
49738
50080
  var MAX_SKILL_BYTES = 1024 * 1024;
49739
50081
  function pluginDirFor(cwd, scope) {
49740
- const base = scope === "user" ? join25(homedir9(), ".claude") : join25(gitToplevel(cwd) ?? cwd, ".claude");
49741
- return join25(base, "skills", "prim");
50082
+ const base = scope === "user" ? join26(homedir10(), ".claude") : join26(gitToplevel(cwd) ?? cwd, ".claude");
50083
+ return join26(base, "skills", "prim");
49742
50084
  }
49743
50085
  function resolvePluginDir(cwd, scope) {
49744
50086
  if (scope && scope !== "user" && scope !== "project") {
@@ -49751,7 +50093,7 @@ function packageVersion2() {
49751
50093
  let dir = __dirname4;
49752
50094
  while (dir !== dirname15(dir)) {
49753
50095
  const p = resolve7(dir, "package.json");
49754
- if (existsSync20(p)) return JSON.parse(readFileSync18(p, "utf-8")).version;
50096
+ if (existsSync21(p)) return JSON.parse(readFileSync19(p, "utf-8")).version;
49755
50097
  dir = dirname15(dir);
49756
50098
  }
49757
50099
  return "0.0.0";
@@ -49766,12 +50108,12 @@ function renderClaudePlugin() {
49766
50108
  return { manifest: pluginManifest(version), skill: loadSkill(), version };
49767
50109
  }
49768
50110
  function removeDirIfEmpty(dir) {
49769
- if (existsSync20(dir) && readdirSync6(dir).length === 0) rmdirSync(dir);
50111
+ if (existsSync21(dir) && readdirSync6(dir).length === 0) rmdirSync(dir);
49770
50112
  }
49771
50113
  function pluginPaths(dir) {
49772
50114
  return {
49773
- manifestPath: join25(dir, ".claude-plugin", "plugin.json"),
49774
- skillPath: join25(dir, "SKILL.md")
50115
+ manifestPath: join26(dir, ".claude-plugin", "plugin.json"),
50116
+ skillPath: join26(dir, "SKILL.md")
49775
50117
  };
49776
50118
  }
49777
50119
  function installClaudePlugin(cwd, opts) {
@@ -49779,8 +50121,8 @@ function installClaudePlugin(cwd, opts) {
49779
50121
  if (dir === null) return 1;
49780
50122
  const { manifestPath, skillPath } = pluginPaths(dir);
49781
50123
  const { manifest, skill } = renderClaudePlugin();
49782
- const manifestCurrent = existsSync20(manifestPath) ? readFileSync18(manifestPath, "utf-8") : null;
49783
- const skillCurrent = existsSync20(skillPath) ? readFileSync18(skillPath, "utf-8") : null;
50124
+ const manifestCurrent = existsSync21(manifestPath) ? readFileSync19(manifestPath, "utf-8") : null;
50125
+ const skillCurrent = existsSync21(skillPath) ? readFileSync19(skillPath, "utf-8") : null;
49784
50126
  if (manifestCurrent === manifest && skillCurrent === skill) {
49785
50127
  console.log("No changes \u2014 prim skill plugin already up to date.");
49786
50128
  return 0;
@@ -49789,7 +50131,7 @@ function installClaudePlugin(cwd, opts) {
49789
50131
  console.log(`Would write plugin to ${dir} (.claude-plugin/plugin.json + SKILL.md)`);
49790
50132
  return 0;
49791
50133
  }
49792
- mkdirSync14(join25(dir, ".claude-plugin"), { recursive: true });
50134
+ mkdirSync14(join26(dir, ".claude-plugin"), { recursive: true });
49793
50135
  atomicWrite4(manifestPath, manifest);
49794
50136
  atomicWrite4(skillPath, skill);
49795
50137
  console.log(`Installed prim skill plugin at ${dir}`);
@@ -49803,13 +50145,13 @@ function uninstallClaudePlugin(cwd, opts) {
49803
50145
  const dir = resolvePluginDir(cwd, opts.scope);
49804
50146
  if (dir === null) return 1;
49805
50147
  const { manifestPath, skillPath } = pluginPaths(dir);
49806
- if (!existsSync20(manifestPath) && !existsSync20(skillPath)) {
50148
+ if (!existsSync21(manifestPath) && !existsSync21(skillPath)) {
49807
50149
  console.log(`prim skill plugin not present at ${dir}`);
49808
50150
  return 0;
49809
50151
  }
49810
50152
  rmSync8(manifestPath, { force: true });
49811
50153
  rmSync8(skillPath, { force: true });
49812
- removeDirIfEmpty(join25(dir, ".claude-plugin"));
50154
+ removeDirIfEmpty(join26(dir, ".claude-plugin"));
49813
50155
  removeDirIfEmpty(dir);
49814
50156
  console.log(`Removed prim skill plugin from ${dir}`);
49815
50157
  return 0;
@@ -49818,7 +50160,7 @@ function statusClaudePlugin(cwd, opts) {
49818
50160
  const dir = resolvePluginDir(cwd, opts.scope);
49819
50161
  if (dir === null) return 1;
49820
50162
  const { skillPath } = pluginPaths(dir);
49821
- const installed = existsSync20(skillPath);
50163
+ const installed = existsSync21(skillPath);
49822
50164
  if (opts.json) {
49823
50165
  printJson({ installed, target: dir });
49824
50166
  return installed ? 0 : 1;
@@ -49853,11 +50195,109 @@ var AGENT_TARGET = {
49853
50195
  codex: "AGENTS.md",
49854
50196
  hermes: ".hermes.md"
49855
50197
  };
50198
+ var CURSOR_SKILL_OWNER = "@primitive.ai/prim";
50199
+ var CURSOR_SKILL_MANIFEST = ".prim-owned.json";
50200
+ function sha2563(content) {
50201
+ return createHash11("sha256").update(content).digest("hex");
50202
+ }
50203
+ function cursorSkillDirectory(cwd, scope) {
50204
+ const base = scope === "user" ? cursorConfigDirectory() : gitToplevel(cwd) ?? cwd;
50205
+ return join27(base, scope === "user" ? "skills" : ".cursor/skills", "prim");
50206
+ }
50207
+ function cursorSkillPaths(cwd, scope) {
50208
+ const directory = cursorSkillDirectory(cwd, scope);
50209
+ return {
50210
+ directory,
50211
+ skill: join27(directory, "SKILL.md"),
50212
+ manifest: join27(directory, CURSOR_SKILL_MANIFEST)
50213
+ };
50214
+ }
50215
+ function readCursorSkillManifest(path9) {
50216
+ try {
50217
+ const value = JSON.parse(readFileSync20(path9, "utf8"));
50218
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
50219
+ const record2 = value;
50220
+ if (record2.version !== 1 || record2.owner !== CURSOR_SKILL_OWNER || typeof record2.contentSha256 !== "string" || !/^[0-9a-f]{64}$/u.test(record2.contentSha256)) {
50221
+ return;
50222
+ }
50223
+ return record2;
50224
+ } catch {
50225
+ return;
50226
+ }
50227
+ }
50228
+ function cursorSkillStatus(cwd, scope) {
50229
+ const paths = cursorSkillPaths(cwd, scope);
50230
+ const manifest = readCursorSkillManifest(paths.manifest);
50231
+ const content = existsSync22(paths.skill) ? readFileSync20(paths.skill, "utf8") : void 0;
50232
+ const owned = manifest !== void 0;
50233
+ const installed = owned && content !== void 0 && sha2563(content) === manifest.contentSha256;
50234
+ return {
50235
+ installed,
50236
+ owned,
50237
+ edited: owned && content !== void 0 && !installed,
50238
+ target: paths.skill
50239
+ };
50240
+ }
50241
+ function validCursorSkillScope(scope) {
50242
+ if (scope === void 0 || scope === "project" || scope === "user") return true;
50243
+ console.error(`Unknown --scope "${scope}" (expected user or project)`);
50244
+ return false;
50245
+ }
50246
+ function installCursorSkill(cwd, opts) {
50247
+ const paths = cursorSkillPaths(cwd, opts.scope);
50248
+ const status = cursorSkillStatus(cwd, opts.scope);
50249
+ const manifestExists = existsSync22(paths.manifest);
50250
+ const skillExists = existsSync22(paths.skill);
50251
+ if (manifestExists && !status.owned || !manifestExists && skillExists || status.edited) {
50252
+ console.error(`Refusing to overwrite a foreign or edited Cursor skill at ${paths.skill}`);
50253
+ return 1;
50254
+ }
50255
+ const content = loadSkill();
50256
+ const manifest = {
50257
+ version: 1,
50258
+ owner: CURSOR_SKILL_OWNER,
50259
+ contentSha256: sha2563(content)
50260
+ };
50261
+ if (status.installed && readFileSync20(paths.skill, "utf8") === content) {
50262
+ console.log(`No changes \u2014 Cursor skill already up to date at ${paths.skill}`);
50263
+ return 0;
50264
+ }
50265
+ if (opts.dryRun) {
50266
+ const existing = skillExists ? readFileSync20(paths.skill, "utf8") : "";
50267
+ process.stdout.write(createPatch(paths.skill, existing, content, "current", "proposed"));
50268
+ return 0;
50269
+ }
50270
+ atomicWriteFile(paths.skill, content, { ensureParent: true });
50271
+ atomicWriteFile(paths.manifest, `${JSON.stringify(manifest, null, 2)}
50272
+ `, { ensureParent: true });
50273
+ console.log(`Installed Cursor skill at ${paths.skill}`);
50274
+ return 0;
50275
+ }
50276
+ function uninstallCursorSkill(cwd, scope) {
50277
+ const paths = cursorSkillPaths(cwd, scope);
50278
+ const status = cursorSkillStatus(cwd, scope);
50279
+ if (!status.owned) {
50280
+ console.log(`No Primitive-owned Cursor skill at ${paths.skill}`);
50281
+ return 0;
50282
+ }
50283
+ if (status.edited) {
50284
+ console.error(`Refusing to remove an edited Cursor skill at ${paths.skill}`);
50285
+ return 1;
50286
+ }
50287
+ if (existsSync22(paths.skill)) unlinkSync7(paths.skill);
50288
+ if (existsSync22(paths.manifest)) unlinkSync7(paths.manifest);
50289
+ try {
50290
+ if (readdirSync7(paths.directory).length === 0) rmdirSync2(paths.directory);
50291
+ } catch {
50292
+ }
50293
+ console.log(`Removed Primitive-owned Cursor skill from ${paths.skill}`);
50294
+ return 0;
50295
+ }
49856
50296
  function userTargetFor(agent) {
49857
- if (agent === "claude") return join26(homedir10(), ".claude", "CLAUDE.md");
49858
- if (agent === "codex") return join26(homedir10(), ".codex", "AGENTS.md");
50297
+ if (agent === "claude") return join27(homedir11(), ".claude", "CLAUDE.md");
50298
+ if (agent === "codex") return join27(homedir11(), ".codex", "AGENTS.md");
49859
50299
  if (agent === "hermes") {
49860
- return join26(process.env.HERMES_HOME ?? join26(homedir10(), ".hermes"), ".hermes.md");
50300
+ return join27(process.env.HERMES_HOME ?? join27(homedir11(), ".hermes"), ".hermes.md");
49861
50301
  }
49862
50302
  return null;
49863
50303
  }
@@ -49865,13 +50305,13 @@ function loadSkill() {
49865
50305
  let dir = __dirname5;
49866
50306
  while (dir !== dirname16(dir)) {
49867
50307
  const p = resolve8(dir, "SKILL.md");
49868
- if (existsSync21(p)) return readFileSync19(p, "utf-8");
50308
+ if (existsSync22(p)) return readFileSync20(p, "utf-8");
49869
50309
  dir = dirname16(dir);
49870
50310
  }
49871
50311
  throw new Error("SKILL.md not found in package");
49872
50312
  }
49873
50313
  function detectTargets(cwd) {
49874
- return TARGET_CANDIDATES.filter((p) => existsSync21(resolve8(cwd, p)));
50314
+ return TARGET_CANDIDATES.filter((p) => existsSync22(resolve8(cwd, p)));
49875
50315
  }
49876
50316
  function detectNewline(content) {
49877
50317
  return content.includes("\r\n") ? "\r\n" : "\n";
@@ -49908,18 +50348,18 @@ function resolveTarget(cwd, opts) {
49908
50348
  if (opts.target) return resolve8(cwd, opts.target);
49909
50349
  if (opts.scope === "user") {
49910
50350
  if (!opts.agent) {
49911
- console.error("--scope user requires --agent (claude, codex, or hermes)");
50351
+ console.error("--scope user requires --agent (claude, codex, cursor, or hermes)");
49912
50352
  return null;
49913
50353
  }
49914
50354
  const userTarget = userTargetFor(opts.agent);
49915
50355
  if (userTarget) return userTarget;
49916
- console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, or hermes)`);
50356
+ console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, cursor, or hermes)`);
49917
50357
  return null;
49918
50358
  }
49919
50359
  if (opts.agent) {
49920
50360
  const mapped = AGENT_TARGET[opts.agent];
49921
50361
  if (typeof mapped === "string") return resolve8(cwd, mapped);
49922
- console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, or hermes)`);
50362
+ console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, cursor, or hermes)`);
49923
50363
  return null;
49924
50364
  }
49925
50365
  const matches = detectTargets(cwd);
@@ -49931,9 +50371,13 @@ function resolveTarget(cwd, opts) {
49931
50371
  }
49932
50372
  function runInstall(cwd, opts) {
49933
50373
  if (opts.agent === "claude" && !opts.target) return installClaudePlugin(cwd, opts);
50374
+ if (opts.agent === "cursor" && !opts.target) {
50375
+ if (!validCursorSkillScope(opts.scope)) return 1;
50376
+ return installCursorSkill(cwd, opts);
50377
+ }
49934
50378
  const target = resolveTarget(cwd, opts);
49935
50379
  if (target === null) return 1;
49936
- const existing = existsSync21(target) ? readFileSync19(target, "utf-8") : "";
50380
+ const existing = existsSync22(target) ? readFileSync20(target, "utf-8") : "";
49937
50381
  const eol = existing ? detectNewline(existing) : "\n";
49938
50382
  const block = composeBlock(loadSkill(), eol);
49939
50383
  const next = applyBlock(existing, block, eol);
@@ -49951,13 +50395,17 @@ function runInstall(cwd, opts) {
49951
50395
  }
49952
50396
  function runUninstall(cwd, opts) {
49953
50397
  if (opts.agent === "claude" && !opts.target) return uninstallClaudePlugin(cwd, opts);
50398
+ if (opts.agent === "cursor" && !opts.target) {
50399
+ if (!validCursorSkillScope(opts.scope)) return 1;
50400
+ return uninstallCursorSkill(cwd, opts.scope);
50401
+ }
49954
50402
  const target = resolveTarget(cwd, opts);
49955
50403
  if (target === null) return 1;
49956
- if (!existsSync21(target)) {
50404
+ if (!existsSync22(target)) {
49957
50405
  console.log(`Skill block not present at ${target}`);
49958
50406
  return 0;
49959
50407
  }
49960
- const existing = readFileSync19(target, "utf-8");
50408
+ const existing = readFileSync20(target, "utf-8");
49961
50409
  const next = removeBlock(existing);
49962
50410
  if (next === null) {
49963
50411
  console.log(`Skill block not present at ${target}`);
@@ -49969,12 +50417,22 @@ function runUninstall(cwd, opts) {
49969
50417
  }
49970
50418
  function runStatus(cwd, opts) {
49971
50419
  if (opts.agent === "claude" && !opts.target) return statusClaudePlugin(cwd, opts);
50420
+ if (opts.agent === "cursor" && !opts.target) {
50421
+ if (!validCursorSkillScope(opts.scope)) return 1;
50422
+ const status = cursorSkillStatus(cwd, opts.scope);
50423
+ if (opts.json) printJson(status);
50424
+ else
50425
+ console.log(
50426
+ status.installed ? `Primitive Cursor skill installed at ${status.target}` : `No intact Primitive-owned Cursor skill at ${status.target}`
50427
+ );
50428
+ return status.installed ? 0 : 1;
50429
+ }
49972
50430
  const target = resolveTarget(cwd, opts);
49973
50431
  if (target === null) return 1;
49974
- const fileExists = existsSync21(target);
50432
+ const fileExists = existsSync22(target);
49975
50433
  let installed = false;
49976
50434
  if (fileExists) {
49977
- const content = readFileSync19(target, "utf-8");
50435
+ const content = readFileSync20(target, "utf-8");
49978
50436
  installed = content.includes(SKILL_BEGIN) && content.includes(SKILL_END);
49979
50437
  }
49980
50438
  if (opts.json) {
@@ -49994,7 +50452,7 @@ function runStatus(cwd, opts) {
49994
50452
  }
49995
50453
  function registerSkillCommands(program3) {
49996
50454
  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) => {
50455
+ 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
50456
  try {
49999
50457
  process.exit(runInstall(process.cwd(), opts));
50000
50458
  } catch (err) {
@@ -50002,16 +50460,16 @@ function registerSkillCommands(program3) {
50002
50460
  process.exit(2);
50003
50461
  }
50004
50462
  });
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) => {
50463
+ 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
50464
  process.exit(runUninstall(process.cwd(), opts));
50007
50465
  });
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) => {
50466
+ 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
50467
  process.exit(runStatus(process.cwd(), opts));
50010
50468
  });
50011
50469
  }
50012
50470
 
50013
50471
  // src/commands/statusline.ts
50014
- import { readFileSync as readFileSync20 } from "fs";
50472
+ import { readFileSync as readFileSync21 } from "fs";
50015
50473
  import { dirname as dirname17, resolve as resolve9 } from "path";
50016
50474
  import { fileURLToPath as fileURLToPath6 } from "url";
50017
50475
  var STATUSLINE_TIMEOUT_MS = 200;
@@ -50027,7 +50485,7 @@ function readPackageVersion() {
50027
50485
  ];
50028
50486
  for (const path9 of candidates) {
50029
50487
  try {
50030
- const pkg2 = JSON.parse(readFileSync20(path9, "utf-8"));
50488
+ const pkg2 = JSON.parse(readFileSync21(path9, "utf-8"));
50031
50489
  if (pkg2.version) {
50032
50490
  return pkg2.version;
50033
50491
  }
@@ -50044,9 +50502,8 @@ function debug(msg) {
50044
50502
  `);
50045
50503
  }
50046
50504
  }
50047
- async function renderStatusline() {
50505
+ async function renderStatusline(cwd = process.cwd()) {
50048
50506
  const version = readPackageVersion();
50049
- const cwd = process.cwd();
50050
50507
  let ingestion;
50051
50508
  const resolveIngestion = () => {
50052
50509
  ingestion ??= decisionIngestionStatus(cwd);
@@ -50094,6 +50551,11 @@ function planUninstallSteps(inRepository) {
50094
50551
  label: "Codex project integration",
50095
50552
  args: ["codex", "uninstall", "--scope", "project"]
50096
50553
  },
50554
+ {
50555
+ key: "cursor-project",
50556
+ label: "Cursor project integration",
50557
+ args: ["cursor", "uninstall", "--scope", "project"]
50558
+ },
50097
50559
  {
50098
50560
  key: "hooks-project",
50099
50561
  label: "project Git hooks",
@@ -50113,6 +50575,11 @@ function planUninstallSteps(inRepository) {
50113
50575
  label: "Codex user integration",
50114
50576
  args: ["codex", "uninstall", "--scope", "user"]
50115
50577
  },
50578
+ {
50579
+ key: "cursor-user",
50580
+ label: "Cursor user integration",
50581
+ args: ["cursor", "uninstall", "--scope", "user"]
50582
+ },
50116
50583
  { key: "hermes-user", label: "Hermes integration", args: ["hermes", "uninstall"] },
50117
50584
  {
50118
50585
  key: "hooks-user",
@@ -50131,7 +50598,7 @@ function uninstallStepSucceeded(step, result) {
50131
50598
  return false;
50132
50599
  }
50133
50600
  }
50134
- if (!step.key.startsWith("claude-") && !step.key.startsWith("codex-") && step.key !== "hermes-user") {
50601
+ if (!step.key.startsWith("claude-") && !step.key.startsWith("codex-") && !step.key.startsWith("cursor-") && step.key !== "hermes-user") {
50135
50602
  return true;
50136
50603
  }
50137
50604
  try {
@@ -50139,7 +50606,7 @@ function uninstallStepSucceeded(step, result) {
50139
50606
  if (step.key.startsWith("claude-")) {
50140
50607
  return parsed.gate === false && parsed.capture === false && parsed.feedback === false && parsed.statusline === false;
50141
50608
  }
50142
- return parsed.gate === false && parsed.capture === false;
50609
+ return parsed.gate === false && parsed.capture === false && (!step.key.startsWith("cursor-user") || parsed.footer === false);
50143
50610
  } catch {
50144
50611
  return false;
50145
50612
  }
@@ -50254,9 +50721,9 @@ function registerUninstallCommand(program3, dependencies = {}) {
50254
50721
  note(`uninstall \xB7 runtime removal incomplete (unknown state): ${detail}`);
50255
50722
  }
50256
50723
  }
50257
- const complete = failed.length === 0;
50724
+ const complete2 = failed.length === 0;
50258
50725
  const result = {
50259
- uninstalled: complete,
50726
+ uninstalled: complete2,
50260
50727
  projectScopeChecked: inRepository,
50261
50728
  steps: results,
50262
50729
  runtime,
@@ -50270,16 +50737,16 @@ function registerUninstallCommand(program3, dependencies = {}) {
50270
50737
  write(`${JSON.stringify(result, null, 2)}
50271
50738
  `);
50272
50739
  note(
50273
- complete ? "uninstall complete \xB7 credentials and pending journals preserved" : `uninstall incomplete \xB7 failed: ${failed.join(", ")}`
50740
+ complete2 ? "uninstall complete \xB7 credentials and pending journals preserved" : `uninstall incomplete \xB7 failed: ${failed.join(", ")}`
50274
50741
  );
50275
- exit(complete ? 0 : EXIT_INCOMPLETE2);
50742
+ exit(complete2 ? 0 : EXIT_INCOMPLETE2);
50276
50743
  });
50277
50744
  }
50278
50745
 
50279
50746
  // src/commands/welcome.ts
50280
50747
  var CMD_GUTTER = 38;
50281
50748
  var RECENT_LIMIT = 5;
50282
- var WELCOME_AGENTS = ["claude", "codex", "hermes"];
50749
+ var WELCOME_AGENTS = ["claude", "codex", "cursor", "hermes"];
50283
50750
  function resolveWelcomeAgent(agentFlag, env4) {
50284
50751
  if (agentFlag !== void 0 && WELCOME_AGENTS.includes(agentFlag)) {
50285
50752
  return agentFlag;
@@ -50287,6 +50754,9 @@ function resolveWelcomeAgent(agentFlag, env4) {
50287
50754
  if (agentFlag === void 0 && env4.HERMES_INTERACTIVE) {
50288
50755
  return "hermes";
50289
50756
  }
50757
+ if (agentFlag === void 0 && env4.CURSOR_AGENT) {
50758
+ return "cursor";
50759
+ }
50290
50760
  return void 0;
50291
50761
  }
50292
50762
  var CAPTURE_LINES = {
@@ -50295,6 +50765,7 @@ var CAPTURE_LINES = {
50295
50765
  "Capture starts once you trust the prim hooks \u2014 run /hooks in Codex;",
50296
50766
  "until then nothing is recorded."
50297
50767
  ],
50768
+ cursor: ["Capture is automatic in trusted Cursor workspaces; restart Cursor CLI for the footer."],
50298
50769
  hermes: [
50299
50770
  "Capture starts once you approve the prim hooks when Hermes prompts;",
50300
50771
  "until then nothing is recorded."
@@ -50310,6 +50781,7 @@ var PASSIVE_LINES = {
50310
50781
  "Once you trust the prim hooks (/hooks in Codex), Primitive captures",
50311
50782
  "decisions passively while you work."
50312
50783
  ],
50784
+ cursor: ["In trusted Cursor workspaces, Primitive captures decisions passively while you work."],
50313
50785
  hermes: [
50314
50786
  "Once you approve the prim hooks, Primitive captures decisions",
50315
50787
  "passively while you work."
@@ -50322,6 +50794,7 @@ var PASSIVE_LINES = {
50322
50794
  var GUIDANCE_PASSIVE = {
50323
50795
  claude: "Otherwise, Primitive passively captures decisions in the background while you work.",
50324
50796
  codex: "Otherwise, once you trust the prim hooks (run /hooks in Codex), Primitive passively captures decisions in the background while you work.",
50797
+ cursor: "Otherwise, Primitive passively captures decisions in trusted Cursor workspaces while you work.",
50325
50798
  hermes: "Otherwise, once you approve the prim hooks when Hermes prompts, Primitive passively captures decisions in the background while you work.",
50326
50799
  generic: "Otherwise, once your agent's prim hooks are active, Primitive passively captures decisions in the background while you work."
50327
50800
  };
@@ -50416,10 +50889,7 @@ function welcomeJson(state, agent) {
50416
50889
  return { welcomed: true, org: "unknown" };
50417
50890
  }
50418
50891
  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) => {
50892
+ 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
50893
  const agent = resolveWelcomeAgent(options.agent, process.env);
50424
50894
  const result = await fetchRecent({ limit: RECENT_LIMIT }, deps);
50425
50895
  const state = welcomeStateFromRecent(result);
@@ -50447,7 +50917,7 @@ function runStartupBackgroundWork(argv, env4, work) {
50447
50917
 
50448
50918
  // src/index.ts
50449
50919
  var __dirname6 = dirname18(fileURLToPath7(import.meta.url));
50450
- var pkg = JSON.parse(readFileSync21(resolve10(__dirname6, "../package.json"), "utf-8"));
50920
+ var pkg = JSON.parse(readFileSync22(resolve10(__dirname6, "../package.json"), "utf-8"));
50451
50921
  runStartupBackgroundWork(process.argv.slice(2), process.env, {
50452
50922
  notify: () => updateNotifier({ pkg }).notify(),
50453
50923
  flush: () => flushIfNeeded()
@@ -50466,6 +50936,7 @@ registerSessionCommands(program2);
50466
50936
  registerDecisionsCommands(program2);
50467
50937
  registerClaudeCommands(program2);
50468
50938
  registerCodexCommands(program2);
50939
+ registerCursorCommands(program2);
50469
50940
  registerHermesCommands(program2);
50470
50941
  registerDaemonCommands(program2);
50471
50942
  registerGithubCommands(program2);