@slope-dev/slope 1.26.1 → 1.27.1
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/README.md +291 -102
- package/dist/cli/commands/briefing.d.ts.map +1 -1
- package/dist/cli/commands/briefing.js +11 -1
- package/dist/cli/commands/briefing.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +3 -1
- package/dist/cli/commands/docs.d.ts.map +1 -1
- package/dist/cli/commands/docs.js +74 -9
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +14 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/review-state.d.ts.map +1 -1
- package/dist/cli/commands/review-state.js +111 -1
- package/dist/cli/commands/review-state.js.map +1 -1
- package/dist/cli/commands/stats.d.ts +58 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +148 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/guards/docs.js +4 -4
- package/dist/cli/guards/docs.js.map +1 -1
- package/dist/cli/guards/explore.d.ts +5 -2
- package/dist/cli/guards/explore.d.ts.map +1 -1
- package/dist/cli/guards/explore.js +37 -27
- package/dist/cli/guards/explore.js.map +1 -1
- package/dist/cli/guards/sprint-completion.d.ts.map +1 -1
- package/dist/cli/guards/sprint-completion.js +89 -27
- package/dist/cli/guards/sprint-completion.js.map +1 -1
- package/dist/cli/guards/subagent-gate.d.ts +2 -2
- package/dist/cli/guards/subagent-gate.d.ts.map +1 -1
- package/dist/cli/guards/subagent-gate.js +7 -18
- package/dist/cli/guards/subagent-gate.js.map +1 -1
- package/dist/cli/index.js +9 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/registry.js +12 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli/template-generator.d.ts.map +1 -1
- package/dist/cli/template-generator.js +5 -0
- package/dist/cli/template-generator.js.map +1 -1
- package/dist/core/config.d.ts +2 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/deferred.d.ts +41 -0
- package/dist/core/deferred.d.ts.map +1 -0
- package/dist/core/deferred.js +92 -0
- package/dist/core/deferred.js.map +1 -0
- package/dist/core/guard.d.ts +4 -0
- package/dist/core/guard.d.ts.map +1 -1
- package/dist/core/guard.js +4 -4
- package/dist/core/guard.js.map +1 -1
- package/dist/core/harness.js +1 -1
- package/dist/core/harness.js.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/roadmap.d.ts +6 -2
- package/dist/core/roadmap.d.ts.map +1 -1
- package/dist/core/roadmap.js +26 -2
- package/dist/core/roadmap.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// SLOPE CLI — Stats export for slope-web live stats
|
|
2
|
+
// Computes SlopeStats JSON from local scorecards + registries.
|
|
3
|
+
import { readdirSync, existsSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { loadScorecards, computeHandicapCard, computeScoreLabel, listMetaphors, GUARD_DEFINITIONS, loadConfig, } from '../../core/index.js';
|
|
6
|
+
import { CLI_COMMAND_REGISTRY } from '../registry.js';
|
|
7
|
+
// Ensure metaphors are registered before counting
|
|
8
|
+
import '../../core/metaphors/index.js';
|
|
9
|
+
// ── Helpers ────────────────────────────────────────────────────
|
|
10
|
+
function simplifyRollingStats(core) {
|
|
11
|
+
return {
|
|
12
|
+
handicap: core.handicap,
|
|
13
|
+
fairway_pct: core.fairway_pct,
|
|
14
|
+
gir_pct: core.gir_pct,
|
|
15
|
+
avg_putts: core.avg_putts,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function countTestFiles(cwd) {
|
|
19
|
+
const testsDir = join(cwd, 'tests');
|
|
20
|
+
if (!existsSync(testsDir))
|
|
21
|
+
return 0;
|
|
22
|
+
let count = 0;
|
|
23
|
+
function walk(dir) {
|
|
24
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
25
|
+
if (entry.isDirectory()) {
|
|
26
|
+
walk(join(dir, entry.name));
|
|
27
|
+
}
|
|
28
|
+
else if (entry.name.endsWith('.test.ts')) {
|
|
29
|
+
count++;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
walk(testsDir);
|
|
34
|
+
return count;
|
|
35
|
+
}
|
|
36
|
+
function countPackages(cwd) {
|
|
37
|
+
const srcDir = join(cwd, 'src');
|
|
38
|
+
if (!existsSync(srcDir))
|
|
39
|
+
return 0;
|
|
40
|
+
return readdirSync(srcDir, { withFileTypes: true })
|
|
41
|
+
.filter(e => e.isDirectory())
|
|
42
|
+
.length;
|
|
43
|
+
}
|
|
44
|
+
function toScorecardSummary(sc) {
|
|
45
|
+
return {
|
|
46
|
+
sprint: sc.sprint_number,
|
|
47
|
+
par: sc.par,
|
|
48
|
+
score: sc.score,
|
|
49
|
+
score_label: sc.score_label ?? computeScoreLabel(sc.score, sc.par),
|
|
50
|
+
theme: sc.theme,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function toLatestScorecard(sc) {
|
|
54
|
+
const stats = sc.stats;
|
|
55
|
+
return {
|
|
56
|
+
sprint: sc.sprint_number,
|
|
57
|
+
par: sc.par,
|
|
58
|
+
score: sc.score,
|
|
59
|
+
score_label: sc.score_label ?? computeScoreLabel(sc.score, sc.par),
|
|
60
|
+
theme: sc.theme,
|
|
61
|
+
stats: {
|
|
62
|
+
fairway_hits: stats?.fairways_hit ?? 0,
|
|
63
|
+
fairway_total: stats?.fairways_total ?? 0,
|
|
64
|
+
gir: stats?.greens_in_regulation ?? 0,
|
|
65
|
+
hazards_hit: stats?.hazards_hit ?? 0,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function computeMilestones(scorecards) {
|
|
70
|
+
const milestones = [];
|
|
71
|
+
// Sample at every 5th sprint, plus the latest
|
|
72
|
+
for (let i = 0; i < scorecards.length; i++) {
|
|
73
|
+
const sc = scorecards[i];
|
|
74
|
+
if ((sc.sprint_number % 5 === 0) || i === scorecards.length - 1) {
|
|
75
|
+
const window = scorecards.slice(0, i + 1);
|
|
76
|
+
const card = computeHandicapCard(window);
|
|
77
|
+
milestones.push({
|
|
78
|
+
sprint: sc.sprint_number,
|
|
79
|
+
handicap: card.all_time.handicap,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return milestones;
|
|
84
|
+
}
|
|
85
|
+
// ── Core export function ───────────────────────────────────────
|
|
86
|
+
export function computeSlopeStats(cwd = process.cwd()) {
|
|
87
|
+
const config = loadConfig(cwd);
|
|
88
|
+
const scorecards = loadScorecards(config, cwd);
|
|
89
|
+
const handicapCard = computeHandicapCard(scorecards);
|
|
90
|
+
const latest = scorecards.length > 0 ? scorecards[scorecards.length - 1] : null;
|
|
91
|
+
const recent = scorecards.slice(-5).reverse().map(toScorecardSummary);
|
|
92
|
+
return {
|
|
93
|
+
sprints_completed: scorecards.length > 0
|
|
94
|
+
? Math.max(...scorecards.map(s => s.sprint_number))
|
|
95
|
+
: 0,
|
|
96
|
+
total_tests: countTestFiles(cwd),
|
|
97
|
+
cli_commands: CLI_COMMAND_REGISTRY.length,
|
|
98
|
+
guards: GUARD_DEFINITIONS.length,
|
|
99
|
+
packages: countPackages(cwd),
|
|
100
|
+
metaphors: listMetaphors().length,
|
|
101
|
+
handicap: {
|
|
102
|
+
last_5: simplifyRollingStats(handicapCard.last_5),
|
|
103
|
+
last_10: simplifyRollingStats(handicapCard.last_10),
|
|
104
|
+
all_time: simplifyRollingStats(handicapCard.all_time),
|
|
105
|
+
},
|
|
106
|
+
recent_scorecards: recent,
|
|
107
|
+
miss_pattern: {
|
|
108
|
+
long: handicapCard.all_time.miss_pattern.long,
|
|
109
|
+
short: handicapCard.all_time.miss_pattern.short,
|
|
110
|
+
left: handicapCard.all_time.miss_pattern.left,
|
|
111
|
+
right: handicapCard.all_time.miss_pattern.right,
|
|
112
|
+
},
|
|
113
|
+
phase_status: {},
|
|
114
|
+
latest_scorecard: latest ? toLatestScorecard(latest) : null,
|
|
115
|
+
handicap_milestones: computeMilestones(scorecards),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// ── CLI command ────────────────────────────────────────────────
|
|
119
|
+
export async function statsCommand(args) {
|
|
120
|
+
const sub = args[0];
|
|
121
|
+
switch (sub) {
|
|
122
|
+
case 'export':
|
|
123
|
+
return exportSubcommand(args.slice(1));
|
|
124
|
+
default:
|
|
125
|
+
console.log(`
|
|
126
|
+
slope stats — Statistics export for slope-web
|
|
127
|
+
|
|
128
|
+
Usage:
|
|
129
|
+
slope stats export [--pretty] [--stdout]
|
|
130
|
+
|
|
131
|
+
Subcommands:
|
|
132
|
+
export Compute SlopeStats JSON from local scorecards + registries
|
|
133
|
+
|
|
134
|
+
Options:
|
|
135
|
+
--pretty Pretty-print JSON output
|
|
136
|
+
--stdout Write to stdout (default behavior)
|
|
137
|
+
`);
|
|
138
|
+
if (sub)
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function exportSubcommand(args) {
|
|
143
|
+
const pretty = args.includes('--pretty');
|
|
144
|
+
const stats = computeSlopeStats();
|
|
145
|
+
const json = JSON.stringify(stats, null, pretty ? 2 : undefined);
|
|
146
|
+
console.log(json);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/cli/commands/stats.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/guards/docs.js
CHANGED
|
@@ -43,10 +43,10 @@ export const GUARD_DOCS = {
|
|
|
43
43
|
level: 'full',
|
|
44
44
|
},
|
|
45
45
|
'subagent-gate': {
|
|
46
|
-
purpose: 'Controls subagent resource usage by
|
|
47
|
-
triggers: 'PreToolUse on
|
|
48
|
-
behavior: '
|
|
49
|
-
configuration: 'guidance.
|
|
46
|
+
purpose: 'Controls subagent resource usage by enforcing model selection on Explore/Plan subagents. Prevents expensive long-running subagent calls.',
|
|
47
|
+
triggers: 'PreToolUse on Agent. Fires when the agent launches a subagent.',
|
|
48
|
+
behavior: 'Blocks subagents using models not in the allowed list. Injects codebase orientation context for allowed subagents.',
|
|
49
|
+
configuration: 'guidance.subagentAllowModels (default: [\'haiku\']). Disable: add "subagent-gate" to guidance.disabled.',
|
|
50
50
|
level: 'full',
|
|
51
51
|
},
|
|
52
52
|
'push-nudge': {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/cli/guards/docs.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAehF,MAAM,CAAC,MAAM,UAAU,GAA6B;IAClD,OAAO,EAAE;QACP,OAAO,EAAE,gKAAgK;QACzK,QAAQ,EAAE,qFAAqF;QAC/F,QAAQ,EAAE,oJAAoJ;QAC9J,aAAa,EAAE,0HAA0H;QACzI,KAAK,EAAE,MAAM;KACd;IACD,MAAM,EAAE;QACN,OAAO,EAAE,8HAA8H;QACvI,QAAQ,EAAE,4EAA4E;QACtF,QAAQ,EAAE,uIAAuI;QACjJ,aAAa,EAAE,qIAAqI;QACpJ,KAAK,EAAE,MAAM;KACd;IACD,cAAc,EAAE;QACd,OAAO,EAAE,kGAAkG;QAC3G,QAAQ,EAAE,wEAAwE;QAClF,QAAQ,EAAE,uHAAuH;QACjI,aAAa,EAAE,+HAA+H;QAC9I,KAAK,EAAE,MAAM;KACd;IACD,aAAa,EAAE;QACb,OAAO,EAAE,wHAAwH;QACjI,QAAQ,EAAE,yEAAyE;QACnF,QAAQ,EAAE,6IAA6I;QACvJ,aAAa,EAAE,wGAAwG;QACvH,KAAK,EAAE,MAAM;KACd;IACD,UAAU,EAAE;QACV,OAAO,EAAE,6IAA6I;QACtJ,QAAQ,EAAE,2EAA2E;QACrF,QAAQ,EAAE,6GAA6G;QACvH,aAAa,EAAE,2IAA2I;QAC1J,KAAK,EAAE,MAAM;KACd;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,wGAAwG;QACjH,QAAQ,EAAE,+CAA+C;QACzD,QAAQ,EAAE,kIAAkI;QAC5I,aAAa,EAAE,iDAAiD;QAChE,KAAK,EAAE,MAAM;KACd;IACD,eAAe,EAAE;QACf,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/cli/guards/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { HookInput, GuardResult } from '../../core/index.js';
|
|
2
2
|
/**
|
|
3
|
-
* Explore guard: fires on Read|Glob|Grep (PreToolUse).
|
|
3
|
+
* Explore guard: fires on Read|Glob|Grep|Edit|Write (PreToolUse).
|
|
4
4
|
* Suggests checking codebase map before deep exploration.
|
|
5
|
-
* Includes staleness awareness when CODEBASE.md has YAML frontmatter
|
|
5
|
+
* Includes tiered staleness awareness when CODEBASE.md has YAML frontmatter:
|
|
6
|
+
* 0–10 commits stale → no warning (within tolerance)
|
|
7
|
+
* 11–30 commits stale → warning with commit count
|
|
8
|
+
* 31+ commits stale → block Edit/Write (don't block Read/Glob/Grep)
|
|
6
9
|
*/
|
|
7
10
|
export declare function exploreGuard(input: HookInput, cwd: string): Promise<GuardResult>;
|
|
8
11
|
//# sourceMappingURL=explore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/explore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/explore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAOlE;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAyDtF"}
|
|
@@ -3,13 +3,18 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { execSync } from 'node:child_process';
|
|
4
4
|
import { loadConfig } from '../config.js';
|
|
5
5
|
const DEFAULT_INDEX_PATHS = ['CODEBASE.md', '.slope/index.json', 'docs/architecture.md'];
|
|
6
|
+
const DEFAULT_STALE_WARN_AT = 11;
|
|
7
|
+
const DEFAULT_STALE_BLOCK_AT = 31;
|
|
6
8
|
/**
|
|
7
|
-
* Explore guard: fires on Read|Glob|Grep (PreToolUse).
|
|
9
|
+
* Explore guard: fires on Read|Glob|Grep|Edit|Write (PreToolUse).
|
|
8
10
|
* Suggests checking codebase map before deep exploration.
|
|
9
|
-
* Includes staleness awareness when CODEBASE.md has YAML frontmatter
|
|
11
|
+
* Includes tiered staleness awareness when CODEBASE.md has YAML frontmatter:
|
|
12
|
+
* 0–10 commits stale → no warning (within tolerance)
|
|
13
|
+
* 11–30 commits stale → warning with commit count
|
|
14
|
+
* 31+ commits stale → block Edit/Write (don't block Read/Glob/Grep)
|
|
10
15
|
*/
|
|
11
16
|
export async function exploreGuard(input, cwd) {
|
|
12
|
-
const config = loadConfig();
|
|
17
|
+
const config = loadConfig(cwd);
|
|
13
18
|
const indexPaths = config.guidance?.indexPaths ?? DEFAULT_INDEX_PATHS;
|
|
14
19
|
// Find which index files exist
|
|
15
20
|
const found = [];
|
|
@@ -25,10 +30,25 @@ export async function exploreGuard(input, cwd) {
|
|
|
25
30
|
// Check if CODEBASE.md exists and assess staleness
|
|
26
31
|
const mapPath = join(cwd, 'CODEBASE.md');
|
|
27
32
|
if (existsSync(mapPath)) {
|
|
28
|
-
const staleness = checkMapStaleness(mapPath, cwd);
|
|
29
|
-
if (staleness === '
|
|
33
|
+
const staleness = checkMapStaleness(mapPath, cwd, config);
|
|
34
|
+
if (staleness.level === 'block') {
|
|
35
|
+
// Only block Edit/Write — let Read/Glob/Grep through with a warning
|
|
36
|
+
const toolName = input.tool_name ?? '';
|
|
37
|
+
const isWriteTool = /^(Edit|Write)$/i.test(toolName);
|
|
38
|
+
if (isWriteTool) {
|
|
39
|
+
return {
|
|
40
|
+
decision: 'deny',
|
|
41
|
+
blockReason: `SLOPE: Codebase map is ${staleness.distance} commits stale. Run \`slope map\` to refresh before editing.`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// Read/Glob/Grep — warn but don't block
|
|
30
45
|
return {
|
|
31
|
-
context: `SLOPE: Codebase map
|
|
46
|
+
context: `SLOPE: Codebase map is ${staleness.distance} commits stale. Run \`slope map\` to refresh.`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (staleness.level === 'warn') {
|
|
50
|
+
return {
|
|
51
|
+
context: `SLOPE: Codebase map at CODEBASE.md is ${staleness.distance} commits stale. Run 'slope map' to refresh, or explore if needed.`,
|
|
32
52
|
};
|
|
33
53
|
}
|
|
34
54
|
// Current map — estimate token size
|
|
@@ -43,36 +63,26 @@ export async function exploreGuard(input, cwd) {
|
|
|
43
63
|
context: `SLOPE: Codebase index available at: ${found.join(', ')} — check before deep exploration.`,
|
|
44
64
|
};
|
|
45
65
|
}
|
|
46
|
-
function checkMapStaleness(mapPath, cwd) {
|
|
66
|
+
function checkMapStaleness(mapPath, cwd, config) {
|
|
67
|
+
const warnAt = config?.guidance?.mapStaleWarnAt ?? DEFAULT_STALE_WARN_AT;
|
|
68
|
+
const blockAt = config?.guidance?.mapStaleBlockAt ?? DEFAULT_STALE_BLOCK_AT;
|
|
47
69
|
try {
|
|
48
70
|
const content = readFileSync(mapPath, 'utf8');
|
|
49
71
|
const metaMatch = content.match(/^---\n([\s\S]*?)\n---/m);
|
|
50
72
|
if (!metaMatch)
|
|
51
|
-
return 'current'; // No metadata — can't check
|
|
73
|
+
return { level: 'current', distance: 0 }; // No metadata — can't check
|
|
52
74
|
const gitShaMatch = metaMatch[1].match(/git_sha:\s*"?([^"\n]+)"?/);
|
|
53
75
|
if (!gitShaMatch)
|
|
54
|
-
return 'current';
|
|
76
|
+
return { level: 'current', distance: 0 };
|
|
55
77
|
const distance = parseInt(execSync(`git rev-list --count ${gitShaMatch[1]}..HEAD 2>/dev/null`, { cwd, encoding: 'utf8', timeout: 5000 }).trim() || '0', 10);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
function getStalenessDetail(mapPath, cwd) {
|
|
63
|
-
try {
|
|
64
|
-
const content = readFileSync(mapPath, 'utf8');
|
|
65
|
-
const metaMatch = content.match(/^---\n([\s\S]*?)\n---/m);
|
|
66
|
-
if (!metaMatch)
|
|
67
|
-
return 'unknown';
|
|
68
|
-
const gitShaMatch = metaMatch[1].match(/git_sha:\s*"?([^"\n]+)"?/);
|
|
69
|
-
if (!gitShaMatch)
|
|
70
|
-
return 'unknown';
|
|
71
|
-
const distance = execSync(`git rev-list --count ${gitShaMatch[1]}..HEAD 2>/dev/null`, { cwd, encoding: 'utf8', timeout: 5000 }).trim();
|
|
72
|
-
return `${distance} commits behind`;
|
|
78
|
+
if (distance >= blockAt)
|
|
79
|
+
return { level: 'block', distance };
|
|
80
|
+
if (distance >= warnAt)
|
|
81
|
+
return { level: 'warn', distance };
|
|
82
|
+
return { level: 'current', distance };
|
|
73
83
|
}
|
|
74
84
|
catch {
|
|
75
|
-
return '
|
|
85
|
+
return { level: 'current', distance: 0 }; // Can't determine — assume current
|
|
76
86
|
}
|
|
77
87
|
}
|
|
78
88
|
//# sourceMappingURL=explore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explore.js","sourceRoot":"","sources":["../../../src/cli/guards/explore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,mBAAmB,GAAG,CAAC,aAAa,EAAE,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"explore.js","sourceRoot":"","sources":["../../../src/cli/guards/explore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sprint-completion.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/sprint-completion.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sprint-completion.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/sprint-completion.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIlE;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgB/F"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { loadConfig } from '../config.js';
|
|
2
5
|
import { loadSprintState, saveSprintState, updateGate, isSprintComplete, pendingGates } from '../sprint-state.js';
|
|
3
6
|
/**
|
|
4
7
|
* Sprint-completion guard: enforces post-implementation gates.
|
|
@@ -40,7 +43,7 @@ function checkStaleness(sprint, cwd) {
|
|
|
40
43
|
}
|
|
41
44
|
return null;
|
|
42
45
|
}
|
|
43
|
-
/** Block `gh pr create` when gates are incomplete. */
|
|
46
|
+
/** Block `gh pr create` when gates are incomplete or scorecard is missing. */
|
|
44
47
|
function handlePreToolUse(input, cwd) {
|
|
45
48
|
const command = input.tool_input?.command;
|
|
46
49
|
if (!command || !command.includes('gh pr create'))
|
|
@@ -48,16 +51,24 @@ function handlePreToolUse(input, cwd) {
|
|
|
48
51
|
const state = loadSprintState(cwd);
|
|
49
52
|
if (!state)
|
|
50
53
|
return {};
|
|
51
|
-
if (state.phase === 'complete'
|
|
54
|
+
if (state.phase === 'complete')
|
|
55
|
+
return {}; // Sprint fully complete — skip all checks
|
|
56
|
+
// Check scorecard existence independently of gates
|
|
57
|
+
const scorecardMissing = !scorecardExists(state.sprint, cwd);
|
|
58
|
+
const gatesComplete = isSprintComplete(state);
|
|
59
|
+
if (gatesComplete && !scorecardMissing)
|
|
52
60
|
return {};
|
|
53
61
|
const staleWarning = checkStaleness(state.sprint, cwd);
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
`SLOPE sprint-completion: Cannot create PR — Sprint ${state.sprint}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
const lines = [];
|
|
63
|
+
if (scorecardMissing) {
|
|
64
|
+
lines.push(`SLOPE sprint-completion: Cannot create PR — Sprint ${state.sprint} scorecard not found.`, '', 'Create a scorecard and validate it:', ' - `slope auto-card` — generate from git + CI signals', ' - `slope validate` — validate scorecard (marks gate complete)');
|
|
65
|
+
}
|
|
66
|
+
if (!gatesComplete) {
|
|
67
|
+
const pending = pendingGates(state);
|
|
68
|
+
if (lines.length > 0)
|
|
69
|
+
lines.push('');
|
|
70
|
+
lines.push(`SLOPE sprint-completion: Sprint ${state.sprint} has incomplete gates:`, ...pending.map(g => ` - ${g}`), '', 'Complete these gates before creating the PR.');
|
|
71
|
+
}
|
|
61
72
|
if (staleWarning)
|
|
62
73
|
lines.push('', staleWarning);
|
|
63
74
|
return {
|
|
@@ -65,36 +76,41 @@ function handlePreToolUse(input, cwd) {
|
|
|
65
76
|
blockReason: lines.join('\n'),
|
|
66
77
|
};
|
|
67
78
|
}
|
|
68
|
-
/** Block session end when mid-sprint with incomplete gates. */
|
|
79
|
+
/** Block session end when mid-sprint with incomplete gates or missing scorecard. */
|
|
69
80
|
function handleStop(cwd) {
|
|
70
81
|
const state = loadSprintState(cwd);
|
|
71
82
|
if (!state)
|
|
72
83
|
return {};
|
|
73
|
-
if (state.phase === 'complete' || isSprintComplete(state))
|
|
74
|
-
return {};
|
|
75
84
|
// Only block during implementing/scoring phases — don't block during planning/reviewing
|
|
76
85
|
if (state.phase !== 'implementing' && state.phase !== 'scoring')
|
|
77
86
|
return {};
|
|
87
|
+
const scorecardMissing = !scorecardExists(state.sprint, cwd);
|
|
88
|
+
const gatesComplete = isSprintComplete(state);
|
|
89
|
+
if (gatesComplete && !scorecardMissing)
|
|
90
|
+
return {};
|
|
78
91
|
const staleWarning = checkStaleness(state.sprint, cwd);
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
`SLOPE sprint-completion: Sprint ${state.sprint}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
' - `slope sprint gate architect_review` — mark architect review done',
|
|
88
|
-
|
|
89
|
-
' - `slope review` — generates review markdown (auto-marks gate)',
|
|
90
|
-
'',
|
|
91
|
-
'Or use `slope sprint reset` to clear sprint state if this sprint was abandoned.',
|
|
92
|
-
];
|
|
92
|
+
const lines = [];
|
|
93
|
+
if (scorecardMissing) {
|
|
94
|
+
lines.push(`SLOPE sprint-completion: Sprint ${state.sprint} scorecard not found.`, '', 'Create a scorecard before ending the session:', ' - `slope auto-card` — generate from git + CI signals', ' - `slope validate` — validate scorecard (marks gate complete)');
|
|
95
|
+
}
|
|
96
|
+
if (!gatesComplete) {
|
|
97
|
+
const pending = pendingGates(state);
|
|
98
|
+
if (lines.length > 0)
|
|
99
|
+
lines.push('');
|
|
100
|
+
lines.push(`SLOPE sprint-completion: Sprint ${state.sprint} is incomplete. Remaining gates:`, ...pending.map(g => ` - ${g}`), '', 'Complete these before ending the session:', ' - `slope sprint gate tests` — mark tests passing', ' - `slope sprint gate code_review` — mark code review done', ' - `slope sprint gate architect_review` — mark architect review done', ' - `slope validate` — validates scorecard (auto-marks gate)', ' - `slope review` — generates review markdown (auto-marks gate)', '', 'Or use `slope sprint reset` to clear sprint state if this sprint was abandoned.');
|
|
101
|
+
}
|
|
93
102
|
if (staleWarning)
|
|
94
103
|
lines.push('', staleWarning);
|
|
95
104
|
return { blockReason: lines.join('\n') };
|
|
96
105
|
}
|
|
97
|
-
/**
|
|
106
|
+
/** Check if a scorecard file exists for the given sprint. */
|
|
107
|
+
function scorecardExists(sprint, cwd) {
|
|
108
|
+
const config = loadConfig(cwd);
|
|
109
|
+
const pattern = config.scorecardPattern.replace('*', String(sprint));
|
|
110
|
+
const scorecardPath = join(cwd, config.scorecardDir, pattern);
|
|
111
|
+
return existsSync(scorecardPath);
|
|
112
|
+
}
|
|
113
|
+
/** Auto-detect test pass, validate success, and PR merge from Bash output. */
|
|
98
114
|
function handlePostToolUse(input, cwd) {
|
|
99
115
|
const command = input.tool_input?.command;
|
|
100
116
|
if (!command)
|
|
@@ -103,6 +119,10 @@ function handlePostToolUse(input, cwd) {
|
|
|
103
119
|
if (/gh\s+pr\s+merge/.test(command)) {
|
|
104
120
|
return handlePrMerge(input, cwd);
|
|
105
121
|
}
|
|
122
|
+
// Detect slope validate success → auto-update roadmap
|
|
123
|
+
if (/\bslope\s+validate\b/.test(command)) {
|
|
124
|
+
return handleValidateSuccess(input, cwd);
|
|
125
|
+
}
|
|
106
126
|
// Check if command looks like a test runner
|
|
107
127
|
const isTestCommand = /\b(jest|vitest|bun\s+test|npx\s+jest|npx\s+vitest)\b/.test(command);
|
|
108
128
|
if (!isTestCommand)
|
|
@@ -122,6 +142,48 @@ function handlePostToolUse(input, cwd) {
|
|
|
122
142
|
}
|
|
123
143
|
return {};
|
|
124
144
|
}
|
|
145
|
+
/** Auto-update roadmap status when `slope validate` succeeds. */
|
|
146
|
+
function handleValidateSuccess(input, cwd) {
|
|
147
|
+
const response = input.tool_response ?? {};
|
|
148
|
+
const exitCode = response.exit_code ?? response.exitCode;
|
|
149
|
+
if (exitCode !== 0 && exitCode !== '0')
|
|
150
|
+
return {};
|
|
151
|
+
const state = loadSprintState(cwd);
|
|
152
|
+
if (!state)
|
|
153
|
+
return {};
|
|
154
|
+
const config = loadConfig(cwd);
|
|
155
|
+
const roadmapPath = join(cwd, config.roadmapPath);
|
|
156
|
+
if (!existsSync(roadmapPath))
|
|
157
|
+
return {};
|
|
158
|
+
try {
|
|
159
|
+
const raw = JSON.parse(readFileSync(roadmapPath, 'utf8'));
|
|
160
|
+
if (!raw || !Array.isArray(raw.sprints))
|
|
161
|
+
return {};
|
|
162
|
+
const sprint = raw.sprints.find((s) => s.id === state.sprint);
|
|
163
|
+
if (!sprint || sprint.status === 'complete')
|
|
164
|
+
return {};
|
|
165
|
+
sprint.status = 'complete';
|
|
166
|
+
// Also update phase status if all sprints in a phase are now complete
|
|
167
|
+
if (Array.isArray(raw.phases)) {
|
|
168
|
+
for (const phase of raw.phases) {
|
|
169
|
+
if (!Array.isArray(phase.sprints) || !phase.sprints.includes(state.sprint))
|
|
170
|
+
continue;
|
|
171
|
+
const allComplete = phase.sprints.every((sid) => {
|
|
172
|
+
const s = raw.sprints.find((sp) => sp.id === sid);
|
|
173
|
+
return s?.status === 'complete';
|
|
174
|
+
});
|
|
175
|
+
if (allComplete && phase.status !== 'complete') {
|
|
176
|
+
phase.status = 'complete';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
writeFileSync(roadmapPath, JSON.stringify(raw, null, 2) + '\n');
|
|
181
|
+
return { context: `SLOPE: Updated roadmap — Sprint ${state.sprint} → complete` };
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return {};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
125
187
|
/** Transition sprint to scoring phase after PR merge. */
|
|
126
188
|
function handlePrMerge(input, cwd) {
|
|
127
189
|
const state = loadSprintState(cwd);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sprint-completion.js","sourceRoot":"","sources":["../../../src/cli/guards/sprint-completion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"sprint-completion.js","sourceRoot":"","sources":["../../../src/cli/guards/sprint-completion.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { HookInput, GuardResult } from '../../core/index.js';
|
|
2
2
|
/**
|
|
3
|
-
* Subagent gate guard: fires PreToolUse on
|
|
4
|
-
*
|
|
3
|
+
* Subagent gate guard: fires PreToolUse on Agent.
|
|
4
|
+
* Enforces model selection on Explore/Plan subagents.
|
|
5
5
|
*/
|
|
6
6
|
export declare function subagentGateGuard(input: HookInput, _cwd: string): Promise<GuardResult>;
|
|
7
7
|
//# sourceMappingURL=subagent-gate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-gate.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/subagent-gate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAsClE;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"subagent-gate.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/subagent-gate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAsClE;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAwB5F"}
|
|
@@ -30,14 +30,13 @@ function buildOrientation(cwd) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Subagent gate guard: fires PreToolUse on
|
|
34
|
-
*
|
|
33
|
+
* Subagent gate guard: fires PreToolUse on Agent.
|
|
34
|
+
* Enforces model selection on Explore/Plan subagents.
|
|
35
35
|
*/
|
|
36
36
|
export async function subagentGateGuard(input, _cwd) {
|
|
37
37
|
const toolInput = input.tool_input ?? {};
|
|
38
38
|
const subagentType = toolInput.subagent_type;
|
|
39
39
|
const model = toolInput.model;
|
|
40
|
-
const maxTurns = toolInput.max_turns;
|
|
41
40
|
const resume = toolInput.resume;
|
|
42
41
|
// Exempt resumed agents — they inherit prior settings
|
|
43
42
|
if (resume)
|
|
@@ -48,22 +47,12 @@ export async function subagentGateGuard(input, _cwd) {
|
|
|
48
47
|
const config = loadConfig();
|
|
49
48
|
const guidance = config.guidance ?? {};
|
|
50
49
|
const allowedModels = guidance.subagentAllowModels ?? ['haiku'];
|
|
51
|
-
const turnsLimit = subagentType === 'Explore'
|
|
52
|
-
? (guidance.subagentExploreTurns ?? 10)
|
|
53
|
-
: (guidance.subagentPlanTurns ?? 15);
|
|
54
|
-
const violations = [];
|
|
55
50
|
if (model && !allowedModels.includes(model)) {
|
|
56
|
-
|
|
51
|
+
return {
|
|
52
|
+
decision: 'deny',
|
|
53
|
+
blockReason: `SLOPE subagent-gate: ${subagentType} agent blocked — model "${model}" not in allowed list [${allowedModels.join(', ')}]. Resubmit with model: ${allowedModels[0]}.`,
|
|
54
|
+
};
|
|
57
55
|
}
|
|
58
|
-
|
|
59
|
-
const current = maxTurns === undefined ? 'not set' : `${maxTurns}`;
|
|
60
|
-
violations.push(`max_turns ${current}, limit is ${turnsLimit}`);
|
|
61
|
-
}
|
|
62
|
-
if (violations.length === 0)
|
|
63
|
-
return { context: buildOrientation(_cwd) };
|
|
64
|
-
return {
|
|
65
|
-
decision: 'deny',
|
|
66
|
-
blockReason: `SLOPE subagent-gate: ${subagentType} agent blocked — ${violations.join('; ')}. Resubmit with model: ${allowedModels[0]}, max_turns: ${turnsLimit}.`,
|
|
67
|
-
};
|
|
56
|
+
return { context: buildOrientation(_cwd) };
|
|
68
57
|
}
|
|
69
58
|
//# sourceMappingURL=subagent-gate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-gate.js","sourceRoot":"","sources":["../../../src/cli/guards/subagent-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,gBAAgB,GACpB,0JAA0J,CAAC;AAE7J,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QACzC,0DAA0D;QAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC/C,SAAS,CAAC,EAAE,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAEhD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS;YAAE,OAAO,gBAAgB,CAAC;QAExC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,OAAO,GAAG,CAAC,GAAW,EAAsB,EAAE,CAClD,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAEnD,MAAM,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QAEpC,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,eAAe,EAAE,MAAM,IAAI,GAAG,MAAM,SAAS,EAAE,KAAK,IAAI,GAAG,KAAK,aAAa,EAAE,GAAG,IAAI,GAAG,GAAG,eAAe,CAAC;aACvI,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO,2GAA2G,KAAK,wHAAwH,CAAC;IAClP,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAgB,EAAE,IAAY;IACpE,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;IACzC,MAAM,YAAY,GAAG,SAAS,CAAC,aAAmC,CAAC;IACnE,MAAM,KAAK,GAAG,SAAS,CAAC,KAA2B,CAAC;IACpD,MAAM,
|
|
1
|
+
{"version":3,"file":"subagent-gate.js","sourceRoot":"","sources":["../../../src/cli/guards/subagent-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,gBAAgB,GACpB,0JAA0J,CAAC;AAE7J,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QACzC,0DAA0D;QAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC/C,SAAS,CAAC,EAAE,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAEhD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS;YAAE,OAAO,gBAAgB,CAAC;QAExC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,OAAO,GAAG,CAAC,GAAW,EAAsB,EAAE,CAClD,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAEnD,MAAM,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QAEpC,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,eAAe,EAAE,MAAM,IAAI,GAAG,MAAM,SAAS,EAAE,KAAK,IAAI,GAAG,KAAK,aAAa,EAAE,GAAG,IAAI,GAAG,GAAG,eAAe,CAAC;aACvI,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO,2GAA2G,KAAK,wHAAwH,CAAC;IAClP,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAgB,EAAE,IAAY;IACpE,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;IACzC,MAAM,YAAY,GAAG,SAAS,CAAC,aAAmC,CAAC;IACnE,MAAM,KAAK,GAAG,SAAS,CAAC,KAA2B,CAAC;IACpD,MAAM,MAAM,GAAG,SAAS,CAAC,MAA4B,CAAC;IAEtD,sDAAsD;IACtD,IAAI,MAAM;QAAE,OAAO,EAAE,CAAC;IAEtB,uCAAuC;IACvC,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,MAAM;QAAE,OAAO,EAAE,CAAC;IAErE,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACvC,MAAM,aAAa,GAAG,QAAQ,CAAC,mBAAmB,IAAI,CAAC,OAAO,CAAC,CAAC;IAEhE,IAAI,KAAK,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE,wBAAwB,YAAY,2BAA2B,KAAK,0BAA0B,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,2BAA2B,aAAa,CAAC,CAAC,CAAC,GAAG;SAClL,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7C,CAAC"}
|