@open-agent-toolkit/cli 0.1.30 → 0.1.32
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/assets/docs/cli-utilities/config-and-local-state.md +18 -5
- package/assets/docs/cli-utilities/tool-packs.md +13 -8
- package/assets/docs/reference/cli-reference.md +14 -13
- package/assets/docs/reference/file-locations.md +2 -1
- package/assets/docs/reference/oat-directory-structure.md +35 -22
- package/assets/migration/pjm-restructure.md +500 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/deep-research/SKILL.md +2 -2
- package/assets/skills/oat-brainstorm/SKILL.md +3 -3
- package/assets/skills/oat-brainstorm/references/destinations.md +10 -2
- package/assets/skills/oat-brainstorm/references/dogfood-results.md +4 -4
- package/assets/skills/oat-pjm-add-backlog-item/SKILL.md +17 -20
- package/assets/skills/oat-pjm-decision/SKILL.md +129 -0
- package/assets/skills/oat-pjm-review-backlog/SKILL.md +17 -17
- package/assets/skills/oat-pjm-review-backlog/references/backlog-review-template.md +2 -2
- package/assets/skills/oat-pjm-review-backlog/references/priority-alignment-template.md +13 -13
- package/assets/skills/oat-pjm-update-repo-reference/SKILL.md +34 -25
- package/assets/skills/oat-project-complete/SKILL.md +2 -2
- package/assets/skills/oat-project-document/SKILL.md +4 -3
- package/assets/skills/oat-project-import-plan/SKILL.md +2 -2
- package/assets/skills/oat-project-summary/SKILL.md +76 -8
- package/assets/templates/backlog-item.md +1 -1
- package/assets/templates/current-state.md +11 -2
- package/assets/templates/decision.md +18 -0
- package/assets/templates/pjm-agents.md +13 -0
- package/assets/templates/reference-agents.md +14 -0
- package/assets/templates/repo-agents.md +13 -0
- package/assets/templates/roadmap.md +8 -3
- package/dist/commands/backlog/index.d.ts +1 -0
- package/dist/commands/backlog/index.d.ts.map +1 -1
- package/dist/commands/backlog/index.js +48 -11
- package/dist/commands/backlog/init.js +1 -1
- package/dist/commands/backlog/regenerate-index.d.ts.map +1 -1
- package/dist/commands/backlog/regenerate-index.js +24 -5
- package/dist/commands/backlog/shared/generate-id.d.ts +1 -3
- package/dist/commands/backlog/shared/generate-id.d.ts.map +1 -1
- package/dist/commands/backlog/shared/generate-id.js +4 -64
- package/dist/commands/cleanup/artifacts/artifacts.d.ts.map +1 -1
- package/dist/commands/cleanup/artifacts/artifacts.js +4 -1
- package/dist/commands/decision/index.d.ts +20 -0
- package/dist/commands/decision/index.d.ts.map +1 -0
- package/dist/commands/decision/index.js +177 -0
- package/dist/commands/decision/init.d.ts +7 -0
- package/dist/commands/decision/init.d.ts.map +1 -0
- package/dist/commands/decision/init.js +53 -0
- package/dist/commands/decision/migrate.d.ts +24 -0
- package/dist/commands/decision/migrate.d.ts.map +1 -0
- package/dist/commands/decision/migrate.js +270 -0
- package/dist/commands/decision/new.d.ts +16 -0
- package/dist/commands/decision/new.d.ts.map +1 -0
- package/dist/commands/decision/new.js +118 -0
- package/dist/commands/decision/regenerate-index.d.ts +14 -0
- package/dist/commands/decision/regenerate-index.d.ts.map +1 -0
- package/dist/commands/decision/regenerate-index.js +122 -0
- package/dist/commands/decision/shared/generate-id.d.ts +2 -0
- package/dist/commands/decision/shared/generate-id.d.ts.map +1 -0
- package/dist/commands/decision/shared/generate-id.js +5 -0
- package/dist/commands/doctor/index.d.ts +2 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +6 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/init/tools/shared/skill-manifest.d.ts +2 -2
- package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
- package/dist/commands/init/tools/shared/skill-manifest.js +5 -1
- package/dist/commands/pjm/doctor.d.ts +3 -0
- package/dist/commands/pjm/doctor.d.ts.map +1 -0
- package/dist/commands/pjm/doctor.js +238 -0
- package/dist/commands/pjm/index.d.ts +7 -0
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +132 -10
- package/dist/commands/pjm/init.d.ts +3 -2
- package/dist/commands/pjm/init.d.ts.map +1 -1
- package/dist/commands/pjm/init.js +42 -33
- package/dist/commands/pjm/migrate.d.ts +36 -0
- package/dist/commands/pjm/migrate.d.ts.map +1 -0
- package/dist/commands/pjm/migrate.js +393 -0
- package/dist/commands/shared/date-id.d.ts +2 -0
- package/dist/commands/shared/date-id.d.ts.map +1 -0
- package/dist/commands/shared/date-id.js +10 -0
- package/dist/commands/shared/managed-index.d.ts +22 -0
- package/dist/commands/shared/managed-index.d.ts.map +1 -0
- package/dist/commands/shared/managed-index.js +92 -0
- package/dist/commands/shared/slug.d.ts +2 -0
- package/dist/commands/shared/slug.d.ts.map +1 -0
- package/dist/commands/shared/slug.js +57 -0
- package/dist/commands/shared/strip-template-frontmatter.d.ts +2 -0
- package/dist/commands/shared/strip-template-frontmatter.d.ts.map +1 -0
- package/dist/commands/shared/strip-template-frontmatter.js +16 -0
- package/dist/engine/hook.d.ts.map +1 -1
- package/dist/engine/hook.js +13 -0
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +10 -1
- package/package.json +2 -2
- package/assets/templates/decision-record.md +0 -21
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const DECISION_INDEX_START = "<!-- OAT DECISION-INDEX -->";
|
|
2
|
+
export declare const DECISION_INDEX_END = "<!-- END OAT DECISION-INDEX -->";
|
|
3
|
+
interface DecisionIndexRecord {
|
|
4
|
+
id: string;
|
|
5
|
+
date: string;
|
|
6
|
+
status: string;
|
|
7
|
+
title: string;
|
|
8
|
+
legacyId: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function assertDecisionIndexScaffold(decisionsRoot: string): Promise<void>;
|
|
11
|
+
export declare function renderDecisionManagedSection(records: DecisionIndexRecord[]): string;
|
|
12
|
+
export declare function regenerateDecisionIndex(decisionsRoot: string): Promise<void>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=regenerate-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regenerate-index.d.ts","sourceRoot":"","sources":["../../../src/commands/decision/regenerate-index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,gCAAgC,CAAC;AAClE,eAAO,MAAM,kBAAkB,oCAAoC,CAAC;AAEpE,UAAU,mBAAmB;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AA2GD,wBAAsB,2BAA2B,CAC/C,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mBAAmB,EAAE,GAC7B,MAAM,CAgBR;AAED,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CA0Cf"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { readdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { getFrontmatterBlock } from '../shared/frontmatter.js';
|
|
4
|
+
import { computeManagedIndexUpdate } from '../shared/managed-index.js';
|
|
5
|
+
import YAML from 'yaml';
|
|
6
|
+
export const DECISION_INDEX_START = '<!-- OAT DECISION-INDEX -->';
|
|
7
|
+
export const DECISION_INDEX_END = '<!-- END OAT DECISION-INDEX -->';
|
|
8
|
+
function parseDecisionFrontmatter(content, filePath) {
|
|
9
|
+
const rawFrontmatter = getFrontmatterBlock(content);
|
|
10
|
+
if (!rawFrontmatter) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const parsed = YAML.parse(rawFrontmatter);
|
|
14
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
15
|
+
throw new Error(`Frontmatter in ${filePath} must be a YAML object.`);
|
|
16
|
+
}
|
|
17
|
+
const frontmatter = parsed;
|
|
18
|
+
return {
|
|
19
|
+
id: String(frontmatter.id ?? ''),
|
|
20
|
+
date: String(frontmatter.date ?? ''),
|
|
21
|
+
status: String(frontmatter.status ?? ''),
|
|
22
|
+
title: String(frontmatter.title ?? ''),
|
|
23
|
+
legacyId: frontmatter.legacy_id === null || frontmatter.legacy_id === undefined
|
|
24
|
+
? ''
|
|
25
|
+
: String(frontmatter.legacy_id),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function compareRecords(a, b) {
|
|
29
|
+
if (a.date > b.date) {
|
|
30
|
+
return -1;
|
|
31
|
+
}
|
|
32
|
+
if (a.date < b.date) {
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
if (a.id < b.id) {
|
|
36
|
+
return -1;
|
|
37
|
+
}
|
|
38
|
+
if (a.id > b.id) {
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
function formatCell(value) {
|
|
44
|
+
const trimmed = value.trim();
|
|
45
|
+
if (trimmed.length === 0) {
|
|
46
|
+
return '-';
|
|
47
|
+
}
|
|
48
|
+
return trimmed.replace(/\r?\n/g, ' ').replace(/\|/g, '\\|');
|
|
49
|
+
}
|
|
50
|
+
function isMissingFileError(error) {
|
|
51
|
+
return (error !== null &&
|
|
52
|
+
typeof error === 'object' &&
|
|
53
|
+
'code' in error &&
|
|
54
|
+
error.code === 'ENOENT');
|
|
55
|
+
}
|
|
56
|
+
async function readDecisionIndex(decisionsRoot) {
|
|
57
|
+
const indexPath = join(decisionsRoot, 'index.md');
|
|
58
|
+
try {
|
|
59
|
+
return {
|
|
60
|
+
content: await readFile(indexPath, 'utf8'),
|
|
61
|
+
indexPath,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (isMissingFileError(error)) {
|
|
66
|
+
throw new Error(`Decision index scaffold is missing at ${indexPath}. Run \`oat decision init\` before creating or regenerating decision records.`, { cause: error });
|
|
67
|
+
}
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function findManagedSectionBounds(content, indexPath) {
|
|
72
|
+
const startIndex = content.indexOf(DECISION_INDEX_START);
|
|
73
|
+
const endIndex = content.indexOf(DECISION_INDEX_END);
|
|
74
|
+
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
|
|
75
|
+
throw new Error(`Managed decision index markers missing in ${indexPath}. Expected the exact marker pair:\n${DECISION_INDEX_START}\n${DECISION_INDEX_END}\nRun \`oat decision init\` if the decision scaffold is missing, or restore those exact markers in \`decisions/index.md\` before rerunning \`oat decision regenerate-index\`.`);
|
|
76
|
+
}
|
|
77
|
+
return { startIndex, endIndex };
|
|
78
|
+
}
|
|
79
|
+
export async function assertDecisionIndexScaffold(decisionsRoot) {
|
|
80
|
+
const { content, indexPath } = await readDecisionIndex(decisionsRoot);
|
|
81
|
+
findManagedSectionBounds(content, indexPath);
|
|
82
|
+
}
|
|
83
|
+
export function renderDecisionManagedSection(records) {
|
|
84
|
+
const rows = records.length > 0
|
|
85
|
+
? records.map((record) => `| ${formatCell(record.id)} | ${formatCell(record.date)} | ${formatCell(record.status)} | ${formatCell(record.title)} | ${formatCell(record.legacyId)} |`)
|
|
86
|
+
: ['| _No decisions yet_ | - | - | - | - |'];
|
|
87
|
+
return [
|
|
88
|
+
DECISION_INDEX_START,
|
|
89
|
+
'| ID | Date | Status | Title | Legacy |',
|
|
90
|
+
'| --- | --- | --- | --- | --- |',
|
|
91
|
+
...rows,
|
|
92
|
+
DECISION_INDEX_END,
|
|
93
|
+
].join('\n');
|
|
94
|
+
}
|
|
95
|
+
export async function regenerateDecisionIndex(decisionsRoot) {
|
|
96
|
+
const { content, indexPath } = await readDecisionIndex(decisionsRoot);
|
|
97
|
+
const { startIndex, endIndex } = findManagedSectionBounds(content, indexPath);
|
|
98
|
+
const entries = (await readdir(decisionsRoot, { withFileTypes: true }))
|
|
99
|
+
.filter((entry) => entry.isFile() &&
|
|
100
|
+
entry.name.endsWith('.md') &&
|
|
101
|
+
entry.name !== 'index.md')
|
|
102
|
+
.map((entry) => entry.name)
|
|
103
|
+
.sort();
|
|
104
|
+
const records = [];
|
|
105
|
+
for (const entry of entries) {
|
|
106
|
+
const filePath = join(decisionsRoot, entry);
|
|
107
|
+
const record = parseDecisionFrontmatter(await readFile(filePath, 'utf8'), filePath);
|
|
108
|
+
if (record) {
|
|
109
|
+
records.push(record);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
records.sort(compareRecords);
|
|
113
|
+
// Content-idempotent gate: when the on-disk managed block is logically equal
|
|
114
|
+
// to the freshly rendered block (cells equal after trimming, so external
|
|
115
|
+
// formatter padding is ignored), preserve the existing bytes and skip the
|
|
116
|
+
// write. Only rewrite on a genuine content change.
|
|
117
|
+
const { content: updated } = computeManagedIndexUpdate(content, startIndex, endIndex + DECISION_INDEX_END.length, renderDecisionManagedSection(records));
|
|
118
|
+
if (updated === null) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await writeFile(indexPath, updated, 'utf8');
|
|
122
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-id.d.ts","sourceRoot":"","sources":["../../../../src/commands/decision/shared/generate-id.ts"],"names":[],"mappings":"AAGA,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,CAER"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
2
|
import { type Manifest } from '../../manifest/index.js';
|
|
3
3
|
import type { ConcreteScope } from '../../shared/types.js';
|
|
4
|
+
import { type DoctorCheck } from '../../ui/output.js';
|
|
4
5
|
import { Command } from 'commander';
|
|
5
6
|
interface DoctorDependencies {
|
|
6
7
|
buildCommandContext: (options: GlobalOptions) => CommandContext;
|
|
@@ -15,6 +16,7 @@ interface DoctorDependencies {
|
|
|
15
16
|
}>>;
|
|
16
17
|
readFile: (path: string) => Promise<string>;
|
|
17
18
|
resolveAssetsRoot: () => Promise<string>;
|
|
19
|
+
runPjmDoctorChecks: (repoRoot: string) => Promise<DoctorCheck[]>;
|
|
18
20
|
checkSkillVersions: (scopeRoot: string, assetsRoot: string, pathExists: (path: string) => Promise<boolean>) => Promise<SkillVersionReport>;
|
|
19
21
|
}
|
|
20
22
|
interface OutdatedSkillVersion {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAW9B,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAM9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,cAAc,EAAE,CACd,SAAS,EAAE,MAAM,KACd,OAAO,CACV,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CACnE,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,kBAAkB,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClC;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,cAAc,EAAE,oBAAoB,EAAE,CAAC;CACxC;AA8aD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAC1C,OAAO,CAcT"}
|
|
@@ -3,6 +3,7 @@ import { tmpdir } from 'node:os';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
5
5
|
import { compareVersions } from '../init/tools/shared/version.js';
|
|
6
|
+
import { runPjmDoctorChecks } from '../pjm/doctor.js';
|
|
6
7
|
import { getSkillVersion } from '../shared/frontmatter.js';
|
|
7
8
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
8
9
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
@@ -125,6 +126,7 @@ function createDependencies() {
|
|
|
125
126
|
checkProviders: checkProvidersDefault,
|
|
126
127
|
readFile: async (path) => readFile(path, 'utf8'),
|
|
127
128
|
resolveAssetsRoot,
|
|
129
|
+
runPjmDoctorChecks,
|
|
128
130
|
// Default binding remains self-contained, but still honors the caller-
|
|
129
131
|
// provided pathExists dependency from runChecksForScope when available.
|
|
130
132
|
checkSkillVersions: (scopeRoot, assetsRoot, pathExists = pathExistsDefault) => checkSkillVersionsDefault(scopeRoot, assetsRoot, pathExists),
|
|
@@ -339,6 +341,10 @@ async function runChecksForScope(scope, scopeRoot, dependencies) {
|
|
|
339
341
|
}
|
|
340
342
|
}
|
|
341
343
|
}
|
|
344
|
+
const repoReferenceRoot = join(scopeRoot, '.oat', 'repo');
|
|
345
|
+
if (await dependencies.pathExists(repoReferenceRoot)) {
|
|
346
|
+
checks.push(...(await dependencies.runPjmDoctorChecks(repoReferenceRoot)));
|
|
347
|
+
}
|
|
342
348
|
}
|
|
343
349
|
return checks;
|
|
344
350
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBzC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsBvD"}
|
package/dist/commands/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createBacklogCommand } from './backlog/index.js';
|
|
2
2
|
import { createCleanupCommand } from './cleanup/index.js';
|
|
3
3
|
import { createConfigCommand } from './config/index.js';
|
|
4
|
+
import { createDecisionCommand } from './decision/index.js';
|
|
4
5
|
import { createDocsCommand } from './docs/index.js';
|
|
5
6
|
import { createDoctorCommand } from './doctor/index.js';
|
|
6
7
|
import { createIndexCommand } from './index-cmd/index.js';
|
|
@@ -20,6 +21,7 @@ import { createSyncCommand } from './sync/index.js';
|
|
|
20
21
|
import { createToolsCommand } from './tools/index.js';
|
|
21
22
|
export function registerCommands(program) {
|
|
22
23
|
program.addCommand(createBacklogCommand());
|
|
24
|
+
program.addCommand(createDecisionCommand());
|
|
23
25
|
program.addCommand(createInitCommand());
|
|
24
26
|
program.addCommand(createStatusCommand());
|
|
25
27
|
program.addCommand(createSyncCommand());
|
|
@@ -20,8 +20,8 @@ export declare const CORE_SKILLS: readonly ["oat-docs", "oat-doctor"];
|
|
|
20
20
|
export declare const DOCS_SKILLS: readonly ["authoring-docs", "oat-agent-instructions-analyze", "oat-agent-instructions-apply", "oat-docs-analyze", "oat-docs-apply", "oat-docs-authoring", "oat-docs-bootstrap"];
|
|
21
21
|
export declare const DOCS_SCRIPTS: readonly ["resolve-tracking.sh"];
|
|
22
22
|
export declare const UTILITY_SKILLS: readonly ["create-agnostic-skill", "oat-repo-maintainability-review", "oat-review-provide", "oat-review-provide-remote", "oat-review-receive", "oat-review-receive-remote"];
|
|
23
|
-
export declare const PROJECT_MANAGEMENT_SKILLS: readonly ["oat-pjm-add-backlog-item", "oat-pjm-update-repo-reference", "oat-pjm-review-backlog"];
|
|
24
|
-
export declare const PROJECT_MANAGEMENT_TEMPLATES: readonly ["backlog-item.md", "roadmap.md", "current-state.md", "decision-
|
|
23
|
+
export declare const PROJECT_MANAGEMENT_SKILLS: readonly ["oat-pjm-add-backlog-item", "oat-pjm-decision", "oat-pjm-update-repo-reference", "oat-pjm-review-backlog"];
|
|
24
|
+
export declare const PROJECT_MANAGEMENT_TEMPLATES: readonly ["backlog-item.md", "roadmap.md", "current-state.md", "decision.md", "repo-agents.md", "pjm-agents.md", "reference-agents.md"];
|
|
25
25
|
export declare const PROJECT_MANAGEMENT_SCRIPTS: readonly [];
|
|
26
26
|
export declare const BRAINSTORM_SKILLS: readonly ["oat-brainstorm"];
|
|
27
27
|
export declare const RESEARCH_SKILLS: readonly ["analyze", "compare", "deep-research", "skeptic", "synthesize"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-manifest.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/shared/skill-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAKtD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5E;AAID,eAAO,MAAM,eAAe,6xBAgClB,CAAC;AAEX,eAAO,MAAM,eAAe,oFAIlB,CAAC;AAEX,eAAO,MAAM,kBAAkB,6GAQrB,CAAC;AAEX,eAAO,MAAM,gBAAgB,qFAInB,CAAC;AAIX,eAAO,MAAM,WAAW,2FAKd,CAAC;AAIX,eAAO,MAAM,WAAW,qCAAsC,CAAC;AAI/D,eAAO,MAAM,WAAW,iLAQd,CAAC;AAEX,eAAO,MAAM,YAAY,kCAAmC,CAAC;AAI7D,eAAO,MAAM,cAAc,6KAOjB,CAAC;AAIX,eAAO,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"skill-manifest.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/shared/skill-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAKtD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5E;AAID,eAAO,MAAM,eAAe,6xBAgClB,CAAC;AAEX,eAAO,MAAM,eAAe,oFAIlB,CAAC;AAEX,eAAO,MAAM,kBAAkB,6GAQrB,CAAC;AAEX,eAAO,MAAM,gBAAgB,qFAInB,CAAC;AAIX,eAAO,MAAM,WAAW,2FAKd,CAAC;AAIX,eAAO,MAAM,WAAW,qCAAsC,CAAC;AAI/D,eAAO,MAAM,WAAW,iLAQd,CAAC;AAEX,eAAO,MAAM,YAAY,kCAAmC,CAAC;AAI7D,eAAO,MAAM,cAAc,6KAOjB,CAAC;AAIX,eAAO,MAAM,yBAAyB,sHAK5B,CAAC;AAEX,eAAO,MAAM,4BAA4B,yIAQ/B,CAAC;AAEX,eAAO,MAAM,0BAA0B,aAAc,CAAC;AAItD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAI7D,eAAO,MAAM,eAAe,2EAMlB,CAAC;AAEX,eAAO,MAAM,eAAe,qCAAsC,CAAC"}
|
|
@@ -99,6 +99,7 @@ export const UTILITY_SKILLS = [
|
|
|
99
99
|
// ── Project management pack ───────────────────────────────────────
|
|
100
100
|
export const PROJECT_MANAGEMENT_SKILLS = [
|
|
101
101
|
'oat-pjm-add-backlog-item',
|
|
102
|
+
'oat-pjm-decision',
|
|
102
103
|
'oat-pjm-update-repo-reference',
|
|
103
104
|
'oat-pjm-review-backlog',
|
|
104
105
|
];
|
|
@@ -106,7 +107,10 @@ export const PROJECT_MANAGEMENT_TEMPLATES = [
|
|
|
106
107
|
'backlog-item.md',
|
|
107
108
|
'roadmap.md',
|
|
108
109
|
'current-state.md',
|
|
109
|
-
'decision
|
|
110
|
+
'decision.md',
|
|
111
|
+
'repo-agents.md',
|
|
112
|
+
'pjm-agents.md',
|
|
113
|
+
'reference-agents.md',
|
|
110
114
|
];
|
|
111
115
|
export const PROJECT_MANAGEMENT_SCRIPTS = [];
|
|
112
116
|
// ── Brainstorm pack ───────────────────────────────────────────────
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/doctor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA0I9C,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,EAAE,CAAC,CAqJxB"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { access, readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { getFrontmatterBlock } from '../shared/frontmatter.js';
|
|
4
|
+
import { CANONICAL_REPO_REFERENCE_PATHS } from './init.js';
|
|
5
|
+
const ALLOWED_TOP_LEVEL_DIRECTORIES = new Set([
|
|
6
|
+
'pjm',
|
|
7
|
+
'reference',
|
|
8
|
+
'knowledge',
|
|
9
|
+
'analysis',
|
|
10
|
+
'reviews',
|
|
11
|
+
]);
|
|
12
|
+
// A human-facing `README.md` at the repo-reference root is benign, so it is an
|
|
13
|
+
// allowed top-level file alongside the canonical `AGENTS.md` (F5).
|
|
14
|
+
const ALLOWED_TOP_LEVEL_FILES = new Set(['AGENTS.md', 'README.md']);
|
|
15
|
+
const LEGACY_MONOLITHS = ['reference/decision-record.md'];
|
|
16
|
+
async function pathExists(path) {
|
|
17
|
+
try {
|
|
18
|
+
await access(path);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
const code = error && typeof error === 'object' && 'code' in error
|
|
23
|
+
? String(error.code)
|
|
24
|
+
: null;
|
|
25
|
+
if (code !== 'ENOENT') {
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function readIfExists(path) {
|
|
32
|
+
try {
|
|
33
|
+
return await readFile(path, 'utf8');
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const code = error && typeof error === 'object' && 'code' in error
|
|
37
|
+
? String(error.code)
|
|
38
|
+
: null;
|
|
39
|
+
if (code !== 'ENOENT') {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function listDirectoryNames(path) {
|
|
46
|
+
try {
|
|
47
|
+
return (await readdir(path, { withFileTypes: true }))
|
|
48
|
+
.filter((entry) => entry.isDirectory() || entry.isFile())
|
|
49
|
+
.map((entry) => entry.name)
|
|
50
|
+
.sort();
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const code = error && typeof error === 'object' && 'code' in error
|
|
54
|
+
? String(error.code)
|
|
55
|
+
: null;
|
|
56
|
+
if (code !== 'ENOENT') {
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function listMarkdownFiles(path) {
|
|
63
|
+
try {
|
|
64
|
+
return (await readdir(path, { withFileTypes: true }))
|
|
65
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.md'))
|
|
66
|
+
.map((entry) => entry.name)
|
|
67
|
+
.sort();
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const code = error && typeof error === 'object' && 'code' in error
|
|
71
|
+
? String(error.code)
|
|
72
|
+
: null;
|
|
73
|
+
if (code !== 'ENOENT') {
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Migrated record directories (relative to the repo-reference root) that hold
|
|
80
|
+
// per-record markdown files and must not retain raw template frontmatter after
|
|
81
|
+
// `oat pjm migrate`. `index.md` is the managed index, not an instantiated
|
|
82
|
+
// record, so it is excluded.
|
|
83
|
+
const MIGRATED_RECORD_DIRECTORIES = [
|
|
84
|
+
'pjm/backlog/items',
|
|
85
|
+
'pjm/backlog/archived',
|
|
86
|
+
'reference/decisions',
|
|
87
|
+
];
|
|
88
|
+
async function collectMigratedTemplateFrontmatterFiles(repoRoot) {
|
|
89
|
+
const offenders = [];
|
|
90
|
+
for (const relativeDir of MIGRATED_RECORD_DIRECTORIES) {
|
|
91
|
+
const fileNames = await listMarkdownFiles(join(repoRoot, relativeDir));
|
|
92
|
+
for (const fileName of fileNames) {
|
|
93
|
+
if (fileName === 'index.md') {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const relativePath = `${relativeDir}/${fileName}`;
|
|
97
|
+
const content = await readIfExists(join(repoRoot, relativeDir, fileName));
|
|
98
|
+
if (content && containsTemplateFrontmatter(content)) {
|
|
99
|
+
offenders.push(relativePath);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return offenders;
|
|
104
|
+
}
|
|
105
|
+
function containsTemplateFrontmatter(content) {
|
|
106
|
+
const frontmatter = getFrontmatterBlock(content);
|
|
107
|
+
return Boolean(frontmatter &&
|
|
108
|
+
(/\boat_template\s*:/i.test(frontmatter) ||
|
|
109
|
+
/\boat_template_name\s*:/i.test(frontmatter)));
|
|
110
|
+
}
|
|
111
|
+
function checkStatus(missing) {
|
|
112
|
+
return missing.length === 0 ? 'pass' : 'fail';
|
|
113
|
+
}
|
|
114
|
+
function warnStatus(items) {
|
|
115
|
+
return items.length === 0 ? 'pass' : 'warn';
|
|
116
|
+
}
|
|
117
|
+
export async function runPjmDoctorChecks(repoRoot) {
|
|
118
|
+
const checks = [];
|
|
119
|
+
const missingCanonical = [];
|
|
120
|
+
for (const relativePath of CANONICAL_REPO_REFERENCE_PATHS) {
|
|
121
|
+
if (!(await pathExists(join(repoRoot, relativePath)))) {
|
|
122
|
+
missingCanonical.push(relativePath);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
checks.push({
|
|
126
|
+
name: 'pjm:canonical_files',
|
|
127
|
+
description: 'PJM canonical file existence',
|
|
128
|
+
status: checkStatus(missingCanonical),
|
|
129
|
+
message: missingCanonical.length === 0
|
|
130
|
+
? 'Canonical PJM files are present.'
|
|
131
|
+
: `Missing canonical PJM files: ${missingCanonical.join(', ')}`,
|
|
132
|
+
fix: missingCanonical.length === 0
|
|
133
|
+
? undefined
|
|
134
|
+
: 'Run `oat pjm init` to restore the canonical PJM scaffold.',
|
|
135
|
+
});
|
|
136
|
+
const templateFrontmatterFiles = [];
|
|
137
|
+
for (const relativePath of CANONICAL_REPO_REFERENCE_PATHS) {
|
|
138
|
+
if (!relativePath.endsWith('.md')) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const content = await readIfExists(join(repoRoot, relativePath));
|
|
142
|
+
if (content && containsTemplateFrontmatter(content)) {
|
|
143
|
+
templateFrontmatterFiles.push(relativePath);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Also scan migrated per-record files (backlog items/archived, decision
|
|
147
|
+
// records). Dogfooding surfaced that `oat pjm migrate` could leave raw
|
|
148
|
+
// `oat_template` frontmatter on migrated records while doctor only inspected
|
|
149
|
+
// the canonical scaffold and reported a false `pass`.
|
|
150
|
+
const migratedTemplateFiles = await collectMigratedTemplateFrontmatterFiles(repoRoot);
|
|
151
|
+
for (const relativePath of migratedTemplateFiles) {
|
|
152
|
+
if (!templateFrontmatterFiles.includes(relativePath)) {
|
|
153
|
+
templateFrontmatterFiles.push(relativePath);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
checks.push({
|
|
157
|
+
name: 'pjm:template_frontmatter',
|
|
158
|
+
description: 'Instantiated PJM files are not raw templates',
|
|
159
|
+
status: checkStatus(templateFrontmatterFiles),
|
|
160
|
+
message: templateFrontmatterFiles.length === 0
|
|
161
|
+
? 'No template frontmatter found in canonical PJM files.'
|
|
162
|
+
: `Template frontmatter still present in: ${templateFrontmatterFiles.join(', ')}`,
|
|
163
|
+
fix: templateFrontmatterFiles.length === 0
|
|
164
|
+
? undefined
|
|
165
|
+
: 'Regenerate or manually remove oat_template frontmatter from instantiated files.',
|
|
166
|
+
});
|
|
167
|
+
const topLevelNames = await listDirectoryNames(repoRoot);
|
|
168
|
+
const unknownTopLevel = topLevelNames.filter((name) => !ALLOWED_TOP_LEVEL_DIRECTORIES.has(name) &&
|
|
169
|
+
!ALLOWED_TOP_LEVEL_FILES.has(name));
|
|
170
|
+
checks.push({
|
|
171
|
+
name: 'pjm:top_level_layout',
|
|
172
|
+
description: 'PJM top-level repo-reference layout',
|
|
173
|
+
status: warnStatus(unknownTopLevel),
|
|
174
|
+
message: unknownTopLevel.length === 0
|
|
175
|
+
? 'No unknown top-level PJM folders or files found.'
|
|
176
|
+
: `Unknown top-level PJM entries: ${unknownTopLevel.join(', ')}`,
|
|
177
|
+
fix: unknownTopLevel.length === 0
|
|
178
|
+
? undefined
|
|
179
|
+
: 'Move ad-hoc durable references under reference/ or document an allowed top-level folder.',
|
|
180
|
+
});
|
|
181
|
+
const legacyMonoliths = [];
|
|
182
|
+
for (const relativePath of LEGACY_MONOLITHS) {
|
|
183
|
+
if (await pathExists(join(repoRoot, relativePath))) {
|
|
184
|
+
legacyMonoliths.push(relativePath);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
checks.push({
|
|
188
|
+
name: 'pjm:legacy_monoliths',
|
|
189
|
+
description: 'Legacy PJM monolith files',
|
|
190
|
+
status: warnStatus(legacyMonoliths),
|
|
191
|
+
message: legacyMonoliths.length === 0
|
|
192
|
+
? 'No legacy PJM monolith files found.'
|
|
193
|
+
: `Legacy PJM monoliths still present: ${legacyMonoliths.join(', ')}`,
|
|
194
|
+
fix: legacyMonoliths.length === 0
|
|
195
|
+
? undefined
|
|
196
|
+
: 'Run `oat decision migrate` or keep the file explicitly documented as legacy.',
|
|
197
|
+
});
|
|
198
|
+
const referenceEntries = await listDirectoryNames(join(repoRoot, 'reference'));
|
|
199
|
+
const looseReferenceFiles = referenceEntries
|
|
200
|
+
.filter((name) => name.endsWith('.md'))
|
|
201
|
+
.filter((name) => name !== 'AGENTS.md' &&
|
|
202
|
+
name !== 'decision-record.md' &&
|
|
203
|
+
name !== 'roadmap.md' &&
|
|
204
|
+
name !== 'current-state.md')
|
|
205
|
+
.map((name) => `reference/${name}`);
|
|
206
|
+
checks.push({
|
|
207
|
+
name: 'pjm:loose_reference_files',
|
|
208
|
+
description: 'Loose reference files outside documented destinations',
|
|
209
|
+
status: warnStatus(looseReferenceFiles),
|
|
210
|
+
message: looseReferenceFiles.length === 0
|
|
211
|
+
? 'No loose reference files found.'
|
|
212
|
+
: `Loose reference files found: ${looseReferenceFiles.join(', ')}`,
|
|
213
|
+
fix: looseReferenceFiles.length === 0
|
|
214
|
+
? undefined
|
|
215
|
+
: 'Move loose files into a documented reference subfolder or add a destination guide.',
|
|
216
|
+
});
|
|
217
|
+
const secondRoadmaps = [];
|
|
218
|
+
for (const relativePath of [
|
|
219
|
+
'reference/roadmap.md',
|
|
220
|
+
'reference/current-state.md',
|
|
221
|
+
]) {
|
|
222
|
+
if (await pathExists(join(repoRoot, relativePath))) {
|
|
223
|
+
secondRoadmaps.push(relativePath);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
checks.push({
|
|
227
|
+
name: 'pjm:second_roadmap',
|
|
228
|
+
description: 'Duplicate active PJM files under reference',
|
|
229
|
+
status: warnStatus(secondRoadmaps),
|
|
230
|
+
message: secondRoadmaps.length === 0
|
|
231
|
+
? 'No duplicate roadmap/current-state files found under reference/.'
|
|
232
|
+
: `Duplicate active PJM files under reference/: ${secondRoadmaps.join(', ')}`,
|
|
233
|
+
fix: secondRoadmaps.length === 0
|
|
234
|
+
? undefined
|
|
235
|
+
: 'Move active operational docs to pjm/ and leave reference/ for durable append-mostly artifacts.',
|
|
236
|
+
});
|
|
237
|
+
return checks;
|
|
238
|
+
}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { buildCommandContext } from '../../app/command-context.js';
|
|
2
|
+
import { readOatConfig } from '../../config/oat-config.js';
|
|
2
3
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
3
4
|
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
4
5
|
import { Command } from 'commander';
|
|
6
|
+
import { runPjmDoctorChecks } from './doctor.js';
|
|
5
7
|
import { initializeRepoReference } from './init.js';
|
|
8
|
+
import { migratePjmRepo, readPjmMigrationPrompt } from './migrate.js';
|
|
6
9
|
interface PjmCommandDependencies {
|
|
7
10
|
buildCommandContext: typeof buildCommandContext;
|
|
8
11
|
resolveProjectRoot: typeof resolveProjectRoot;
|
|
9
12
|
resolveAssetsRoot: typeof resolveAssetsRoot;
|
|
13
|
+
readOatConfig: typeof readOatConfig;
|
|
10
14
|
initializeRepoReference: typeof initializeRepoReference;
|
|
15
|
+
runPjmDoctorChecks: typeof runPjmDoctorChecks;
|
|
16
|
+
migratePjmRepo: typeof migratePjmRepo;
|
|
17
|
+
readPjmMigrationPrompt: typeof readPjmMigrationPrompt;
|
|
11
18
|
}
|
|
12
19
|
export declare function createPjmCommand(overrides?: Partial<PjmCommandDependencies>): Command;
|
|
13
20
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAiBnE,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA6FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,CAkJT"}
|