68 lines
3.6 KiB
JSON
68 lines
3.6 KiB
JSON
{
|
|
"id": "refactor-trigger",
|
|
"role": "feature",
|
|
"version": "1.13.0",
|
|
"title": "Complexity-triggered refactor",
|
|
"description": "Measures the complexity of the code a phase touched and, when a function crosses a configured threshold or jumps past its recorded anchor, surfaces a scoped refactor proposal at .planning/phases/<N>/<NN>-REFACTOR.md. Advisory by default — it never edits code and never blocks. Opt-in strict mode blocks /gsd-ship while a proposal is untriaged; a declined proposal is recorded in the broken-windows ledger when that capability is present. Operationalizes 'refactor early, refactor often' as continuous pressure instead of a thing you have to remember (issue #1953).",
|
|
"tier": "full",
|
|
"requires": [],
|
|
"engines": {
|
|
"gsd": ">=1.10.0"
|
|
},
|
|
"runtimeCompat": {
|
|
"supported": [
|
|
"*"
|
|
],
|
|
"unsupported": []
|
|
},
|
|
"skills": [],
|
|
"agents": [],
|
|
"activationKey": "refactor.trigger_enabled",
|
|
"config": {
|
|
"refactor.trigger_enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable the complexity-triggered refactor hook. When true, an execute:post step evaluates the complexity of the files the phase touched and writes a scoped refactor proposal if a function crosses refactor.complexity_threshold or jumps past refactor.complexity_jump_delta. Opt-in; when false the hook never runs. Issue #1953."
|
|
},
|
|
"refactor.complexity_threshold": {
|
|
"type": "number",
|
|
"default": 15,
|
|
"description": "Absolute per-function complexity above which a refactor proposal is surfaced. Semantics match ESLint's `complexity: {max: N}` — the trigger is STRICTLY GREATER, so a score of exactly N does not trigger. Default 15 follows SonarSource's default; ESLint's own default is 20 and radon's rank C begins at 11. Raise it if proposals feel like noise."
|
|
},
|
|
"refactor.complexity_jump_delta": {
|
|
"type": "number",
|
|
"default": 5,
|
|
"description": "Complexity growth above which a refactor proposal is surfaced even when the absolute threshold is not reached. Measured against the function's anchor — the score recorded the last time the function was consciously dispositioned — so it accumulates across phases and catches slow creep the absolute threshold would miss. Strictly greater, as with the threshold."
|
|
},
|
|
"refactor.trigger_strict": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Record an untriaged refactor proposal as an open `deviation` entry in the broken-windows ledger, so it becomes a tracked task that must be resolved before ship. Off by default and deliberately so: a blocking complexity number is a metric an executor can satisfy by splitting one coherent function into two incoherent ones, so the entry clears on the proposal being DISPOSITIONED (gsd-tools refactor accept|decline), never on the score improving. Ship blocking is the broken-windows capability's existing ship:pre gate — enable it with workflow.windows_enforce. With broken-windows absent, strict mode still records the proposal locally and says so; it cannot block on its own. Advisory mode (the default) surfaces the same proposal and tracks nothing."
|
|
}
|
|
},
|
|
"commands": [
|
|
{
|
|
"family": "refactor",
|
|
"module": "refactor-trigger-command-router.cjs",
|
|
"router": "routeRefactorTriggerCommand"
|
|
}
|
|
],
|
|
"hooks": [],
|
|
"steps": [
|
|
{
|
|
"point": "execute:post",
|
|
"ref": {
|
|
"command": "refactor evaluate"
|
|
},
|
|
"produces": [
|
|
"REFACTOR.md"
|
|
],
|
|
"consumes": [],
|
|
"when": "refactor.trigger_enabled",
|
|
"onError": "skip"
|
|
}
|
|
],
|
|
"contributions": [],
|
|
"gates": []
|
|
}
|