@slope-dev/slope 1.55.10 → 1.55.14
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/cli/atomic-write.d.ts +9 -0
- package/dist/cli/atomic-write.d.ts.map +1 -0
- package/dist/cli/atomic-write.js +89 -0
- package/dist/cli/atomic-write.js.map +1 -0
- package/dist/cli/commands/claim.d.ts.map +1 -1
- package/dist/cli/commands/claim.js +22 -0
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +32 -11
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/guard.d.ts.map +1 -1
- package/dist/cli/commands/guard.js +14 -0
- package/dist/cli/commands/guard.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +189 -13
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/pr.d.ts.map +1 -1
- package/dist/cli/commands/pr.js +44 -0
- package/dist/cli/commands/pr.js.map +1 -1
- package/dist/cli/commands/review-state.d.ts +2 -0
- package/dist/cli/commands/review-state.d.ts.map +1 -1
- package/dist/cli/commands/review-state.js +148 -46
- package/dist/cli/commands/review-state.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +93 -7
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/commands/store.d.ts +1 -0
- package/dist/cli/commands/store.d.ts.map +1 -1
- package/dist/cli/commands/store.js +72 -5
- package/dist/cli/commands/store.js.map +1 -1
- package/dist/cli/commands/worktree.d.ts.map +1 -1
- package/dist/cli/commands/worktree.js +203 -8
- package/dist/cli/commands/worktree.js.map +1 -1
- package/dist/cli/guards/claim-required.d.ts.map +1 -1
- package/dist/cli/guards/claim-required.js +23 -25
- package/dist/cli/guards/claim-required.js.map +1 -1
- package/dist/cli/guards/docs.js +4 -4
- package/dist/cli/guards/docs.js.map +1 -1
- package/dist/cli/guards/hazard.d.ts.map +1 -1
- package/dist/cli/guards/hazard.js +148 -52
- package/dist/cli/guards/hazard.js.map +1 -1
- package/dist/cli/guards/hook-input.d.ts +15 -0
- package/dist/cli/guards/hook-input.d.ts.map +1 -0
- package/dist/cli/guards/hook-input.js +89 -0
- package/dist/cli/guards/hook-input.js.map +1 -0
- package/dist/cli/guards/plan-analysis.d.ts +5 -1
- package/dist/cli/guards/plan-analysis.d.ts.map +1 -1
- package/dist/cli/guards/plan-analysis.js +5 -3
- package/dist/cli/guards/plan-analysis.js.map +1 -1
- package/dist/cli/guards/post-hole-enforcement.d.ts.map +1 -1
- package/dist/cli/guards/post-hole-enforcement.js +49 -22
- package/dist/cli/guards/post-hole-enforcement.js.map +1 -1
- package/dist/cli/guards/pr-review.d.ts.map +1 -1
- package/dist/cli/guards/pr-review.js +22 -2
- package/dist/cli/guards/pr-review.js.map +1 -1
- package/dist/cli/guards/roadmap-edit-shipped.d.ts.map +1 -1
- package/dist/cli/guards/roadmap-edit-shipped.js +109 -16
- package/dist/cli/guards/roadmap-edit-shipped.js.map +1 -1
- package/dist/cli/guards/scope-drift.d.ts.map +1 -1
- package/dist/cli/guards/scope-drift.js +25 -15
- package/dist/cli/guards/scope-drift.js.map +1 -1
- package/dist/cli/guards/session-briefing.d.ts.map +1 -1
- package/dist/cli/guards/session-briefing.js +14 -8
- package/dist/cli/guards/session-briefing.js.map +1 -1
- package/dist/cli/guards/sprint-completion.js +10 -4
- package/dist/cli/guards/sprint-completion.js.map +1 -1
- package/dist/cli/guards/workflow-gate.js +6 -5
- package/dist/cli/guards/workflow-gate.js.map +1 -1
- package/dist/cli/guards/worktree-check.js +1 -1
- package/dist/cli/guards/worktree-check.js.map +1 -1
- package/dist/cli/index.js +3 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/pr-review-state.d.ts +26 -0
- package/dist/cli/pr-review-state.d.ts.map +1 -0
- package/dist/cli/pr-review-state.js +86 -0
- package/dist/cli/pr-review-state.js.map +1 -0
- package/dist/cli/session-state.d.ts +5 -1
- package/dist/cli/session-state.d.ts.map +1 -1
- package/dist/cli/session-state.js +94 -54
- package/dist/cli/session-state.js.map +1 -1
- package/dist/cli/sprint-inference.d.ts +1 -1
- package/dist/cli/sprint-inference.d.ts.map +1 -1
- package/dist/cli/sprint-inference.js +10 -0
- package/dist/cli/sprint-inference.js.map +1 -1
- package/dist/cli/sprint-state.d.ts +5 -1
- package/dist/cli/sprint-state.d.ts.map +1 -1
- package/dist/cli/sprint-state.js +44 -24
- package/dist/cli/sprint-state.js.map +1 -1
- package/dist/core/analytics.d.ts +2 -1
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/analytics.js +25 -2
- package/dist/core/analytics.js.map +1 -1
- package/dist/core/analyzers/git.d.ts +8 -1
- package/dist/core/analyzers/git.d.ts.map +1 -1
- package/dist/core/analyzers/git.js +31 -5
- package/dist/core/analyzers/git.js.map +1 -1
- package/dist/core/guard.d.ts +4 -0
- package/dist/core/guard.d.ts.map +1 -1
- package/dist/core/guard.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +13 -8
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/registry.d.ts +1 -0
- package/dist/mcp/registry.d.ts.map +1 -1
- package/dist/mcp/registry.js +20 -10
- package/dist/mcp/registry.js.map +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +5 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/sqlite-memory-backend.d.ts.map +1 -1
- package/dist/store/sqlite-memory-backend.js +6 -1
- package/dist/store/sqlite-memory-backend.js.map +1 -1
- package/package.json +1 -1
- package/templates/codex/plugins/slope/.codex-plugin/plugin.json +10 -7
- package/templates/codex/plugins/slope/.mcp.json +8 -0
- package/templates/codex/plugins/slope/hooks/slope-guard.sh +3 -1
- package/templates/codex/plugins/slope/hooks.json +211 -10
- package/templates/codex/plugins/slope/skills/slope-guard-warning/SKILL.md +28 -0
- package/templates/codex/plugins/slope/skills/slope-setup/SKILL.md +29 -0
- package/templates/codex/plugins/slope/skills/slope-sprint/SKILL.md +34 -0
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
3
|
import { loadConfig } from '../config.js';
|
|
4
|
+
import { loadScorecards } from '../../core/index.js';
|
|
4
5
|
import { dedupGuardContext } from '../session-state.js';
|
|
6
|
+
import { normalizeTouchedPath, resolveTouchedPaths } from './hook-input.js';
|
|
5
7
|
const GUARD_STATE_DIR = '.slope/guard-state';
|
|
6
8
|
const STATE_FILE = 'hazard.json';
|
|
7
9
|
const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
10
|
+
const DEFAULT_HAZARD_RECENCY = 5;
|
|
11
|
+
const GENERIC_AREA_SEGMENTS = new Set(['src', 'test', 'tests', 'package', 'packages']);
|
|
8
12
|
function loadHazardState(cwd) {
|
|
9
13
|
try {
|
|
10
14
|
const path = join(cwd, GUARD_STATE_DIR, STATE_FILE);
|
|
@@ -38,74 +42,166 @@ function pruneState(state, currentSprint) {
|
|
|
38
42
|
* Writes state to disk so warnings survive context compaction.
|
|
39
43
|
*/
|
|
40
44
|
export async function hazardGuard(input, cwd) {
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
43
|
-
return {};
|
|
44
|
-
const config = loadConfig();
|
|
45
|
-
const recency = config.guidance?.hazardRecency ?? 5;
|
|
45
|
+
const areas = resolveTouchedAreas(input, cwd);
|
|
46
|
+
if (areas.length === 0)
|
|
47
|
+
return { metricReason: 'no-file-path' };
|
|
48
|
+
const config = loadConfig(cwd);
|
|
46
49
|
const currentSprint = config.currentSprint ?? 0;
|
|
47
|
-
// Determine the area from the file path (use directory)
|
|
48
|
-
const area = dirname(filePath).replace(cwd + '/', '').replace(cwd, '');
|
|
49
|
-
if (!area || area === '.')
|
|
50
|
-
return {};
|
|
51
50
|
// Load and prune disk state
|
|
52
51
|
let state = loadHazardState(cwd);
|
|
53
52
|
state = pruneState(state, currentSprint);
|
|
54
|
-
|
|
55
|
-
const MAX_HAZARDS = 3;
|
|
56
|
-
const freshWarnings = [];
|
|
53
|
+
let issues = null;
|
|
57
54
|
try {
|
|
58
55
|
const issuesPath = join(cwd, config.commonIssuesPath);
|
|
59
56
|
if (existsSync(issuesPath)) {
|
|
60
|
-
|
|
61
|
-
const areaLower = area.toLowerCase();
|
|
62
|
-
for (const pattern of issues.recurring_patterns) {
|
|
63
|
-
// Check if pattern is relevant to this area
|
|
64
|
-
const text = `${pattern.title} ${pattern.description} ${pattern.prevention}`.toLowerCase();
|
|
65
|
-
if (text.includes(areaLower) || areaLower.split('/').some(seg => text.includes(seg))) {
|
|
66
|
-
const lastSprint = Math.max(...pattern.sprints_hit);
|
|
67
|
-
freshWarnings.push({ lastSprint, text: `[${pattern.category}] ${pattern.title} (S${lastSprint}) — ${pattern.prevention.slice(0, 80)}` });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
57
|
+
issues = JSON.parse(readFileSync(issuesPath, 'utf8'));
|
|
70
58
|
}
|
|
71
59
|
}
|
|
72
60
|
catch { /* skip — common issues are optional */ }
|
|
73
|
-
|
|
61
|
+
const hazardRecency = config.guidance?.hazardRecency ?? DEFAULT_HAZARD_RECENCY;
|
|
62
|
+
let recentScorecards = null;
|
|
63
|
+
let scorecardSourceAvailable = false;
|
|
64
|
+
const loadRecentScorecards = () => {
|
|
65
|
+
if (recentScorecards)
|
|
66
|
+
return recentScorecards;
|
|
67
|
+
try {
|
|
68
|
+
const scorecards = loadScorecards(config, cwd);
|
|
69
|
+
recentScorecards = hazardRecency > 0 ? scorecards.slice(-hazardRecency) : scorecards;
|
|
70
|
+
scorecardSourceAvailable = recentScorecards.length > 0;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
recentScorecards = [];
|
|
74
|
+
scorecardSourceAvailable = false;
|
|
75
|
+
}
|
|
76
|
+
return recentScorecards;
|
|
77
|
+
};
|
|
78
|
+
for (const area of areas) {
|
|
79
|
+
// Compute fresh warnings from common issues (ranked by recency)
|
|
80
|
+
const commonWarnings = computeFreshWarnings(area, issues);
|
|
81
|
+
const freshTexts = commonWarnings.length > 0
|
|
82
|
+
? commonWarnings
|
|
83
|
+
: computeScorecardWarnings(area, loadRecentScorecards());
|
|
84
|
+
// Merge fresh warnings with any disk-cached warnings for this area
|
|
85
|
+
const cached = state.entries.find(e => e.area === area);
|
|
86
|
+
const allWarnings = freshTexts.length > 0 ? freshTexts : (cached?.warnings ?? []);
|
|
87
|
+
if (freshTexts.length === 0 && cached) {
|
|
88
|
+
state.entries = state.entries.filter(e => e.area !== area);
|
|
89
|
+
saveHazardState(cwd, state);
|
|
90
|
+
}
|
|
91
|
+
// Persist fresh warnings to disk (update or add entry)
|
|
92
|
+
if (freshTexts.length > 0) {
|
|
93
|
+
const entry = {
|
|
94
|
+
area,
|
|
95
|
+
warnings: freshTexts,
|
|
96
|
+
sprint: currentSprint,
|
|
97
|
+
timestamp: Date.now(),
|
|
98
|
+
};
|
|
99
|
+
state.entries = state.entries.filter(e => e.area !== area);
|
|
100
|
+
state.entries.push(entry);
|
|
101
|
+
saveHazardState(cwd, state);
|
|
102
|
+
}
|
|
103
|
+
if (allWarnings.length === 0)
|
|
104
|
+
continue;
|
|
105
|
+
const fullContext = formatHazardContext(area, allWarnings);
|
|
106
|
+
// Session dedup: if this exact context was already injected, return compressed reference
|
|
107
|
+
const dedup = dedupGuardContext(cwd, input.session_id, 'hazard', fullContext);
|
|
108
|
+
if (dedup)
|
|
109
|
+
return { context: dedup, metricReason: 'deduped' };
|
|
110
|
+
return { context: fullContext, metricReason: 'matched' };
|
|
111
|
+
}
|
|
112
|
+
return { metricReason: issues || scorecardSourceAvailable ? 'no-match' : 'state-unavailable' };
|
|
113
|
+
}
|
|
114
|
+
function resolveTouchedAreas(input, cwd) {
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
const areas = [];
|
|
117
|
+
for (const touchedPath of resolveTouchedPaths(input)) {
|
|
118
|
+
const relativePath = normalizeTouchedPath(touchedPath, cwd);
|
|
119
|
+
if (!relativePath)
|
|
120
|
+
continue;
|
|
121
|
+
const area = dirname(relativePath);
|
|
122
|
+
if (!area || area === '.' || seen.has(area))
|
|
123
|
+
continue;
|
|
124
|
+
seen.add(area);
|
|
125
|
+
areas.push(area);
|
|
126
|
+
}
|
|
127
|
+
return areas;
|
|
128
|
+
}
|
|
129
|
+
function computeFreshWarnings(area, issues) {
|
|
130
|
+
if (!issues)
|
|
131
|
+
return [];
|
|
132
|
+
const freshWarnings = [];
|
|
133
|
+
for (const pattern of issues.recurring_patterns) {
|
|
134
|
+
// Check if pattern is relevant to this area
|
|
135
|
+
const text = `${pattern.title} ${pattern.description} ${pattern.prevention}`.toLowerCase();
|
|
136
|
+
if (areaMatchesText(area, text, { includeGenericSegments: true })) {
|
|
137
|
+
const lastSprint = Math.max(...pattern.sprints_hit);
|
|
138
|
+
freshWarnings.push({ lastSprint, text: `[${pattern.category}] ${pattern.title} (S${lastSprint}) — ${pattern.prevention.slice(0, 80)}` });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Sort by recency (most recent first)
|
|
74
142
|
freshWarnings.sort((a, b) => b.lastSprint - a.lastSprint);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
143
|
+
return freshWarnings.map(w => w.text);
|
|
144
|
+
}
|
|
145
|
+
function computeScorecardWarnings(area, scorecards) {
|
|
146
|
+
const warnings = [];
|
|
147
|
+
for (const sc of scorecards) {
|
|
148
|
+
const sprint = sc.sprint_number ?? sc.sprint ?? 0;
|
|
149
|
+
for (const shot of sc.shots ?? []) {
|
|
150
|
+
for (const hazard of shot.hazards ?? []) {
|
|
151
|
+
const description = hazard.description ?? '';
|
|
152
|
+
const haystack = `${shot.ticket_key} ${shot.title} ${hazard.type} ${description}`.toLowerCase();
|
|
153
|
+
if (!areaMatchesText(area, haystack))
|
|
154
|
+
continue;
|
|
155
|
+
warnings.push({
|
|
156
|
+
sprint,
|
|
157
|
+
text: `[scorecard:${hazard.type}] ${description || shot.title} (S${sprint})`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
for (const location of sc.bunker_locations ?? []) {
|
|
162
|
+
const locationText = typeof location === 'string'
|
|
163
|
+
? location
|
|
164
|
+
: String(location.area ?? '');
|
|
165
|
+
if (!locationText || !areaMatchesText(area, locationText.toLowerCase()))
|
|
166
|
+
continue;
|
|
167
|
+
warnings.push({
|
|
168
|
+
sprint,
|
|
169
|
+
text: `[scorecard:bunker] ${locationText} (S${sprint})`,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
82
172
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
state.entries.push(entry);
|
|
93
|
-
saveHazardState(cwd, state);
|
|
173
|
+
warnings.sort((a, b) => b.sprint - a.sprint);
|
|
174
|
+
const seen = new Set();
|
|
175
|
+
const unique = [];
|
|
176
|
+
for (const warning of warnings) {
|
|
177
|
+
const key = warning.text.replace(/ \(S\d+\)$/, '');
|
|
178
|
+
if (seen.has(key))
|
|
179
|
+
continue;
|
|
180
|
+
seen.add(key);
|
|
181
|
+
unique.push(warning.text);
|
|
94
182
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
183
|
+
return unique;
|
|
184
|
+
}
|
|
185
|
+
function areaMatchesText(area, lowerText, opts = {}) {
|
|
186
|
+
const areaLower = area.toLowerCase();
|
|
187
|
+
if (lowerText.includes(areaLower))
|
|
188
|
+
return true;
|
|
189
|
+
const segments = areaLower
|
|
190
|
+
.split('/')
|
|
191
|
+
.map(seg => seg.trim())
|
|
192
|
+
.filter(Boolean)
|
|
193
|
+
.filter(seg => opts.includeGenericSegments || seg.length >= 4)
|
|
194
|
+
.filter(seg => opts.includeGenericSegments || !GENERIC_AREA_SEGMENTS.has(seg));
|
|
195
|
+
return segments.some(seg => lowerText.includes(seg));
|
|
196
|
+
}
|
|
197
|
+
function formatHazardContext(area, allWarnings) {
|
|
198
|
+
const maxHazards = 3;
|
|
199
|
+
const shown = allWarnings.slice(0, maxHazards);
|
|
99
200
|
const overflow = allWarnings.length - shown.length;
|
|
100
|
-
const header = `SLOPE hazards (${area}, ${allWarnings.length} total${overflow > 0 ? `, showing top ${
|
|
201
|
+
const header = `SLOPE hazards (${area}, ${allWarnings.length} total${overflow > 0 ? `, showing top ${maxHazards}` : ''}):`;
|
|
101
202
|
const lines = [header, ...shown.map(w => `• ${w}`)];
|
|
102
203
|
if (overflow > 0)
|
|
103
204
|
lines.push(` (+${overflow} more — run \`slope briefing --area=${area}\` for all)`);
|
|
104
|
-
|
|
105
|
-
// Session dedup: if this exact context was already injected, return compressed reference
|
|
106
|
-
const dedup = dedupGuardContext(cwd, input.session_id, 'hazard', fullContext);
|
|
107
|
-
if (dedup)
|
|
108
|
-
return { context: dedup };
|
|
109
|
-
return { context: fullContext };
|
|
205
|
+
return lines.join('\n');
|
|
110
206
|
}
|
|
111
207
|
//# sourceMappingURL=hazard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hazard.js","sourceRoot":"","sources":["../../../src/cli/guards/hazard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"hazard.js","sourceRoot":"","sources":["../../../src/cli/guards/hazard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { HookInput } from '../../core/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve file paths touched by a hook input across agent harness payloads.
|
|
4
|
+
*
|
|
5
|
+
* Claude-style tools usually provide tool_input.file_path. Codex apply_patch
|
|
6
|
+
* hooks carry the edited files inside the patch text, commonly in
|
|
7
|
+
* tool_input.command.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveTouchedPaths(input: HookInput): string[];
|
|
10
|
+
export declare function resolvePrimaryTouchedPath(input: HookInput): string | undefined;
|
|
11
|
+
export declare function normalizeTouchedPath(filePath: string | undefined, cwd: string): string | null;
|
|
12
|
+
export declare function toAbsoluteTouchedPath(filePath: string, cwd: string): string;
|
|
13
|
+
export declare function getApplyPatchText(input: HookInput): string | null;
|
|
14
|
+
export declare function parseApplyPatchTouchedPaths(patchText: string): string[];
|
|
15
|
+
//# sourceMappingURL=hook-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-input.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/hook-input.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAMrD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,EAAE,CAqB9D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAE9E;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY7F;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG3E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAavE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
2
|
+
const PATCH_TEXT_KEYS = ['command', 'patch', 'input'];
|
|
3
|
+
const DIRECT_PATH_KEYS = ['file_path', 'path'];
|
|
4
|
+
const DIRECT_PATH_ARRAY_KEYS = ['file_paths', 'paths'];
|
|
5
|
+
/**
|
|
6
|
+
* Resolve file paths touched by a hook input across agent harness payloads.
|
|
7
|
+
*
|
|
8
|
+
* Claude-style tools usually provide tool_input.file_path. Codex apply_patch
|
|
9
|
+
* hooks carry the edited files inside the patch text, commonly in
|
|
10
|
+
* tool_input.command.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveTouchedPaths(input) {
|
|
13
|
+
const toolInput = input.tool_input ?? {};
|
|
14
|
+
const paths = [];
|
|
15
|
+
for (const key of DIRECT_PATH_KEYS) {
|
|
16
|
+
const value = toolInput[key];
|
|
17
|
+
if (typeof value === 'string')
|
|
18
|
+
paths.push(value);
|
|
19
|
+
}
|
|
20
|
+
for (const key of DIRECT_PATH_ARRAY_KEYS) {
|
|
21
|
+
const value = toolInput[key];
|
|
22
|
+
if (!Array.isArray(value))
|
|
23
|
+
continue;
|
|
24
|
+
for (const item of value) {
|
|
25
|
+
if (typeof item === 'string')
|
|
26
|
+
paths.push(item);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const patchText = getApplyPatchText(input);
|
|
30
|
+
if (patchText)
|
|
31
|
+
paths.push(...parseApplyPatchTouchedPaths(patchText));
|
|
32
|
+
return uniqueNonEmpty(paths);
|
|
33
|
+
}
|
|
34
|
+
export function resolvePrimaryTouchedPath(input) {
|
|
35
|
+
return resolveTouchedPaths(input)[0];
|
|
36
|
+
}
|
|
37
|
+
export function normalizeTouchedPath(filePath, cwd) {
|
|
38
|
+
if (!filePath)
|
|
39
|
+
return null;
|
|
40
|
+
const normalizedCwd = cwd.replace(/\\/g, '/').replace(/\/$/, '');
|
|
41
|
+
const normalizedPath = filePath.trim().replace(/\\/g, '/');
|
|
42
|
+
if (!normalizedPath)
|
|
43
|
+
return null;
|
|
44
|
+
const relativePath = normalizedPath.startsWith(`${normalizedCwd}/`)
|
|
45
|
+
? normalizedPath.slice(normalizedCwd.length + 1)
|
|
46
|
+
: normalizedPath;
|
|
47
|
+
return relativePath.replace(/^\.\//, '');
|
|
48
|
+
}
|
|
49
|
+
export function toAbsoluteTouchedPath(filePath, cwd) {
|
|
50
|
+
const trimmed = filePath.trim();
|
|
51
|
+
return isAbsolute(trimmed) ? resolve(trimmed) : resolve(cwd, trimmed);
|
|
52
|
+
}
|
|
53
|
+
export function getApplyPatchText(input) {
|
|
54
|
+
const toolInput = input.tool_input ?? {};
|
|
55
|
+
for (const key of PATCH_TEXT_KEYS) {
|
|
56
|
+
const value = toolInput[key];
|
|
57
|
+
if (typeof value === 'string' && value.includes('*** Begin Patch')) {
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
export function parseApplyPatchTouchedPaths(patchText) {
|
|
64
|
+
const paths = [];
|
|
65
|
+
for (const line of patchText.split(/\r?\n/)) {
|
|
66
|
+
const match = line.match(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/);
|
|
67
|
+
if (match) {
|
|
68
|
+
paths.push(match[1]);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const moveMatch = line.match(/^\*\*\* Move to: (.+)$/);
|
|
72
|
+
if (moveMatch)
|
|
73
|
+
paths.push(moveMatch[1]);
|
|
74
|
+
}
|
|
75
|
+
return uniqueNonEmpty(paths);
|
|
76
|
+
}
|
|
77
|
+
function uniqueNonEmpty(values) {
|
|
78
|
+
const seen = new Set();
|
|
79
|
+
const result = [];
|
|
80
|
+
for (const value of values) {
|
|
81
|
+
const normalized = value.trim();
|
|
82
|
+
if (!normalized || seen.has(normalized))
|
|
83
|
+
continue;
|
|
84
|
+
seen.add(normalized);
|
|
85
|
+
result.push(normalized);
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=hook-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-input.js","sourceRoot":"","sources":["../../../src/cli/guards/hook-input.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,10 @@ export interface PlanFile {
|
|
|
3
3
|
path: string;
|
|
4
4
|
content: string;
|
|
5
5
|
}
|
|
6
|
+
export interface FindPlanContentOptions {
|
|
7
|
+
includeRepoLocal?: boolean;
|
|
8
|
+
includeGlobal?: boolean;
|
|
9
|
+
}
|
|
6
10
|
/** Extracted ticket info for specialist selection */
|
|
7
11
|
export interface TicketInfo {
|
|
8
12
|
title: string;
|
|
@@ -13,7 +17,7 @@ export interface TicketInfo {
|
|
|
13
17
|
* Searches repo-local first ({cwd}/.claude/plans/), then falls back
|
|
14
18
|
* to global (~/.claude/plans/) since Claude Code writes plans there.
|
|
15
19
|
*/
|
|
16
|
-
export declare function findPlanContent(cwd: string): PlanFile | null;
|
|
20
|
+
export declare function findPlanContent(cwd: string, options?: FindPlanContentOptions): PlanFile | null;
|
|
17
21
|
/**
|
|
18
22
|
* Count tickets in plan content.
|
|
19
23
|
* Matches `### T\d+:` or `### S\d+-\d+:` patterns, then the Markdown
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-analysis.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/plan-analysis.ts"],"names":[],"mappings":"AAIA,oCAAoC;AACpC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"plan-analysis.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/plan-analysis.ts"],"names":[],"mappings":"AAIA,oCAAoC;AACpC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,QAAQ,GAAG,IAAI,CAuClG;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAK7D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAoB/D"}
|
|
@@ -6,14 +6,16 @@ import { homedir } from 'node:os';
|
|
|
6
6
|
* Searches repo-local first ({cwd}/.claude/plans/), then falls back
|
|
7
7
|
* to global (~/.claude/plans/) since Claude Code writes plans there.
|
|
8
8
|
*/
|
|
9
|
-
export function findPlanContent(cwd) {
|
|
9
|
+
export function findPlanContent(cwd, options = {}) {
|
|
10
10
|
const repoLocal = join(cwd, '.claude', 'plans');
|
|
11
11
|
const global = join(homedir(), '.claude', 'plans');
|
|
12
|
+
const includeRepoLocal = options.includeRepoLocal ?? true;
|
|
13
|
+
const includeGlobal = options.includeGlobal ?? true;
|
|
12
14
|
// Deduplicate when cwd is the home directory
|
|
13
15
|
const searchDirs = [
|
|
14
|
-
{ dir: repoLocal, relative: true },
|
|
16
|
+
...(includeRepoLocal ? [{ dir: repoLocal, relative: true }] : []),
|
|
15
17
|
];
|
|
16
|
-
if (global.replace(/\\/g, '/') !== repoLocal.replace(/\\/g, '/')) {
|
|
18
|
+
if (includeGlobal && global.replace(/\\/g, '/') !== repoLocal.replace(/\\/g, '/')) {
|
|
17
19
|
searchDirs.push({ dir: global, relative: false });
|
|
18
20
|
}
|
|
19
21
|
for (const { dir: plansDir, relative } of searchDirs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-analysis.js","sourceRoot":"","sources":["../../../src/cli/guards/plan-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"plan-analysis.js","sourceRoot":"","sources":["../../../src/cli/guards/plan-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-hole-enforcement.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/post-hole-enforcement.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"post-hole-enforcement.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/post-hole-enforcement.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMlE;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA8EnG"}
|
|
@@ -2,6 +2,7 @@ import { readFileSync, existsSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { findShippedSprintsOnMain } from '../../core/index.js';
|
|
4
4
|
import { loadConfig } from '../config.js';
|
|
5
|
+
import { pendingPrReviews } from '../pr-review-state.js';
|
|
5
6
|
/**
|
|
6
7
|
* Post-hole enforcement guard: fires on Stop.
|
|
7
8
|
*
|
|
@@ -61,26 +62,39 @@ export async function postHoleEnforcementGuard(_input, cwd) {
|
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
const shipped = findShippedSprintsOnMain(cwd);
|
|
64
|
-
if (shipped.size === 0)
|
|
65
|
-
return {};
|
|
66
65
|
const drifts = [];
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
66
|
+
if (shipped.size > 0) {
|
|
67
|
+
for (const id of [...shipped].sort((a, b) => b - a)) {
|
|
68
|
+
const status = statusById.get(id);
|
|
69
|
+
// Replace EVERY '*' so patterns with multiple wildcards are sanitized
|
|
70
|
+
// (CodeQL js/incomplete-sanitization): single .replace() leaves later
|
|
71
|
+
// occurrences as literal '*' which won't match real filenames.
|
|
72
|
+
const scorecardFile = join(scorecardDirAbs, scorecardPattern.replaceAll('*', String(id)));
|
|
73
|
+
const hasScorecard = existsSync(scorecardFile);
|
|
74
|
+
const issues = [];
|
|
75
|
+
if (status !== 'complete')
|
|
76
|
+
issues.push(`status="${status ?? 'unset'}"`);
|
|
77
|
+
if (!hasScorecard)
|
|
78
|
+
issues.push('no scorecard');
|
|
79
|
+
if (issues.length > 0)
|
|
80
|
+
drifts.push({ sprint: id, issues });
|
|
81
|
+
}
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
+
const prReviewGaps = pendingPrReviews(cwd);
|
|
84
|
+
if (drifts.length === 0 && prReviewGaps.length === 0)
|
|
83
85
|
return {};
|
|
86
|
+
const sections = [];
|
|
87
|
+
if (drifts.length > 0)
|
|
88
|
+
sections.push(formatCloseoutDriftMessage(drifts));
|
|
89
|
+
if (prReviewGaps.length > 0)
|
|
90
|
+
sections.push(formatPendingPrReviewMessage(prReviewGaps));
|
|
91
|
+
const message = sections.join('\n\n');
|
|
92
|
+
if (process.env.SLOPE_POST_HOLE_BLOCK === '1') {
|
|
93
|
+
return { decision: 'deny', blockReason: message };
|
|
94
|
+
}
|
|
95
|
+
return { context: message };
|
|
96
|
+
}
|
|
97
|
+
function formatCloseoutDriftMessage(drifts) {
|
|
84
98
|
const shown = drifts.slice(0, 5);
|
|
85
99
|
const remainder = drifts.length - shown.length;
|
|
86
100
|
const lines = [
|
|
@@ -91,10 +105,23 @@ export async function postHoleEnforcementGuard(_input, cwd) {
|
|
|
91
105
|
if (remainder > 0)
|
|
92
106
|
lines.push(` …and ${remainder} more`);
|
|
93
107
|
lines.push('', 'Per the post-hole routine, each shipped sprint needs:', ' • status:complete in roadmap.json', ' • scorecard at docs/retros/sprint-N.json', '', 'Fix commands:', ' - Build scorecard: slope auto-card --sprint=<N>', ' - Validate scorecard: slope validate', ' - Roadmap status: edit docs/backlog/roadmap.json (or slope sprint complete)');
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
108
|
+
return lines.join('\n');
|
|
109
|
+
}
|
|
110
|
+
function formatPendingPrReviewMessage(records) {
|
|
111
|
+
const shown = records.slice(0, 5);
|
|
112
|
+
const remainder = records.length - shown.length;
|
|
113
|
+
const lines = [
|
|
114
|
+
`SLOPE PR review enforcement: ${records.length} created PR${records.length === 1 ? '' : 's'} missing a \`slope pr review\` record:`,
|
|
115
|
+
'',
|
|
116
|
+
...shown.map(record => {
|
|
117
|
+
const sprintArg = record.sprint ? ` --sprint=${record.sprint}` : '';
|
|
118
|
+
const sprintLabel = record.sprint ? ` (S${record.sprint})` : '';
|
|
119
|
+
return ` • PR #${record.pr}${sprintLabel}: slope pr review --pr=${record.pr}${sprintArg}`;
|
|
120
|
+
}),
|
|
121
|
+
];
|
|
122
|
+
if (remainder > 0)
|
|
123
|
+
lines.push(` …and ${remainder} more`);
|
|
124
|
+
lines.push('', 'Run the review command before presenting the PR as ready to merge.');
|
|
125
|
+
return lines.join('\n');
|
|
99
126
|
}
|
|
100
127
|
//# sourceMappingURL=post-hole-enforcement.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-hole-enforcement.js","sourceRoot":"","sources":["../../../src/cli/guards/post-hole-enforcement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"post-hole-enforcement.js","sourceRoot":"","sources":["../../../src/cli/guards/post-hole-enforcement.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-review.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/pr-review.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"pr-review.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/pr-review.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAIhE;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgCvF;AAiBD;oEACoE;AACpE,iBAAS,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAenE;AAwBD,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiB3D;AAED,iBAAS,qBAAqB,CAAC,IAAI,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAKnE;AAGD,eAAO,MAAM,UAAU;;;;CAAsE,CAAC"}
|