ai-factory 2.10.0 ā 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -68
- package/dist/cli/commands/audit-artifacts.d.ts +7 -0
- package/dist/cli/commands/audit-artifacts.d.ts.map +1 -0
- package/dist/cli/commands/audit-artifacts.js +407 -0
- package/dist/cli/commands/audit-artifacts.js.map +1 -0
- package/dist/cli/commands/extension.d.ts.map +1 -1
- package/dist/cli/commands/extension.js +16 -7
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +71 -13
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +108 -10
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts.map +1 -1
- package/dist/cli/commands/upgrade.js +15 -1
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/index.js +9 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/wizard/skill-hints.d.ts.map +1 -1
- package/dist/cli/wizard/skill-hints.js +1 -0
- package/dist/cli/wizard/skill-hints.js.map +1 -1
- package/dist/core/agents.d.ts +8 -0
- package/dist/core/agents.d.ts.map +1 -1
- package/dist/core/agents.js +25 -4
- package/dist/core/agents.js.map +1 -1
- package/dist/core/config.d.ts +19 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +135 -7
- package/dist/core/config.js.map +1 -1
- package/dist/core/extension-ops.d.ts +9 -1
- package/dist/core/extension-ops.d.ts.map +1 -1
- package/dist/core/extension-ops.js +106 -8
- package/dist/core/extension-ops.js.map +1 -1
- package/dist/core/extensions.d.ts +23 -5
- package/dist/core/extensions.d.ts.map +1 -1
- package/dist/core/extensions.js +190 -8
- package/dist/core/extensions.js.map +1 -1
- package/dist/core/installer.d.ts +46 -2
- package/dist/core/installer.d.ts.map +1 -1
- package/dist/core/installer.js +387 -32
- package/dist/core/installer.js.map +1 -1
- package/dist/core/mcp-toml.d.ts +7 -0
- package/dist/core/mcp-toml.d.ts.map +1 -0
- package/dist/core/mcp-toml.js +106 -0
- package/dist/core/mcp-toml.js.map +1 -0
- package/dist/core/mcp.d.ts.map +1 -1
- package/dist/core/mcp.js +58 -5
- package/dist/core/mcp.js.map +1 -1
- package/dist/core/transformer.d.ts +6 -0
- package/dist/core/transformer.d.ts.map +1 -1
- package/dist/core/transformer.js +55 -7
- package/dist/core/transformer.js.map +1 -1
- package/dist/core/transformers/antigravity.d.ts.map +1 -1
- package/dist/core/transformers/antigravity.js +2 -0
- package/dist/core/transformers/antigravity.js.map +1 -1
- package/dist/core/transformers/codex.d.ts +2 -0
- package/dist/core/transformers/codex.d.ts.map +1 -1
- package/dist/core/transformers/codex.js +6 -2
- package/dist/core/transformers/codex.js.map +1 -1
- package/dist/utils/fs.d.ts +10 -4
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +11 -7
- package/dist/utils/fs.js.map +1 -1
- package/package.json +16 -4
- package/schemas/extension.schema.json +243 -0
- package/skills/aif/SKILL.md +76 -4
- package/skills/aif/references/config-template.yaml +28 -1
- package/skills/aif-architecture/SKILL.md +18 -176
- package/skills/aif-architecture/references/architecture.md +590 -0
- package/skills/aif-build-automation/SKILL.md +142 -34
- package/skills/aif-build-automation/templates/justfile-gradle +90 -0
- package/skills/aif-build-automation/templates/justfile-maven +90 -0
- package/skills/aif-build-automation/templates/justfile-ruby +105 -0
- package/skills/aif-build-automation/templates/justfile-rust +114 -0
- package/skills/aif-build-automation/templates/makefile-gradle.mk +141 -0
- package/skills/aif-build-automation/templates/makefile-maven.mk +140 -0
- package/skills/aif-build-automation/templates/makefile-ruby.mk +107 -0
- package/skills/aif-build-automation/templates/makefile-rust.mk +114 -0
- package/skills/aif-build-automation/templates/taskfile-gradle.yml +126 -0
- package/skills/aif-build-automation/templates/taskfile-maven.yml +126 -0
- package/skills/aif-build-automation/templates/taskfile-ruby.yml +104 -0
- package/skills/aif-build-automation/templates/taskfile-rust.yml +120 -0
- package/skills/aif-commit/SKILL.md +1 -0
- package/skills/aif-dockerize/SKILL.md +5 -0
- package/skills/aif-dockerize/references/ANGIE-ACME.md +193 -0
- package/skills/aif-dockerize/references/COMPOSE-LIFECYCLE-HOOKS.md +165 -0
- package/skills/aif-explore/SKILL.md +21 -3
- package/skills/aif-implement/SKILL.md +180 -6
- package/skills/aif-improve/SKILL.md +31 -5
- package/skills/aif-plan/SKILL.md +157 -30
- package/skills/aif-plan/references/EXAMPLES.md +28 -0
- package/skills/aif-plan/references/TASK-FORMAT.md +15 -0
- package/skills/aif-qa/SKILL.md +55 -15
- package/skills/aif-qa/references/CHANGE-SUMMARY.md +96 -34
- package/skills/aif-qa/references/TEST-CASES.md +38 -28
- package/skills/aif-qa/references/TEST-PLAN.md +27 -26
- package/skills/aif-qa/templates/CHANGE-SUMMARY.md +8 -0
- package/skills/aif-review/SKILL.md +34 -1
- package/skills/aif-rules-check/SKILL.md +223 -0
- package/skills/aif-rules-check/references/RULES-CHECK-CONTRACT.md +55 -0
- package/skills/aif-security-checklist/SKILL.md +90 -2
- package/skills/aif-security-checklist/scripts/audit.sh +21 -6
- package/skills/aif-verify/SKILL.md +62 -7
- package/skills/aif-verify/references/CONTEXT-GATES-AND-OWNERSHIP.md +11 -0
- package/skills/aif-verify/references/GATE-RESULT-CONTRACT.md +88 -0
- package/subagents/{best-practices-sidecar.md ā claude/agents/best-practices-sidecar.md} +5 -2
- package/subagents/{implement-coordinator.md ā claude/agents/implement-coordinator.md} +5 -1
- package/subagents/{plan-coordinator.md ā claude/agents/plan-coordinator.md} +13 -4
- package/subagents/claude/agents/plan-polisher.md +175 -0
- package/subagents/{review-sidecar.md ā claude/agents/review-sidecar.md} +5 -2
- package/subagents/claude/agents/rules-sidecar.md +31 -0
- package/subagents/{security-sidecar.md ā claude/agents/security-sidecar.md} +5 -2
- package/subagents/codex/agents/best-practices-sidecar.toml +21 -0
- package/subagents/codex/agents/commit-preparer.toml +21 -0
- package/subagents/codex/agents/docs-auditor.toml +21 -0
- package/subagents/codex/agents/implement-coordinator.toml +31 -0
- package/subagents/codex/agents/implement-worker.toml +22 -0
- package/subagents/codex/agents/plan-coordinator.toml +27 -0
- package/subagents/codex/agents/plan-polisher.toml +24 -0
- package/subagents/codex/agents/review-sidecar.toml +21 -0
- package/subagents/codex/agents/security-sidecar.toml +21 -0
- package/subagents/codex/config.toml +4 -0
- package/subagents/plan-polisher.md +0 -109
- /package/subagents/{commit-preparer.md ā claude/agents/commit-preparer.md} +0 -0
- /package/subagents/{docs-auditor.md ā claude/agents/docs-auditor.md} +0 -0
- /package/subagents/{implement-worker.md ā claude/agents/implement-worker.md} +0 -0
- /package/subagents/{loop-critic.md ā claude/agents/loop-critic.md} +0 -0
- /package/subagents/{loop-evaluator.md ā claude/agents/loop-evaluator.md} +0 -0
- /package/subagents/{loop-invariant-prep.md ā claude/agents/loop-invariant-prep.md} +0 -0
- /package/subagents/{loop-orchestrator.md ā claude/agents/loop-orchestrator.md} +0 -0
- /package/subagents/{loop-perf-prep.md ā claude/agents/loop-perf-prep.md} +0 -0
- /package/subagents/{loop-planner.md ā claude/agents/loop-planner.md} +0 -0
- /package/subagents/{loop-producer.md ā claude/agents/loop-producer.md} +0 -0
- /package/subagents/{loop-refiner.md ā claude/agents/loop-refiner.md} +0 -0
- /package/subagents/{loop-test-prep.md ā claude/agents/loop-test-prep.md} +0 -0
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ ai-factory init
|
|
|
33
33
|
- **Spec-driven development** ā AI follows plans, not random exploration. Predictable, resumable, reviewable
|
|
34
34
|
- **Community skills** ā leverage [skills.sh](https://skills.sh) ecosystem or generate custom skills
|
|
35
35
|
- **Stack-agnostic** ā works with any language, framework, or platform
|
|
36
|
-
- **Multi-agent support** ā Claude Code, Cursor, Windsurf, Roo Code, Kilo Code, Antigravity, OpenCode, Warp, Zencoder, Codex CLI, GitHub Copilot, Gemini CLI, Junie, Qwen Code, or [any agent](docs/getting-started.md#supported-agents)
|
|
36
|
+
- **Multi-agent support** ā Claude Code, Cursor, Windsurf, Roo Code, Kilo Code, Antigravity, OpenCode, Warp, Zencoder, Codex CLI, Codex app, GitHub Copilot, Gemini CLI, Junie, Qwen Code, or [any agent](docs/getting-started.md#supported-agents)
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
@@ -72,46 +72,11 @@ Then open your AI agent and start working:
|
|
|
72
72
|
/aif
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
Codex CLI and Codex app use `$aif` style invocations after installation.
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
ai-factory init
|
|
80
|
-
```
|
|
77
|
+
Need CLI flags, update/upgrade details, or extension commands? See [Getting Started](docs/getting-started.md). Need slash-command reference? See [Core Skills](docs/skills.md).
|
|
81
78
|
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
npx ai-factory init
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Non-interactive mode
|
|
88
|
-
|
|
89
|
-
Pass `--agents` to skip the interactive wizard:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
# Agents + MCP servers
|
|
93
|
-
ai-factory init --agents claude,cursor --mcp github,playwright
|
|
94
|
-
|
|
95
|
-
# With specific skills
|
|
96
|
-
ai-factory init --agents claude --skills commit,plan
|
|
97
|
-
|
|
98
|
-
# Without base skills
|
|
99
|
-
ai-factory init --agents codex --no-skills --mcp github
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Available MCP servers: `github`, `postgres`, `filesystem`, `chrome-devtools`, `playwright`
|
|
103
|
-
|
|
104
|
-
### Upgrading from v1 to v2
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
ai-factory upgrade
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
`ai-factory upgrade` removes old bare-named skills (`commit`, `feature`, etc.) and installs new `aif-*` prefixed versions. Custom skills are preserved.
|
|
111
|
-
|
|
112
|
-
> **Note:** `ai-factory update` automatically checks npm for a newer CLI version and offers to install it before updating skills, then reports `changed/unchanged/skipped/removed` for installed base skills. Use `ai-factory update --force` for a clean reinstall of currently installed base skills.
|
|
113
|
-
|
|
114
|
-
### Example Workflow
|
|
79
|
+
## Example Workflow
|
|
115
80
|
|
|
116
81
|
```bash
|
|
117
82
|
# Explore options and requirements before planning (optional)
|
|
@@ -144,20 +109,6 @@ ai-factory upgrade
|
|
|
144
109
|
|
|
145
110
|
See the full [Development Workflow](docs/workflow.md) with diagram and decision table.
|
|
146
111
|
|
|
147
|
-
### Auto-Generated Documentation
|
|
148
|
-
|
|
149
|
-
AI Factory can generate and maintain your project docs with a single command:
|
|
150
|
-
|
|
151
|
-
```bash
|
|
152
|
-
/aif-docs # Creates README + docs/ structure from your codebase
|
|
153
|
-
/aif-docs --web # Also generates a static HTML documentation site
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
- **Generates docs from scratch** ā analyzes your codebase and creates a lean README + detailed `docs/` pages by topic
|
|
157
|
-
- **Cleans up scattered files** ā finds loose CONTRIBUTING.md, ARCHITECTURE.md, SETUP.md in your root and consolidates them into a structured `docs/` directory
|
|
158
|
-
- **Keeps docs in sync** ā integrates with `/aif-implement` docs policy (`Docs: yes` = mandatory docs checkpoint routed to `/aif-docs`, `Docs: no` = visible `WARN [docs]`)
|
|
159
|
-
- **Builds a docs website** ā `--web` generates a static HTML site with navigation and dark mode, ready to host
|
|
160
|
-
|
|
161
112
|
---
|
|
162
113
|
|
|
163
114
|
## Documentation
|
|
@@ -167,8 +118,9 @@ AI Factory can generate and maintain your project docs with a single command:
|
|
|
167
118
|
| [Getting Started](docs/getting-started.md) | What is AI Factory, supported agents, CLI commands |
|
|
168
119
|
| [Development Workflow](docs/workflow.md) | Workflow diagram, when to use `explore` vs `grounded`, spec-driven approach |
|
|
169
120
|
| [Reflex Loop](docs/loop.md) | Iterative generate ā evaluate ā critique ā refine workflow |
|
|
170
|
-
| [Subagents](docs/subagents.md) | Claude
|
|
121
|
+
| [Subagents](docs/subagents.md) | Bundled Claude subagents and the baseline Codex native agent-file bundle, including managed Codex config |
|
|
171
122
|
| [Core Skills](docs/skills.md) | All slash commands ā explore, grounded, plan, fix, implement, evolve, docs, and more |
|
|
123
|
+
| [Quality Gates](docs/quality-gates.md) | Machine-readable `aif-gate-result` summaries for verify, review, security, and rules gates |
|
|
172
124
|
| [Skill Evolution](docs/evolve.md) | How /aif-fix patches feed into /aif-evolve to generate smarter skill rules |
|
|
173
125
|
| [Plan Files](docs/plan-files.md) | Plan files, self-improvement patches, skill acquisition |
|
|
174
126
|
| [Security](docs/security.md) | Two-level security scanning for external skills |
|
|
@@ -176,22 +128,9 @@ AI Factory can generate and maintain your project docs with a single command:
|
|
|
176
128
|
| [Configuration](docs/configuration.md) | `.ai-factory.json`, MCP servers, project structure, best practices |
|
|
177
129
|
| [Config Reference](docs/config-reference.md) | Full `config.yaml` key reference and skill read/write matrix |
|
|
178
130
|
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-

|
|
182
|
-
|
|
183
|
-
## AIF Handoff
|
|
184
|
-
|
|
185
|
-
Looking for an **Autonomous Kanban board where AI agents plan, implement, and review your tasks**? Check out [aif-handoff](https://github.com/lee-to/aif-handoff) ā a visual task management system built on top of AI Factory.
|
|
186
|
-
|
|
187
|
-

|
|
188
|
-

|
|
189
|
-

|
|
190
|
-

|
|
191
|
-
|
|
192
131
|
## Links
|
|
193
|
-
|
|
194
132
|
- [Official Website](https://aif.cutcode.dev) - AI Factory website
|
|
133
|
+
- [aif-handoff](https://github.com/lee-to/aif-handoff) - Autonomous Kanban board built on AI Factory
|
|
195
134
|
- If AI Factory feels too simple for your goals, try [HLV](https://github.com/lee-to/hlv)
|
|
196
135
|
- [skills.sh](https://skills.sh) - Skill marketplace
|
|
197
136
|
- [Agent Skills Spec](https://agentskills.io) - Skill specification
|
|
@@ -204,6 +143,7 @@ Looking for an **Autonomous Kanban board where AI agents plan, implement, and re
|
|
|
204
143
|
- [Warp](https://www.warp.dev) - Intelligent terminal with AI agent
|
|
205
144
|
- [Zencoder](https://zencoder.ai) - AI coding agent for VS Code and JetBrains
|
|
206
145
|
- [Codex CLI](https://github.com/openai/codex) - OpenAI's coding agent
|
|
146
|
+
- [Codex app](https://openai.com/codex/) - OpenAI's coding agent app
|
|
207
147
|
- [Gemini CLI](https://github.com/google-gemini/gemini-cli) - Google's coding agent
|
|
208
148
|
- [Antigravity](https://antigravity.dev) - AI coding agent
|
|
209
149
|
- [Junie](https://www.jetbrains.com/junie/) - JetBrains' AI coding agent
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-artifacts.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/audit-artifacts.ts"],"names":[],"mappings":"AAuBA,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA2aD,wBAAsB,qBAAqB,CAAC,KAAK,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6C3G"}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { readTextFile } from '../../utils/fs.js';
|
|
5
|
+
const RELATION_FIELDS = [
|
|
6
|
+
'depends_on',
|
|
7
|
+
'affects',
|
|
8
|
+
'implements',
|
|
9
|
+
'verifies',
|
|
10
|
+
'documents',
|
|
11
|
+
'supersedes',
|
|
12
|
+
];
|
|
13
|
+
const DEFAULT_TARGETS = ['.ai-factory', 'docs', 'README.md', 'AGENTS.md'];
|
|
14
|
+
const DEFAULT_SKIP_DIRS = new Set([
|
|
15
|
+
'.git',
|
|
16
|
+
'node_modules',
|
|
17
|
+
'dist',
|
|
18
|
+
'coverage',
|
|
19
|
+
'docs-html',
|
|
20
|
+
'evolution',
|
|
21
|
+
'evolutions',
|
|
22
|
+
'qa',
|
|
23
|
+
]);
|
|
24
|
+
function emptyRelations() {
|
|
25
|
+
return {
|
|
26
|
+
depends_on: [],
|
|
27
|
+
affects: [],
|
|
28
|
+
implements: [],
|
|
29
|
+
verifies: [],
|
|
30
|
+
documents: [],
|
|
31
|
+
supersedes: [],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function normalizeRelPath(projectDir, filePath) {
|
|
35
|
+
return path.relative(projectDir, filePath).replaceAll('\\', '/');
|
|
36
|
+
}
|
|
37
|
+
function isInsideProject(canonicalProjectDir, candidate) {
|
|
38
|
+
const relative = path.relative(canonicalProjectDir, candidate);
|
|
39
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
40
|
+
}
|
|
41
|
+
function stripInlineComment(value) {
|
|
42
|
+
const hashIndex = value.indexOf(' #');
|
|
43
|
+
return hashIndex >= 0 ? value.slice(0, hashIndex).trim() : value.trim();
|
|
44
|
+
}
|
|
45
|
+
function stripQuotes(value) {
|
|
46
|
+
const trimmed = stripInlineComment(value).trim();
|
|
47
|
+
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
48
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))) {
|
|
49
|
+
return trimmed.slice(1, -1).trim();
|
|
50
|
+
}
|
|
51
|
+
return trimmed;
|
|
52
|
+
}
|
|
53
|
+
function parseArrayValue(value) {
|
|
54
|
+
const trimmed = stripInlineComment(value).trim();
|
|
55
|
+
if (!trimmed)
|
|
56
|
+
return [];
|
|
57
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
58
|
+
return trimmed
|
|
59
|
+
.slice(1, -1)
|
|
60
|
+
.split(',')
|
|
61
|
+
.map(item => stripQuotes(item))
|
|
62
|
+
.filter(Boolean);
|
|
63
|
+
}
|
|
64
|
+
return [stripQuotes(trimmed)].filter(Boolean);
|
|
65
|
+
}
|
|
66
|
+
function parseFrontmatter(content) {
|
|
67
|
+
if (!content.startsWith('---\n') && !content.startsWith('---\r\n')) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const endMatch = content.match(/\r?\n---\r?\n/);
|
|
71
|
+
if (!endMatch || typeof endMatch.index !== 'number') {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const block = content.slice(content.indexOf('\n') + 1, endMatch.index);
|
|
75
|
+
const fields = {};
|
|
76
|
+
let currentListKey = null;
|
|
77
|
+
for (const rawLine of block.split(/\r?\n/)) {
|
|
78
|
+
const line = rawLine.trimEnd();
|
|
79
|
+
if (!line.trim() || line.trimStart().startsWith('#')) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const listMatch = line.match(/^\s*-\s+(.+)$/);
|
|
83
|
+
if (listMatch && currentListKey) {
|
|
84
|
+
fields[currentListKey] = [...(fields[currentListKey] ?? []), ...parseArrayValue(listMatch[1])];
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const fieldMatch = line.match(/^([A-Za-z0-9_.-]+):(?:\s*(.*))?$/);
|
|
88
|
+
if (!fieldMatch) {
|
|
89
|
+
currentListKey = null;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const key = fieldMatch[1];
|
|
93
|
+
const value = fieldMatch[2] ?? '';
|
|
94
|
+
currentListKey = value.trim() === '' ? key : null;
|
|
95
|
+
fields[key] = parseArrayValue(value);
|
|
96
|
+
}
|
|
97
|
+
return fields;
|
|
98
|
+
}
|
|
99
|
+
function first(fields, key) {
|
|
100
|
+
return fields[key]?.[0];
|
|
101
|
+
}
|
|
102
|
+
function getOwners(fields) {
|
|
103
|
+
return [...(fields.owners ?? []), ...(fields.owner ?? [])].filter(Boolean);
|
|
104
|
+
}
|
|
105
|
+
function toArtifact(projectDir, absPath, fields) {
|
|
106
|
+
const id = first(fields, 'id');
|
|
107
|
+
if (!id)
|
|
108
|
+
return null;
|
|
109
|
+
const relations = emptyRelations();
|
|
110
|
+
for (const field of RELATION_FIELDS) {
|
|
111
|
+
relations[field] = fields[field] ?? [];
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
id,
|
|
115
|
+
file: normalizeRelPath(projectDir, absPath),
|
|
116
|
+
type: first(fields, 'type'),
|
|
117
|
+
status: first(fields, 'status'),
|
|
118
|
+
owners: getOwners(fields),
|
|
119
|
+
relations,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function targetFindingLevel(isExplicit) {
|
|
123
|
+
return isExplicit ? 'fail' : 'warn';
|
|
124
|
+
}
|
|
125
|
+
async function realpathOrNull(filePath) {
|
|
126
|
+
try {
|
|
127
|
+
return await fs.realpath(filePath);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function collectMarkdownFiles(projectDir, targets, isExplicit) {
|
|
134
|
+
const canonicalProjectDir = await fs.realpath(projectDir);
|
|
135
|
+
const files = new Set();
|
|
136
|
+
const findings = [];
|
|
137
|
+
const visitedDirectories = new Set();
|
|
138
|
+
async function walk(currentPath, requestedPath, isRootTarget = false) {
|
|
139
|
+
const canonicalPath = await realpathOrNull(currentPath);
|
|
140
|
+
if (!canonicalPath) {
|
|
141
|
+
findings.push({
|
|
142
|
+
level: targetFindingLevel(isExplicit),
|
|
143
|
+
file: requestedPath,
|
|
144
|
+
message: `Requested audit target does not exist: ${requestedPath}`,
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (!isInsideProject(canonicalProjectDir, canonicalPath)) {
|
|
149
|
+
findings.push({
|
|
150
|
+
level: targetFindingLevel(isExplicit),
|
|
151
|
+
file: requestedPath,
|
|
152
|
+
message: `Requested audit target is outside the project boundary: ${requestedPath}`,
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const stats = await fs.lstat(currentPath);
|
|
157
|
+
const statTarget = stats.isSymbolicLink() ? canonicalPath : currentPath;
|
|
158
|
+
const targetStats = stats.isSymbolicLink() ? await fs.stat(canonicalPath) : stats;
|
|
159
|
+
if (targetStats.isFile()) {
|
|
160
|
+
if (statTarget.endsWith('.md')) {
|
|
161
|
+
files.add(statTarget);
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (!targetStats.isDirectory()) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (visitedDirectories.has(canonicalPath)) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
visitedDirectories.add(canonicalPath);
|
|
172
|
+
const directoryName = path.basename(currentPath);
|
|
173
|
+
if (!isRootTarget && DEFAULT_SKIP_DIRS.has(directoryName)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const entries = await fs.readdir(canonicalPath, { withFileTypes: true });
|
|
177
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
178
|
+
for (const entry of entries) {
|
|
179
|
+
const entryPath = path.join(canonicalPath, entry.name);
|
|
180
|
+
const entryRequestedPath = path.join(requestedPath, entry.name).replaceAll('\\', '/');
|
|
181
|
+
await walk(entryPath, entryRequestedPath);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
for (const target of targets) {
|
|
185
|
+
const absTarget = path.resolve(projectDir, target);
|
|
186
|
+
if (!isInsideProject(canonicalProjectDir, absTarget)) {
|
|
187
|
+
findings.push({
|
|
188
|
+
level: targetFindingLevel(isExplicit),
|
|
189
|
+
file: target,
|
|
190
|
+
message: `Requested audit target is outside the project boundary: ${target}`,
|
|
191
|
+
});
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (!await fs.pathExists(absTarget)) {
|
|
195
|
+
if (isExplicit) {
|
|
196
|
+
findings.push({
|
|
197
|
+
level: 'fail',
|
|
198
|
+
file: target,
|
|
199
|
+
message: `Requested audit target does not exist: ${target}`,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
await walk(absTarget, target, true);
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
files: [...files].sort((a, b) => a.localeCompare(b)),
|
|
208
|
+
findings,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function relationTargets(artifact) {
|
|
212
|
+
return RELATION_FIELDS.flatMap(field => artifact.relations[field]);
|
|
213
|
+
}
|
|
214
|
+
function hasIncomingRelation(artifactId, artifacts, fields) {
|
|
215
|
+
return artifacts.some(artifact => fields.some(field => artifact.relations[field].includes(artifactId)));
|
|
216
|
+
}
|
|
217
|
+
function detectDependencyCycles(artifacts) {
|
|
218
|
+
const byId = new Map(artifacts.map(artifact => [artifact.id, artifact]));
|
|
219
|
+
const cycles = [];
|
|
220
|
+
const visiting = new Set();
|
|
221
|
+
const visited = new Set();
|
|
222
|
+
const stack = [];
|
|
223
|
+
function visit(id) {
|
|
224
|
+
if (visiting.has(id)) {
|
|
225
|
+
const start = stack.indexOf(id);
|
|
226
|
+
if (start >= 0) {
|
|
227
|
+
cycles.push([...stack.slice(start), id]);
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (visited.has(id))
|
|
232
|
+
return;
|
|
233
|
+
const artifact = byId.get(id);
|
|
234
|
+
if (!artifact)
|
|
235
|
+
return;
|
|
236
|
+
visiting.add(id);
|
|
237
|
+
stack.push(id);
|
|
238
|
+
for (const targetId of artifact.relations.depends_on) {
|
|
239
|
+
visit(targetId);
|
|
240
|
+
}
|
|
241
|
+
stack.pop();
|
|
242
|
+
visiting.delete(id);
|
|
243
|
+
visited.add(id);
|
|
244
|
+
}
|
|
245
|
+
for (const artifact of artifacts) {
|
|
246
|
+
visit(artifact.id);
|
|
247
|
+
}
|
|
248
|
+
return cycles;
|
|
249
|
+
}
|
|
250
|
+
function auditRecords(artifacts, markdownWithoutMetadata) {
|
|
251
|
+
const findings = [];
|
|
252
|
+
const ids = new Map();
|
|
253
|
+
for (const artifact of artifacts) {
|
|
254
|
+
ids.set(artifact.id, [...(ids.get(artifact.id) ?? []), artifact]);
|
|
255
|
+
}
|
|
256
|
+
for (const [id, matches] of ids) {
|
|
257
|
+
if (matches.length > 1) {
|
|
258
|
+
findings.push({
|
|
259
|
+
level: 'fail',
|
|
260
|
+
id,
|
|
261
|
+
message: `Duplicate artifact id is used by ${matches.map(match => match.file).join(', ')}`,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const knownIds = new Set(ids.keys());
|
|
266
|
+
for (const artifact of artifacts) {
|
|
267
|
+
if (!artifact.type) {
|
|
268
|
+
findings.push({ level: 'warn', file: artifact.file, id: artifact.id, message: 'Missing type.' });
|
|
269
|
+
}
|
|
270
|
+
if (!artifact.status) {
|
|
271
|
+
findings.push({ level: 'warn', file: artifact.file, id: artifact.id, message: 'Missing status.' });
|
|
272
|
+
}
|
|
273
|
+
if (artifact.owners.length === 0) {
|
|
274
|
+
findings.push({ level: 'warn', file: artifact.file, id: artifact.id, message: 'Missing owner/owners.' });
|
|
275
|
+
}
|
|
276
|
+
for (const field of RELATION_FIELDS) {
|
|
277
|
+
for (const targetId of artifact.relations[field]) {
|
|
278
|
+
if (targetId === artifact.id) {
|
|
279
|
+
findings.push({
|
|
280
|
+
level: 'fail',
|
|
281
|
+
file: artifact.file,
|
|
282
|
+
id: artifact.id,
|
|
283
|
+
message: `Self-reference in ${field}.`,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
else if (!knownIds.has(targetId)) {
|
|
287
|
+
findings.push({
|
|
288
|
+
level: 'fail',
|
|
289
|
+
file: artifact.file,
|
|
290
|
+
id: artifact.id,
|
|
291
|
+
message: `${field} references unknown artifact "${targetId}".`,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const type = artifact.type?.toLowerCase();
|
|
297
|
+
const status = artifact.status?.toLowerCase();
|
|
298
|
+
if ((type === 'spec' || type === 'requirement' || type === 'requirements') && relationTargets(artifact).length === 0) {
|
|
299
|
+
findings.push({
|
|
300
|
+
level: 'warn',
|
|
301
|
+
file: artifact.file,
|
|
302
|
+
id: artifact.id,
|
|
303
|
+
message: 'Spec has no explicit dependency/impact links.',
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
if ((type === 'spec' || type === 'requirement' || type === 'requirements') &&
|
|
307
|
+
!hasIncomingRelation(artifact.id, artifacts, ['implements', 'verifies', 'documents'])) {
|
|
308
|
+
findings.push({
|
|
309
|
+
level: 'warn',
|
|
310
|
+
file: artifact.file,
|
|
311
|
+
id: artifact.id,
|
|
312
|
+
message: 'Spec is not referenced by code/tests/docs metadata.',
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
if (type === 'adr' && status === 'accepted' && artifact.relations.affects.length === 0) {
|
|
316
|
+
findings.push({
|
|
317
|
+
level: 'warn',
|
|
318
|
+
file: artifact.file,
|
|
319
|
+
id: artifact.id,
|
|
320
|
+
message: 'Accepted ADR has no affects links.',
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
for (const cycle of detectDependencyCycles(artifacts)) {
|
|
325
|
+
findings.push({
|
|
326
|
+
level: 'fail',
|
|
327
|
+
message: `Dependency cycle: ${cycle.join(' -> ')}`,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
if (markdownWithoutMetadata > 0 && artifacts.length === 0) {
|
|
331
|
+
findings.push({
|
|
332
|
+
level: 'warn',
|
|
333
|
+
message: `${markdownWithoutMetadata} markdown file(s) were found, but none had artifact frontmatter with an id.`,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
return findings;
|
|
337
|
+
}
|
|
338
|
+
function printHumanReport(artifacts, findings, markdownWithoutMetadata, strict) {
|
|
339
|
+
const failCount = findings.filter(finding => finding.level === 'fail').length;
|
|
340
|
+
const warnCount = findings.filter(finding => finding.level === 'warn').length;
|
|
341
|
+
const effectiveFailCount = strict ? failCount + warnCount : failCount;
|
|
342
|
+
console.log(chalk.bold('Artifact Audit'));
|
|
343
|
+
console.log(`Artifacts indexed: ${artifacts.length}`);
|
|
344
|
+
console.log(`Markdown without artifact metadata: ${markdownWithoutMetadata}`);
|
|
345
|
+
console.log(`Findings: ${failCount} fail, ${warnCount} warn${strict ? ' (strict treats warnings as failures)' : ''}`);
|
|
346
|
+
console.log('');
|
|
347
|
+
if (findings.length === 0) {
|
|
348
|
+
console.log(chalk.green('PASS No artifact graph issues found.'));
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
for (const finding of findings) {
|
|
352
|
+
const label = finding.level === 'fail' ? chalk.red('FAIL') : chalk.yellow('WARN');
|
|
353
|
+
const location = [finding.file, finding.id].filter(Boolean).join(' ');
|
|
354
|
+
console.log(`${label} ${location ? `${location}: ` : ''}${finding.message}`);
|
|
355
|
+
}
|
|
356
|
+
console.log('');
|
|
357
|
+
if (effectiveFailCount > 0) {
|
|
358
|
+
console.log(chalk.red('Result: FAIL'));
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
console.log(chalk.yellow('Result: WARN'));
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
export async function auditArtifactsCommand(paths = [], options = {}) {
|
|
365
|
+
const projectDir = process.cwd();
|
|
366
|
+
const targets = paths.length > 0 ? paths : DEFAULT_TARGETS;
|
|
367
|
+
const explicitTargets = paths.length > 0;
|
|
368
|
+
const { files: markdownFiles, findings: collectionFindings } = await collectMarkdownFiles(projectDir, targets, explicitTargets);
|
|
369
|
+
const artifacts = [];
|
|
370
|
+
let markdownWithoutMetadata = 0;
|
|
371
|
+
for (const file of markdownFiles) {
|
|
372
|
+
const content = await readTextFile(file);
|
|
373
|
+
if (!content)
|
|
374
|
+
continue;
|
|
375
|
+
const fields = parseFrontmatter(content);
|
|
376
|
+
if (!fields) {
|
|
377
|
+
markdownWithoutMetadata += 1;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const artifact = toArtifact(projectDir, file, fields);
|
|
381
|
+
if (artifact) {
|
|
382
|
+
artifacts.push(artifact);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
markdownWithoutMetadata += 1;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const findings = [...collectionFindings, ...auditRecords(artifacts, markdownWithoutMetadata)];
|
|
389
|
+
const failCount = findings.filter(finding => finding.level === 'fail').length;
|
|
390
|
+
const warnCount = findings.filter(finding => finding.level === 'warn').length;
|
|
391
|
+
const shouldFail = options.strict ? failCount + warnCount > 0 : failCount > 0;
|
|
392
|
+
if (options.json) {
|
|
393
|
+
console.log(JSON.stringify({
|
|
394
|
+
status: shouldFail ? 'fail' : warnCount > 0 ? 'warn' : 'pass',
|
|
395
|
+
artifacts: artifacts.length,
|
|
396
|
+
markdown_without_metadata: markdownWithoutMetadata,
|
|
397
|
+
findings,
|
|
398
|
+
}, null, 2));
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
printHumanReport(artifacts, findings, markdownWithoutMetadata, options.strict ?? false);
|
|
402
|
+
}
|
|
403
|
+
if (shouldFail) {
|
|
404
|
+
process.exitCode = 1;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
//# sourceMappingURL=audit-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-artifacts.js","sourceRoot":"","sources":["../../../src/cli/commands/audit-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA8BjD,MAAM,eAAe,GAAoB;IACvC,YAAY;IACZ,SAAS;IACT,YAAY;IACZ,UAAU;IACV,WAAW;IACX,YAAY;CACb,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AAC1E,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,MAAM;IACN,cAAc;IACd,MAAM;IACN,UAAU;IACV,WAAW;IACX,WAAW;IACX,YAAY;IACZ,IAAI;CACL,CAAC,CAAC;AAEH,SAAS,cAAc;IACrB,OAAO;QACL,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,EAAE;QACX,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE;KACf,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,QAAgB;IAC5D,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,eAAe,CAAC,mBAA2B,EAAE,SAAiB;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC;IAC/D,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;AAC1E,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,IACE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAClD,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACrC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACrD,OAAO,OAAO;aACX,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACZ,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;aAC9B,MAAM,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;IACvC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAChD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,IAAI,cAAc,GAAkB,IAAI,CAAC;IAEzC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,SAAS;QACX,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC9C,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;YAChC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/F,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,cAAc,GAAG,IAAI,CAAC;YACtB,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClC,cAAc,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAClD,MAAM,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,KAAK,CAAC,MAAgC,EAAE,GAAW;IAC1D,OAAO,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,SAAS,CAAC,MAAgC;IACjD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,UAAU,CAAC,UAAkB,EAAE,OAAe,EAAE,MAAgC;IACvF,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAErB,MAAM,SAAS,GAAG,cAAc,EAAE,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,OAAO;QACL,EAAE;QACF,IAAI,EAAE,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC;QAC3C,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;QAC3B,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC/B,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;QACzB,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAmB;IAC7C,OAAO,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACtC,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,QAAgB;IAC5C,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,UAAkB,EAAE,OAAiB,EAAE,UAAmB;IAC5F,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE7C,KAAK,UAAU,IAAI,CAAC,WAAmB,EAAE,aAAqB,EAAE,YAAY,GAAG,KAAK;QAClF,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;QACxD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC;gBACrC,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,0CAA0C,aAAa,EAAE;aACnE,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC,eAAe,CAAC,mBAAmB,EAAE,aAAa,CAAC,EAAE,CAAC;YACzD,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC;gBACrC,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,2DAA2D,aAAa,EAAE;aACpF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;QACxE,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAElF,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;YACzB,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACxB,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,IAAI,kBAAkB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QACD,kBAAkB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAEtC,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY,IAAI,iBAAiB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAErD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACtF,MAAM,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,eAAe,CAAC,mBAAmB,EAAE,SAAS,CAAC,EAAE,CAAC;YACrD,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC;gBACrC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,2DAA2D,MAAM,EAAE;aAC7E,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,IAAI,UAAU,EAAE,CAAC;gBACf,QAAQ,CAAC,IAAI,CAAC;oBACZ,KAAK,EAAE,MAAM;oBACb,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,0CAA0C,MAAM,EAAE;iBAC5D,CAAC,CAAC;YACL,CAAC;YACD,SAAS;QACX,CAAC;QAED,MAAM,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QACpD,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,QAAwB;IAC/C,OAAO,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAkB,EAAE,SAA2B,EAAE,MAAuB;IACnG,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CACrE,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,SAA2B;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,KAAK,CAAC,EAAU;QACvB,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO;QAE5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;YACrD,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClB,CAAC;QACD,KAAK,CAAC,GAAG,EAAE,CAAC;QACZ,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,SAA2B,EAAE,uBAA+B;IAChF,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEhD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,MAAM;gBACb,EAAE;gBACF,OAAO,EAAE,oCAAoC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aAC3F,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;QACnG,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACrG,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAC3G,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;YACpC,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,IAAI,QAAQ,KAAK,QAAQ,CAAC,EAAE,EAAE,CAAC;oBAC7B,QAAQ,CAAC,IAAI,CAAC;wBACZ,KAAK,EAAE,MAAM;wBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,EAAE,EAAE,QAAQ,CAAC,EAAE;wBACf,OAAO,EAAE,qBAAqB,KAAK,GAAG;qBACvC,CAAC,CAAC;gBACL,CAAC;qBAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACnC,QAAQ,CAAC,IAAI,CAAC;wBACZ,KAAK,EAAE,MAAM;wBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,EAAE,EAAE,QAAQ,CAAC,EAAE;wBACf,OAAO,EAAE,GAAG,KAAK,iCAAiC,QAAQ,IAAI;qBAC/D,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,cAAc,CAAC,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrH,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,MAAM;gBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,OAAO,EAAE,+CAA+C;aACzD,CAAC,CAAC;QACL,CAAC;QACD,IACE,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,cAAc,CAAC;YACtE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,EACrF,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,MAAM;gBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,OAAO,EAAE,qDAAqD;aAC/D,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvF,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,MAAM;gBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,OAAO,EAAE,oCAAoC;aAC9C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,qBAAqB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;SACnD,CAAC,CAAC;IACL,CAAC;IAED,IAAI,uBAAuB,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,GAAG,uBAAuB,6EAA6E;SACjH,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,gBAAgB,CAAC,SAA2B,EAAE,QAAmB,EAAE,uBAA+B,EAAE,MAAe;IAC1H,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,kBAAkB,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAEtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,sBAAsB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,uCAAuC,uBAAuB,EAAE,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,aAAa,SAAS,UAAU,SAAS,QAAQ,MAAM,CAAC,CAAC,CAAC,uCAAuC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;QACjE,OAAO;IACT,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,QAAkB,EAAE,EAAE,UAAwB,EAAE;IAC1F,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC;IAC3D,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACzC,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,EAAE,GAAG,MAAM,oBAAoB,CAAC,UAAU,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;IAChI,MAAM,SAAS,GAAqB,EAAE,CAAC;IACvC,IAAI,uBAAuB,GAAG,CAAC,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO;YAAE,SAAS;QAEvB,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,uBAAuB,IAAI,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,QAAQ,EAAE,CAAC;YACb,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,uBAAuB,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,GAAG,kBAAkB,EAAE,GAAG,YAAY,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAC9F,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC;IAE9E,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACzB,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAC7D,SAAS,EAAE,SAAS,CAAC,MAAM;YAC3B,yBAAyB,EAAE,uBAAuB;YAClD,QAAQ;SACT,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;SAAM,CAAC;QACN,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,uBAAuB,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;IAC1F,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/extension.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/extension.ts"],"names":[],"mappings":"AAkDA,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CvE;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4FxE;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAoC1D;AAED,wBAAsB,sBAAsB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFxG"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { loadConfig, saveConfig } from '../../core/config.js';
|
|
3
|
+
import { hydrateAgentFileSources, loadConfig, saveConfig } from '../../core/config.js';
|
|
4
4
|
import { hydrateProjectAgentRegistry } from '../../core/agents.js';
|
|
5
|
-
import { resolveExtension, removeExtensionFiles, getExtensionsDir,
|
|
5
|
+
import { resolveExtension, removeExtensionFiles, getExtensionsDir, loadInstalledExtensionManifest, } from '../../core/extensions.js';
|
|
6
6
|
import { removeExtensionMcpServers } from '../../core/mcp.js';
|
|
7
|
-
import { removeSkillsForAllAgents, collectReplacedSkills, removeExtensionAgentFilesForAllAgents, restoreBaseSkills, stripInjectionsForAllAgents, removeCustomSkillsForAllAgents, commitResolvedExtension, refreshExtensions, getManifestRuntimeIds, assertNoConfiguredRuntimeOrphans, } from '../../core/extension-ops.js';
|
|
7
|
+
import { collectTrackedExtensionAgentFileTargets, removeSkillsForAllAgents, collectReplacedSkills, collectManifestAgentFileTargets, removeAgentFilesForAllAgentsByTargets, removeExtensionAgentFilesForAllAgents, pruneAgentFileSources, pruneInstalledAgentFiles, pruneManagedAgentFiles, restoreBaseSkills, stripInjectionsForAllAgents, removeCustomSkillsForAllAgents, commitResolvedExtension, refreshExtensions, getManifestRuntimeIds, assertNoConfiguredRuntimeOrphans, } from '../../core/extension-ops.js';
|
|
8
8
|
async function loadHydratedExtensionConfig(projectDir, options = {}) {
|
|
9
9
|
const config = await loadConfig(projectDir);
|
|
10
10
|
if (!config) {
|
|
@@ -66,6 +66,7 @@ export async function extensionRemoveCommand(name) {
|
|
|
66
66
|
const projectDir = process.cwd();
|
|
67
67
|
console.log(chalk.bold.blue('\nš AI Factory - Remove Extension\n'));
|
|
68
68
|
const config = await loadHydratedExtensionConfig(projectDir);
|
|
69
|
+
await hydrateAgentFileSources(projectDir, config);
|
|
69
70
|
const extensions = config.extensions ?? [];
|
|
70
71
|
const index = extensions.findIndex(e => e.name === name);
|
|
71
72
|
if (index < 0) {
|
|
@@ -74,10 +75,18 @@ export async function extensionRemoveCommand(name) {
|
|
|
74
75
|
}
|
|
75
76
|
try {
|
|
76
77
|
const extensionDir = path.join(getExtensionsDir(projectDir), name);
|
|
77
|
-
const manifest = await
|
|
78
|
+
const manifest = await loadInstalledExtensionManifest(extensionDir);
|
|
78
79
|
assertNoConfiguredRuntimeOrphans(config, getManifestRuntimeIds(manifest), name, 'remove');
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
const trackedAgentFileTargets = manifest?.agentFiles?.length
|
|
81
|
+
? collectManifestAgentFileTargets(manifest)
|
|
82
|
+
: collectTrackedExtensionAgentFileTargets(config.agents, name);
|
|
83
|
+
if (Array.from(trackedAgentFileTargets.values()).some(targets => targets.length > 0)) {
|
|
84
|
+
const removedAgentFiles = manifest?.agentFiles?.length
|
|
85
|
+
? await removeExtensionAgentFilesForAllAgents(projectDir, config.agents, manifest)
|
|
86
|
+
: await removeAgentFilesForAllAgentsByTargets(projectDir, config.agents, trackedAgentFileTargets);
|
|
87
|
+
pruneInstalledAgentFiles(config.agents, trackedAgentFileTargets);
|
|
88
|
+
pruneAgentFileSources(config.agents, trackedAgentFileTargets);
|
|
89
|
+
pruneManagedAgentFiles(config.agents, trackedAgentFileTargets);
|
|
81
90
|
for (const [agentId, files] of removedAgentFiles) {
|
|
82
91
|
if (files.length > 0) {
|
|
83
92
|
console.log(chalk.green(`ā Agent files removed for ${agentId}: ${files.join(', ')}`));
|
|
@@ -145,7 +154,7 @@ export async function extensionListCommand() {
|
|
|
145
154
|
console.log(` ${chalk.bold(ext.name)} ${chalk.dim(`v${ext.version}`)}`);
|
|
146
155
|
console.log(chalk.dim(` Source: ${ext.source}`));
|
|
147
156
|
const extensionDir = path.join(getExtensionsDir(projectDir), ext.name);
|
|
148
|
-
const manifest = await
|
|
157
|
+
const manifest = await loadInstalledExtensionManifest(extensionDir);
|
|
149
158
|
if (manifest) {
|
|
150
159
|
if (manifest.description) {
|
|
151
160
|
console.log(chalk.dim(` ${manifest.description}`));
|