safeword 0.56.0 → 0.57.0
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.
- package/dist/{check-OD4QHC2P.js → check-IV6KC65F.js} +10 -4
- package/dist/check-IV6KC65F.js.map +1 -0
- package/dist/{chunk-64TSNY2M.js → chunk-D5H7VBXQ.js} +2 -2
- package/dist/{chunk-RQBSXETC.js → chunk-HGOG5ZLC.js} +75 -7
- package/dist/chunk-HGOG5ZLC.js.map +1 -0
- package/dist/{chunk-EUSXT3MN.js → chunk-HTDMZQKA.js} +37 -6
- package/dist/chunk-HTDMZQKA.js.map +1 -0
- package/dist/{chunk-VLK2DXJ7.js → chunk-MT4WBU2P.js} +76 -43
- package/dist/chunk-MT4WBU2P.js.map +1 -0
- package/dist/{chunk-FZVYR37T.js → chunk-O3QF6QHX.js} +3 -3
- package/dist/chunk-ZESHX2BU.js +14 -0
- package/dist/chunk-ZESHX2BU.js.map +1 -0
- package/dist/cli.js +7 -7
- package/dist/{diff-L7DED7WY.js → diff-55Y2SH4U.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/presets/typescript/index.d.ts +0 -42
- package/dist/presets/typescript/index.js +1 -1
- package/dist/{reset-LE6GYEYU.js → reset-FZRYTUFF.js} +2 -2
- package/dist/{setup-ZJCYBXA6.js → setup-WKFBBSLJ.js} +5 -5
- package/dist/{sync-tickets-53DTTY7B.js → sync-tickets-35ZSEKIE.js} +8 -2
- package/dist/sync-tickets-35ZSEKIE.js.map +1 -0
- package/dist/{sync-tracker-MP6BTZXX.js → sync-tracker-YUXD7QKS.js} +144 -11
- package/dist/sync-tracker-YUXD7QKS.js.map +1 -0
- package/dist/{upgrade-7JTIBI3I.js → upgrade-MCBH6GTD.js} +5 -5
- package/package.json +4 -4
- package/templates/commands/audit.md +3 -3
- package/templates/commands/refactor.md +1 -1
- package/templates/commands/self-review.md +1 -1
- package/templates/commands/verify.md +3 -3
- package/templates/cursor/rules/safeword-refactoring.mdc +1 -1
- package/templates/hooks/codex/pre-tool-quality.ts +11 -2
- package/templates/hooks/cursor/after-file-edit.ts +5 -2
- package/templates/hooks/cursor/before-shell-execution.ts +55 -0
- package/templates/hooks/cursor/gate-adapter.ts +208 -0
- package/templates/hooks/cursor/post-tool-quality.ts +70 -0
- package/templates/hooks/cursor/pre-tool-quality.ts +101 -0
- package/templates/hooks/cursor/stop.ts +5 -2
- package/templates/hooks/lib/active-ticket.ts +166 -0
- package/templates/hooks/lib/done-gate.ts +172 -0
- package/templates/hooks/lib/quality-state.ts +63 -11
- package/templates/hooks/lib/run-identity.ts +150 -0
- package/templates/hooks/pre-tool-quality.ts +49 -1
- package/templates/hooks/prompt-questions.ts +13 -1
- package/templates/hooks/record-skill-invocation.ts +22 -15
- package/templates/hooks/stop-quality.ts +1 -28
- package/templates/hooks/write-review-stamp.ts +4 -2
- package/templates/skills/audit/SKILL.md +3 -3
- package/templates/skills/quality-review/SKILL.md +3 -3
- package/templates/skills/refactor/SKILL.md +34 -11
- package/templates/skills/self-review/SKILL.md +1 -1
- package/templates/skills/verify/SKILL.md +3 -3
- package/dist/check-OD4QHC2P.js.map +0 -1
- package/dist/chunk-EUSXT3MN.js.map +0 -1
- package/dist/chunk-RQBSXETC.js.map +0 -1
- package/dist/chunk-VLK2DXJ7.js.map +0 -1
- package/dist/sync-tickets-53DTTY7B.js.map +0 -1
- package/dist/sync-tracker-MP6BTZXX.js.map +0 -1
- /package/dist/{chunk-64TSNY2M.js.map → chunk-D5H7VBXQ.js.map} +0 -0
- /package/dist/{chunk-FZVYR37T.js.map → chunk-O3QF6QHX.js.map} +0 -0
- /package/dist/{diff-L7DED7WY.js.map → diff-55Y2SH4U.js.map} +0 -0
- /package/dist/{reset-LE6GYEYU.js.map → reset-FZRYTUFF.js.map} +0 -0
- /package/dist/{setup-ZJCYBXA6.js.map → setup-WKFBBSLJ.js.map} +0 -0
- /package/dist/{upgrade-7JTIBI3I.js.map → upgrade-MCBH6GTD.js.map} +0 -0
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildIndexConflictListMessage
|
|
3
|
+
} from "./chunk-ZESHX2BU.js";
|
|
1
4
|
import {
|
|
2
5
|
isNewerVersion
|
|
3
6
|
} from "./chunk-FJYRWU2V.js";
|
|
4
7
|
import {
|
|
5
8
|
checkHealth,
|
|
6
9
|
reportHealthSummary
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-O3QF6QHX.js";
|
|
8
11
|
import "./chunk-YXNI7W5D.js";
|
|
9
12
|
import "./chunk-XTLCJKGE.js";
|
|
10
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-HGOG5ZLC.js";
|
|
11
14
|
import "./chunk-GS3TBFXU.js";
|
|
12
15
|
import {
|
|
13
16
|
syncTickets
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-HTDMZQKA.js";
|
|
15
18
|
import "./chunk-NHXVS5FL.js";
|
|
16
19
|
import "./chunk-P2IC575P.js";
|
|
17
20
|
import "./chunk-PHR2K2Y3.js";
|
|
@@ -79,6 +82,9 @@ function regenerateTicketIndex(cwd) {
|
|
|
79
82
|
if (result.wrote) {
|
|
80
83
|
info("Regenerated ticket index (INDEX.md / INDEX-completed.md)");
|
|
81
84
|
}
|
|
85
|
+
if (result.indexConflicts.length > 0) {
|
|
86
|
+
warn(buildIndexConflictListMessage(result.indexConflicts));
|
|
87
|
+
}
|
|
82
88
|
} catch (error) {
|
|
83
89
|
if (process.env.DEBUG) {
|
|
84
90
|
console.error("[check] ticket index regen failed:", error);
|
|
@@ -111,4 +117,4 @@ async function check(options) {
|
|
|
111
117
|
export {
|
|
112
118
|
check
|
|
113
119
|
};
|
|
114
|
-
//# sourceMappingURL=check-
|
|
120
|
+
//# sourceMappingURL=check-IV6KC65F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/check.ts"],"sourcesContent":["/**\n * Check command - Verify project health and configuration\n *\n * The config-health core lives in ../health.ts (shared with the setup/upgrade\n * self-verify, ticket 3293WH). This command adds the standalone-only\n * surfaces: npm update-check, version display, and ticket-index refresh.\n */\n\nimport process from 'node:process';\n\nimport { checkHealth, type HealthStatus, reportHealthSummary } from '../health.js';\nimport { syncTickets } from '../ticket-sync/index.js';\nimport { header, info, keyValue, success, warn } from '../utils/output.js';\nimport { buildIndexConflictListMessage } from '../utils/ticket-index-warnings.js';\nimport { isNewerVersion } from '../utils/version.js';\n\ninterface CheckOptions {\n offline?: boolean;\n}\n\n/**\n * Check for latest version from npm (with timeout)\n * @param timeout\n */\nasync function checkLatestVersion(timeout = 3000): Promise<string | undefined> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, timeout);\n\n const response = await fetch('https://registry.npmjs.org/safeword/latest', {\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) return undefined;\n\n const data = (await response.json()) as { version?: string };\n return data.version ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Check for CLI updates and report status\n * @param health\n */\nasync function reportUpdateStatus(health: HealthStatus): Promise<void> {\n info('\\nChecking for updates...');\n const latestVersion = await checkLatestVersion();\n\n if (!latestVersion) {\n warn(\"Couldn't check for updates (offline?)\");\n return;\n }\n\n health.latestVersion = latestVersion;\n health.updateAvailable = isNewerVersion(health.cliVersion, latestVersion);\n\n if (health.updateAvailable) {\n warn(`Update available: v${latestVersion}`);\n info('Run `bunx safeword@latest upgrade` to upgrade');\n } else {\n success('CLI is up to date');\n }\n}\n\n/**\n * Compare project version vs CLI version and report\n * @param health\n */\nfunction reportVersionMismatch(health: HealthStatus): void {\n if (!health.projectVersion) return;\n\n if (isNewerVersion(health.cliVersion, health.projectVersion)) {\n warn(`Project config (v${health.projectVersion}) is newer than CLI (v${health.cliVersion})`);\n info('Consider upgrading the CLI');\n } else if (isNewerVersion(health.projectVersion, health.cliVersion)) {\n info(`\\nUpgrade available for project config`);\n info(\n `Run \\`safeword upgrade\\` to update from v${health.projectVersion} to v${health.cliVersion}`,\n );\n }\n}\n\n/**\n * Regenerate the ticket discovery index, swallowing any error — index\n * freshness must never block or fail a health check. Reports only when it\n * actually rewrote a file.\n * @param cwd\n */\nfunction regenerateTicketIndex(cwd: string): void {\n try {\n const result = syncTickets(cwd);\n if (result.wrote) {\n info('Regenerated ticket index (INDEX.md / INDEX-completed.md)');\n }\n if (result.indexConflicts.length > 0) {\n warn(buildIndexConflictListMessage(result.indexConflicts));\n }\n } catch (error: unknown) {\n // Best-effort: index freshness must never fail the health check. Surface\n // under DEBUG, then return — the deliberate swallow point.\n if (process.env.DEBUG) {\n console.error('[check] ticket index regen failed:', error);\n }\n return;\n }\n}\n\n/**\n *\n * @param options\n */\nexport async function check(options: CheckOptions): Promise<void> {\n const cwd = process.cwd();\n\n header('Safeword Health Check');\n\n const health = await checkHealth(cwd);\n\n // Not configured\n if (!health.configured) {\n info('Not configured. Run `safeword setup` to initialize.');\n return;\n }\n\n // Keep the ticket discovery index fresh at this checkpoint (best-effort —\n // never fail the health check on index regen). Ticket 1GGD28.\n regenerateTicketIndex(cwd);\n\n // Show versions\n keyValue('Safeword CLI', `v${health.cliVersion}`);\n keyValue('Project config', health.projectVersion ? `v${health.projectVersion}` : 'unknown');\n\n // Check for updates (unless offline)\n if (options.offline) {\n info('\\nSkipped update check (offline mode)');\n } else {\n await reportUpdateStatus(health);\n }\n\n reportVersionMismatch(health);\n const hasIssues = reportHealthSummary(health);\n\n if (hasIssues) {\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,OAAO,aAAa;AAgBpB,eAAe,mBAAmB,UAAU,KAAmC;AAC7E,MAAI;AACF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM;AACjC,iBAAW,MAAM;AAAA,IACnB,GAAG,OAAO;AAEV,UAAM,WAAW,MAAM,MAAM,8CAA8C;AAAA,MACzE,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,iBAAa,SAAS;AAEtB,QAAI,CAAC,SAAS,GAAI,QAAO;AAEzB,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,WAAO,KAAK,WAAW;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAe,mBAAmB,QAAqC;AACrE,OAAK,2BAA2B;AAChC,QAAM,gBAAgB,MAAM,mBAAmB;AAE/C,MAAI,CAAC,eAAe;AAClB,SAAK,uCAAuC;AAC5C;AAAA,EACF;AAEA,SAAO,gBAAgB;AACvB,SAAO,kBAAkB,eAAe,OAAO,YAAY,aAAa;AAExE,MAAI,OAAO,iBAAiB;AAC1B,SAAK,sBAAsB,aAAa,EAAE;AAC1C,SAAK,+CAA+C;AAAA,EACtD,OAAO;AACL,YAAQ,mBAAmB;AAAA,EAC7B;AACF;AAMA,SAAS,sBAAsB,QAA4B;AACzD,MAAI,CAAC,OAAO,eAAgB;AAE5B,MAAI,eAAe,OAAO,YAAY,OAAO,cAAc,GAAG;AAC5D,SAAK,oBAAoB,OAAO,cAAc,yBAAyB,OAAO,UAAU,GAAG;AAC3F,SAAK,4BAA4B;AAAA,EACnC,WAAW,eAAe,OAAO,gBAAgB,OAAO,UAAU,GAAG;AACnE,SAAK;AAAA,qCAAwC;AAC7C;AAAA,MACE,4CAA4C,OAAO,cAAc,QAAQ,OAAO,UAAU;AAAA,IAC5F;AAAA,EACF;AACF;AAQA,SAAS,sBAAsB,KAAmB;AAChD,MAAI;AACF,UAAM,SAAS,YAAY,GAAG;AAC9B,QAAI,OAAO,OAAO;AAChB,WAAK,0DAA0D;AAAA,IACjE;AACA,QAAI,OAAO,eAAe,SAAS,GAAG;AACpC,WAAK,8BAA8B,OAAO,cAAc,CAAC;AAAA,IAC3D;AAAA,EACF,SAAS,OAAgB;AAGvB,QAAI,QAAQ,IAAI,OAAO;AACrB,cAAQ,MAAM,sCAAsC,KAAK;AAAA,IAC3D;AACA;AAAA,EACF;AACF;AAMA,eAAsB,MAAM,SAAsC;AAChE,QAAM,MAAM,QAAQ,IAAI;AAExB,SAAO,uBAAuB;AAE9B,QAAM,SAAS,MAAM,YAAY,GAAG;AAGpC,MAAI,CAAC,OAAO,YAAY;AACtB,SAAK,qDAAqD;AAC1D;AAAA,EACF;AAIA,wBAAsB,GAAG;AAGzB,WAAS,gBAAgB,IAAI,OAAO,UAAU,EAAE;AAChD,WAAS,kBAAkB,OAAO,iBAAiB,IAAI,OAAO,cAAc,KAAK,SAAS;AAG1F,MAAI,QAAQ,SAAS;AACnB,SAAK,uCAAuC;AAAA,EAC9C,OAAO;AACL,UAAM,mBAAmB,MAAM;AAAA,EACjC;AAEA,wBAAsB,MAAM;AAC5B,QAAM,YAAY,oBAAoB,MAAM;AAE5C,MAAI,WAAW;AACb,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
addInstalledPack,
|
|
4
4
|
isGitRepo,
|
|
5
5
|
isPackInstalled
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HGOG5ZLC.js";
|
|
7
7
|
import {
|
|
8
8
|
SAFEWORD_PEER_DEPENDENCIES
|
|
9
9
|
} from "./chunk-HSC7TELY.js";
|
|
@@ -392,4 +392,4 @@ export {
|
|
|
392
392
|
getEslintPeerMismatchWarning,
|
|
393
393
|
maybeAutoPatchOrNudge
|
|
394
394
|
};
|
|
395
|
-
//# sourceMappingURL=chunk-
|
|
395
|
+
//# sourceMappingURL=chunk-D5H7VBXQ.js.map
|
|
@@ -2149,9 +2149,54 @@ ${prettier.configEntry}
|
|
|
2149
2149
|
`;
|
|
2150
2150
|
}
|
|
2151
2151
|
var CURSOR_HOOKS = {
|
|
2152
|
+
// Observational: injects standing context. Fail-open — a failed inject must not
|
|
2153
|
+
// block the session from starting.
|
|
2152
2154
|
sessionStart: [{ command: "bun ./.safeword/hooks/session-safeword-context.ts --agent=cursor" }],
|
|
2155
|
+
// NOTE (F2TKR3): there is deliberately NO beforeSubmitPrompt gate. That hook
|
|
2156
|
+
// fires at prompt-send time, where Cursor exposes only the prompt text — no tool
|
|
2157
|
+
// name or file path — so it cannot tell "create test-definitions.md" from "write
|
|
2158
|
+
// application code". A block there is a catch-22: it would stop the very prompt
|
|
2159
|
+
// that asks the agent to create the scenarios. The phase gate lives at the edit
|
|
2160
|
+
// layer below (preToolUse), which is path-aware (META_PATHS lets scenario/meta
|
|
2161
|
+
// files through) and session-bound — exact parity with the Claude side.
|
|
2162
|
+
//
|
|
2163
|
+
// Blocking edit gate. Matcher limits it to the `Write` tool (Cursor's only edit
|
|
2164
|
+
// tool) so it never spawns on Read/Grep/Task. Denies edits when a feature at the
|
|
2165
|
+
// implement phase has no test-definitions.md, and on LOC blast-radius overflow.
|
|
2166
|
+
//
|
|
2167
|
+
// Done gate (AKNWZK): this same hook also enforces the done gate. Cursor's `stop`
|
|
2168
|
+
// cannot block, so closing a ticket is gated here — a Write that flips ticket.md to
|
|
2169
|
+
// `status: done` is denied unless the evidence holds (tests green, verify.md in
|
|
2170
|
+
// scope, scenarios complete). That makes done the only edit that runs the test
|
|
2171
|
+
// suite, so the timeout is raised to cover a full run (the suite self-caps at 60s).
|
|
2172
|
+
preToolUse: [
|
|
2173
|
+
{
|
|
2174
|
+
command: "bun ./.safeword/hooks/cursor/pre-tool-quality.ts",
|
|
2175
|
+
matcher: "Write",
|
|
2176
|
+
failClosed: true,
|
|
2177
|
+
timeout: 90
|
|
2178
|
+
}
|
|
2179
|
+
],
|
|
2180
|
+
// Blocking commit gate (a REFACTOR commit may not touch test files).
|
|
2181
|
+
beforeShellExecution: [
|
|
2182
|
+
{ command: "bun ./.safeword/hooks/cursor/before-shell-execution.ts", failClosed: true }
|
|
2183
|
+
],
|
|
2184
|
+
// Observational: triggers lint on edited files. Fail-open — a lint crash must
|
|
2185
|
+
// not block the edit.
|
|
2153
2186
|
afterFileEdit: [{ command: "bun ./.safeword/hooks/cursor/after-file-edit.ts" }],
|
|
2154
|
-
|
|
2187
|
+
// Observational: maintains the per-session quality state (LOC, commit-clears-gate,
|
|
2188
|
+
// ticket binding) the blocking edit gate reads. Matched to edits + shell only.
|
|
2189
|
+
// Fail-open — if it crashes the gate simply lacks fuel and degrades to allow,
|
|
2190
|
+
// which must never block work.
|
|
2191
|
+
postToolUse: [
|
|
2192
|
+
{ command: "bun ./.safeword/hooks/cursor/post-tool-quality.ts", matcher: "Write|Shell" }
|
|
2193
|
+
],
|
|
2194
|
+
// Observational: nudges a quality review. Cursor `stop` cannot block anyway —
|
|
2195
|
+
// the real done enforcement lives in preToolUse (above). loop_limit:1 is
|
|
2196
|
+
// intentional: this is a one-shot reminder (the hook clears its edit marker after
|
|
2197
|
+
// firing), NOT a drive-to-done loop, so a single auto-continue is enough and a
|
|
2198
|
+
// higher cap would just re-nudge noisily.
|
|
2199
|
+
stop: [{ command: "bun ./.safeword/hooks/cursor/stop.ts", loop_limit: 1 }]
|
|
2155
2200
|
};
|
|
2156
2201
|
var HOOKS_DIR = '"$CLAUDE_PROJECT_DIR"/.safeword/hooks';
|
|
2157
2202
|
function hook(command) {
|
|
@@ -2932,9 +2977,11 @@ var SAFEWORD_SCHEMA = {
|
|
|
2932
2977
|
".safeword/hooks/lib/lint.ts": { template: "hooks/lib/lint.ts" },
|
|
2933
2978
|
".safeword/hooks/lib/quality.ts": { template: "hooks/lib/quality.ts" },
|
|
2934
2979
|
".safeword/hooks/lib/quality-state.ts": { template: "hooks/lib/quality-state.ts" },
|
|
2980
|
+
".safeword/hooks/lib/run-identity.ts": { template: "hooks/lib/run-identity.ts" },
|
|
2935
2981
|
".safeword/hooks/lib/dependency-readiness.ts": {
|
|
2936
2982
|
template: "hooks/lib/dependency-readiness.ts"
|
|
2937
2983
|
},
|
|
2984
|
+
".safeword/hooks/lib/done-gate.ts": { template: "hooks/lib/done-gate.ts" },
|
|
2938
2985
|
".safeword/hooks/lib/namespace-root.ts": { template: "hooks/lib/namespace-root.ts" },
|
|
2939
2986
|
".safeword/hooks/lib/skill-invocation-log.ts": {
|
|
2940
2987
|
template: "hooks/lib/skill-invocation-log.ts"
|
|
@@ -3261,6 +3308,18 @@ var SAFEWORD_SCHEMA = {
|
|
|
3261
3308
|
".safeword/hooks/cursor/after-file-edit.ts": {
|
|
3262
3309
|
template: "hooks/cursor/after-file-edit.ts"
|
|
3263
3310
|
},
|
|
3311
|
+
".safeword/hooks/cursor/gate-adapter.ts": {
|
|
3312
|
+
template: "hooks/cursor/gate-adapter.ts"
|
|
3313
|
+
},
|
|
3314
|
+
".safeword/hooks/cursor/pre-tool-quality.ts": {
|
|
3315
|
+
template: "hooks/cursor/pre-tool-quality.ts"
|
|
3316
|
+
},
|
|
3317
|
+
".safeword/hooks/cursor/before-shell-execution.ts": {
|
|
3318
|
+
template: "hooks/cursor/before-shell-execution.ts"
|
|
3319
|
+
},
|
|
3320
|
+
".safeword/hooks/cursor/post-tool-quality.ts": {
|
|
3321
|
+
template: "hooks/cursor/post-tool-quality.ts"
|
|
3322
|
+
},
|
|
3264
3323
|
".safeword/hooks/cursor/stop.ts": { template: "hooks/cursor/stop.ts" }
|
|
3265
3324
|
},
|
|
3266
3325
|
// Files created if missing, updated only if content matches current template
|
|
@@ -3349,7 +3408,15 @@ var SAFEWORD_SCHEMA = {
|
|
|
3349
3408
|
// form is `.jsonc`; yaml/cjs/mjs variants fall back to manual wiring.
|
|
3350
3409
|
".markdownlint-cli2.jsonc": MARKDOWNLINT_CLI2_IGNORES_MERGE,
|
|
3351
3410
|
".cursor/hooks.json": {
|
|
3352
|
-
keys: [
|
|
3411
|
+
keys: [
|
|
3412
|
+
"version",
|
|
3413
|
+
"hooks.sessionStart",
|
|
3414
|
+
"hooks.preToolUse",
|
|
3415
|
+
"hooks.beforeShellExecution",
|
|
3416
|
+
"hooks.afterFileEdit",
|
|
3417
|
+
"hooks.postToolUse",
|
|
3418
|
+
"hooks.stop"
|
|
3419
|
+
],
|
|
3353
3420
|
removeFileIfEmpty: true,
|
|
3354
3421
|
merge: (existing) => {
|
|
3355
3422
|
const hooks = existing.hooks ?? {};
|
|
@@ -3365,10 +3432,11 @@ var SAFEWORD_SCHEMA = {
|
|
|
3365
3432
|
},
|
|
3366
3433
|
unmerge: (existing) => {
|
|
3367
3434
|
const result = { ...existing };
|
|
3368
|
-
const
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3435
|
+
const existingHooks = existing.hooks ?? {};
|
|
3436
|
+
const safewordHookNames = new Set(Object.keys(CURSOR_HOOKS));
|
|
3437
|
+
const hooks = Object.fromEntries(
|
|
3438
|
+
Object.entries(existingHooks).filter(([name]) => !safewordHookNames.has(name))
|
|
3439
|
+
);
|
|
3372
3440
|
if (!assignOrPrune(result, "hooks", hooks)) {
|
|
3373
3441
|
delete result.version;
|
|
3374
3442
|
}
|
|
@@ -3778,4 +3846,4 @@ export {
|
|
|
3778
3846
|
untrackIgnoredFiles,
|
|
3779
3847
|
createProjectContext
|
|
3780
3848
|
};
|
|
3781
|
-
//# sourceMappingURL=chunk-
|
|
3849
|
+
//# sourceMappingURL=chunk-HGOG5ZLC.js.map
|