@dewtech/dare-cli 3.11.0 → 3.13.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 +2 -0
- package/dist/__tests__/cli-only-invariants.test.d.ts +2 -0
- package/dist/__tests__/cli-only-invariants.test.d.ts.map +1 -0
- package/dist/__tests__/cli-only-invariants.test.js +100 -0
- package/dist/__tests__/cli-only-invariants.test.js.map +1 -0
- package/dist/__tests__/cli-only-regression.test.d.ts +2 -0
- package/dist/__tests__/cli-only-regression.test.d.ts.map +1 -0
- package/dist/__tests__/cli-only-regression.test.js +29 -0
- package/dist/__tests__/cli-only-regression.test.js.map +1 -0
- package/dist/__tests__/ensure-skills.test.js +5 -0
- package/dist/__tests__/ensure-skills.test.js.map +1 -1
- package/dist/__tests__/ide-command-parity.test.js +1 -0
- package/dist/__tests__/ide-command-parity.test.js.map +1 -1
- package/dist/__tests__/project-generator.test.js +17 -0
- package/dist/__tests__/project-generator.test.js.map +1 -1
- package/dist/__tests__/reverse-facts.test.js +1 -0
- package/dist/__tests__/reverse-facts.test.js.map +1 -1
- package/dist/__tests__/terminal-parity-regression.test.d.ts +2 -0
- package/dist/__tests__/terminal-parity-regression.test.d.ts.map +1 -0
- package/dist/__tests__/terminal-parity-regression.test.js +116 -0
- package/dist/__tests__/terminal-parity-regression.test.js.map +1 -0
- package/dist/__tests__/terminal-parity.test.d.ts +2 -0
- package/dist/__tests__/terminal-parity.test.d.ts.map +1 -0
- package/dist/__tests__/terminal-parity.test.js +81 -0
- package/dist/__tests__/terminal-parity.test.js.map +1 -0
- package/dist/agent/__tests__/antigravity-driver.test.d.ts +2 -0
- package/dist/agent/__tests__/antigravity-driver.test.d.ts.map +1 -0
- package/dist/agent/__tests__/antigravity-driver.test.js +52 -0
- package/dist/agent/__tests__/antigravity-driver.test.js.map +1 -0
- package/dist/agent/__tests__/codex-driver.test.d.ts +2 -0
- package/dist/agent/__tests__/codex-driver.test.d.ts.map +1 -0
- package/dist/agent/__tests__/codex-driver.test.js +68 -0
- package/dist/agent/__tests__/codex-driver.test.js.map +1 -0
- package/dist/agent/__tests__/cursor-driver.test.d.ts +2 -0
- package/dist/agent/__tests__/cursor-driver.test.d.ts.map +1 -0
- package/dist/agent/__tests__/cursor-driver.test.js +52 -0
- package/dist/agent/__tests__/cursor-driver.test.js.map +1 -0
- package/dist/agent/driver.d.ts +1 -1
- package/dist/agent/driver.d.ts.map +1 -1
- package/dist/agent/drivers/antigravity.d.ts +8 -0
- package/dist/agent/drivers/antigravity.d.ts.map +1 -0
- package/dist/agent/drivers/antigravity.js +99 -0
- package/dist/agent/drivers/antigravity.js.map +1 -0
- package/dist/agent/drivers/codex.d.ts +12 -0
- package/dist/agent/drivers/codex.d.ts.map +1 -0
- package/dist/agent/drivers/codex.js +137 -0
- package/dist/agent/drivers/codex.js.map +1 -0
- package/dist/agent/drivers/cursor.d.ts +8 -0
- package/dist/agent/drivers/cursor.d.ts.map +1 -0
- package/dist/agent/drivers/cursor.js +99 -0
- package/dist/agent/drivers/cursor.js.map +1 -0
- package/dist/ai/__tests__/ai-core.test.d.ts +2 -0
- package/dist/ai/__tests__/ai-core.test.d.ts.map +1 -0
- package/dist/ai/__tests__/ai-core.test.js +41 -0
- package/dist/ai/__tests__/ai-core.test.js.map +1 -0
- package/dist/ai/__tests__/parity.test.d.ts +2 -0
- package/dist/ai/__tests__/parity.test.d.ts.map +1 -0
- package/dist/ai/__tests__/parity.test.js +36 -0
- package/dist/ai/__tests__/parity.test.js.map +1 -0
- package/dist/ai/__tests__/pipeline.test.d.ts +2 -0
- package/dist/ai/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/ai/__tests__/pipeline.test.js +147 -0
- package/dist/ai/__tests__/pipeline.test.js.map +1 -0
- package/dist/ai/__tests__/refine-bridge.test.d.ts +2 -0
- package/dist/ai/__tests__/refine-bridge.test.d.ts.map +1 -0
- package/dist/ai/__tests__/refine-bridge.test.js +17 -0
- package/dist/ai/__tests__/refine-bridge.test.js.map +1 -0
- package/dist/ai/__tests__/resolve.test.d.ts +2 -0
- package/dist/ai/__tests__/resolve.test.d.ts.map +1 -0
- package/dist/ai/__tests__/resolve.test.js +42 -0
- package/dist/ai/__tests__/resolve.test.js.map +1 -0
- package/dist/ai/capabilities.d.ts +3 -0
- package/dist/ai/capabilities.d.ts.map +1 -0
- package/dist/ai/capabilities.js +11 -0
- package/dist/ai/capabilities.js.map +1 -0
- package/dist/ai/command-options.d.ts +10 -0
- package/dist/ai/command-options.d.ts.map +1 -0
- package/dist/ai/command-options.js +15 -0
- package/dist/ai/command-options.js.map +1 -0
- package/dist/ai/config.d.ts +27 -0
- package/dist/ai/config.d.ts.map +1 -0
- package/dist/ai/config.js +89 -0
- package/dist/ai/config.js.map +1 -0
- package/dist/ai/parity.d.ts +13 -0
- package/dist/ai/parity.d.ts.map +1 -0
- package/dist/ai/parity.js +87 -0
- package/dist/ai/parity.js.map +1 -0
- package/dist/ai/parse-json-output.d.ts +5 -0
- package/dist/ai/parse-json-output.d.ts.map +1 -0
- package/dist/ai/parse-json-output.js +25 -0
- package/dist/ai/parse-json-output.js.map +1 -0
- package/dist/ai/pipeline.d.ts +20 -0
- package/dist/ai/pipeline.d.ts.map +1 -0
- package/dist/ai/pipeline.js +303 -0
- package/dist/ai/pipeline.js.map +1 -0
- package/dist/ai/prompts.d.ts +6 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +49 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/providers.d.ts +63 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +297 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/ai/refine-bridge.d.ts +5 -0
- package/dist/ai/refine-bridge.d.ts.map +1 -0
- package/dist/ai/refine-bridge.js +14 -0
- package/dist/ai/refine-bridge.js.map +1 -0
- package/dist/ai/registry.d.ts +12 -0
- package/dist/ai/registry.d.ts.map +1 -0
- package/dist/ai/registry.js +43 -0
- package/dist/ai/registry.js.map +1 -0
- package/dist/ai/resolve.d.ts +28 -0
- package/dist/ai/resolve.d.ts.map +1 -0
- package/dist/ai/resolve.js +83 -0
- package/dist/ai/resolve.js.map +1 -0
- package/dist/ai/schemas.d.ts +175 -0
- package/dist/ai/schemas.d.ts.map +1 -0
- package/dist/ai/schemas.js +199 -0
- package/dist/ai/schemas.js.map +1 -0
- package/dist/ai/types.d.ts +52 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +8 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/bin/dare.js +2 -0
- package/dist/bin/dare.js.map +1 -1
- package/dist/commands/__tests__/ai-command.test.d.ts +2 -0
- package/dist/commands/__tests__/ai-command.test.d.ts.map +1 -0
- package/dist/commands/__tests__/ai-command.test.js +68 -0
- package/dist/commands/__tests__/ai-command.test.js.map +1 -0
- package/dist/commands/__tests__/execute-agent.test.js +82 -0
- package/dist/commands/__tests__/execute-agent.test.js.map +1 -1
- package/dist/commands/ai.d.ts +3 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +141 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/blueprint.d.ts.map +1 -1
- package/dist/commands/blueprint.js +17 -3
- package/dist/commands/blueprint.js.map +1 -1
- package/dist/commands/design.d.ts.map +1 -1
- package/dist/commands/design.js +21 -2
- package/dist/commands/design.js.map +1 -1
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +9 -1
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/dna.d.ts.map +1 -1
- package/dist/commands/dna.js +23 -3
- package/dist/commands/dna.js.map +1 -1
- package/dist/commands/execute.d.ts +11 -0
- package/dist/commands/execute.d.ts.map +1 -1
- package/dist/commands/execute.js +111 -4
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +14 -2
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/patterns.d.ts.map +1 -1
- package/dist/commands/patterns.js +14 -2
- package/dist/commands/patterns.js.map +1 -1
- package/dist/commands/refine.d.ts.map +1 -1
- package/dist/commands/refine.js +23 -2
- package/dist/commands/refine.js.map +1 -1
- package/dist/commands/reverse.d.ts.map +1 -1
- package/dist/commands/reverse.js +28 -3
- package/dist/commands/reverse.js.map +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +25 -3
- package/dist/commands/review.js.map +1 -1
- package/dist/core/types/project.d.ts +1 -1
- package/dist/core/types/project.d.ts.map +1 -1
- package/dist/dag-runner/run_dag.d.ts +1 -1
- package/dist/dag-runner/run_dag.d.ts.map +1 -1
- package/dist/exec/safe-spawn.d.ts.map +1 -1
- package/dist/exec/safe-spawn.js +6 -1
- package/dist/exec/safe-spawn.js.map +1 -1
- package/dist/skills/bundled.d.ts +5 -0
- package/dist/skills/bundled.d.ts.map +1 -0
- package/dist/skills/bundled.js +34 -0
- package/dist/skills/bundled.js.map +1 -0
- package/dist/skills/commands/add.d.ts +1 -3
- package/dist/skills/commands/add.d.ts.map +1 -1
- package/dist/skills/commands/add.js +20 -3
- package/dist/skills/commands/add.js.map +1 -1
- package/dist/skills/tests/bundled.spec.d.ts +2 -0
- package/dist/skills/tests/bundled.spec.d.ts.map +1 -0
- package/dist/skills/tests/bundled.spec.js +24 -0
- package/dist/skills/tests/bundled.spec.js.map +1 -0
- package/dist/types/UpdateManifest.types.d.ts +1 -1
- package/dist/types/UpdateManifest.types.d.ts.map +1 -1
- package/dist/utils/dag-converter.js +1 -1
- package/dist/utils/dag-converter.js.map +1 -1
- package/dist/utils/project-detector.d.ts +1 -0
- package/dist/utils/project-detector.d.ts.map +1 -1
- package/dist/utils/project-detector.js +8 -0
- package/dist/utils/project-detector.js.map +1 -1
- package/dist/utils/project-generator.d.ts +1 -1
- package/dist/utils/project-generator.d.ts.map +1 -1
- package/dist/utils/project-generator.js +23 -2
- package/dist/utils/project-generator.js.map +1 -1
- package/dist/utils/templates.d.ts +2 -0
- package/dist/utils/templates.d.ts.map +1 -1
- package/dist/utils/templates.js +74 -0
- package/dist/utils/templates.js.map +1 -1
- package/dist/verification/__tests__/safe-spawn.test.js +12 -0
- package/dist/verification/__tests__/safe-spawn.test.js.map +1 -1
- package/package.json +2 -1
- package/skills/dare-ax/generator.ts +325 -0
- package/skills/dare-ax/index.ts +19 -0
- package/skills/dare-ax/metrics.ts +352 -0
- package/skills/dare-ax/package-lock.json +1855 -0
- package/skills/dare-ax/package.json +50 -0
- package/skills/dare-ax/secret-detector.ts +123 -0
- package/skills/dare-ax/skill.yml +19 -0
- package/skills/dare-ax/templates/llms.txt.jinja2 +80 -0
- package/skills/dare-ax/tests/generator.spec.ts +193 -0
- package/skills/dare-ax/tests/metrics.spec.ts +394 -0
- package/skills/dare-ax/tests/validator.spec.ts +298 -0
- package/skills/dare-ax/tsconfig.json +18 -0
- package/skills/dare-ax/types.ts +79 -0
- package/skills/dare-ax/validator.ts +238 -0
- package/skills/dare-frontend-design/generator.ts +616 -0
- package/skills/dare-frontend-design/index.ts +25 -0
- package/skills/dare-frontend-design/linter.ts +227 -0
- package/skills/dare-frontend-design/metrics.ts +82 -0
- package/skills/dare-frontend-design/package-lock.json +1855 -0
- package/skills/dare-frontend-design/package.json +43 -0
- package/skills/dare-frontend-design/skill.yml +20 -0
- package/skills/dare-frontend-design/tests/frontend_design.spec.ts +435 -0
- package/skills/dare-frontend-design/tsconfig.json +18 -0
- package/skills/dare-frontend-design/types.ts +62 -0
- package/skills/dare-layered-design/generator.ts +740 -0
- package/skills/dare-layered-design/index.ts +17 -0
- package/skills/dare-layered-design/linter.ts +462 -0
- package/skills/dare-layered-design/metrics.ts +409 -0
- package/skills/dare-layered-design/package-lock.json +1855 -0
- package/skills/dare-layered-design/package.json +50 -0
- package/skills/dare-layered-design/skill.yml +35 -0
- package/skills/dare-layered-design/tests/generator.spec.ts +156 -0
- package/skills/dare-layered-design/tests/linter.spec.ts +255 -0
- package/skills/dare-layered-design/tests/metrics.spec.ts +286 -0
- package/skills/dare-layered-design/tsconfig.json +18 -0
- package/skills/dare-layered-design/types.ts +48 -0
- package/skills/dare-llm-integration/cache/llm_cache.ts +122 -0
- package/skills/dare-llm-integration/index.ts +49 -0
- package/skills/dare-llm-integration/metrics.ts +107 -0
- package/skills/dare-llm-integration/package-lock.json +1855 -0
- package/skills/dare-llm-integration/package.json +49 -0
- package/skills/dare-llm-integration/prompts/prompt_loader.ts +258 -0
- package/skills/dare-llm-integration/providers/anthropic_provider.ts +159 -0
- package/skills/dare-llm-integration/providers/dummy_provider.ts +113 -0
- package/skills/dare-llm-integration/providers/llm_provider.ts +6 -0
- package/skills/dare-llm-integration/providers/openai_provider.ts +215 -0
- package/skills/dare-llm-integration/rate_limit/token_bucket.ts +86 -0
- package/skills/dare-llm-integration/skill.yml +23 -0
- package/skills/dare-llm-integration/tests/fixtures/greet_v1.jinja2 +1 -0
- package/skills/dare-llm-integration/tests/fixtures/summarize_v1.jinja2 +1 -0
- package/skills/dare-llm-integration/tests/fixtures/summarize_v2.jinja2 +3 -0
- package/skills/dare-llm-integration/tests/llm_integration.spec.ts +657 -0
- package/skills/dare-llm-integration/tsconfig.json +23 -0
- package/skills/dare-llm-integration/types.ts +91 -0
- package/skills/dare-llm-integration/validators/output_validator.ts +200 -0
- package/skills/dare-quality-telemetry/collect.ts +134 -0
- package/skills/dare-quality-telemetry/collectors/dare_ax_collector.ts +301 -0
- package/skills/dare-quality-telemetry/collectors/dare_layered_design_collector.ts +406 -0
- package/skills/dare-quality-telemetry/collectors/index.ts +24 -0
- package/skills/dare-quality-telemetry/github_actions_template.ts +25 -0
- package/skills/dare-quality-telemetry/index.ts +18 -0
- package/skills/dare-quality-telemetry/metrics.ts +137 -0
- package/skills/dare-quality-telemetry/package-lock.json +1855 -0
- package/skills/dare-quality-telemetry/package.json +48 -0
- package/skills/dare-quality-telemetry/regression.ts +60 -0
- package/skills/dare-quality-telemetry/reporter.ts +132 -0
- package/skills/dare-quality-telemetry/skill.yml +18 -0
- package/skills/dare-quality-telemetry/tests/quality_telemetry.spec.ts +885 -0
- package/skills/dare-quality-telemetry/tsconfig.json +19 -0
- package/skills/dare-quality-telemetry/types.ts +41 -0
- package/skills/dare-realtime/event_registry.ts +101 -0
- package/skills/dare-realtime/index.ts +30 -0
- package/skills/dare-realtime/metrics.ts +84 -0
- package/skills/dare-realtime/package-lock.json +1855 -0
- package/skills/dare-realtime/package.json +43 -0
- package/skills/dare-realtime/reconnect_strategy.ts +85 -0
- package/skills/dare-realtime/schema_validator.ts +80 -0
- package/skills/dare-realtime/skill.yml +21 -0
- package/skills/dare-realtime/subscription_manager.ts +106 -0
- package/skills/dare-realtime/tests/realtime.spec.ts +482 -0
- package/skills/dare-realtime/tsconfig.json +18 -0
- package/skills/dare-realtime/types.ts +51 -0
- package/templates/ide/antigravity/.agents/skills/dare-ai/SKILL.md +17 -0
- package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +2 -0
- package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +2 -0
- package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-patterns/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +3 -0
- package/templates/ide/claude/.claude/commands/dare-ai.md +17 -0
- package/templates/ide/claude/.claude/commands/dare-blueprint.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-design.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-dna.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-migrate.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-patterns.md +3 -0
- package/templates/ide/claude/.claude/commands/dare-refine.md +3 -0
- package/templates/ide/claude/.claude/commands/dare-reverse.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-review.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-ai.md +17 -0
- package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-design.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-dna.md +2 -0
- package/templates/ide/cursor/.cursor/commands/dare-migrate.md +2 -0
- package/templates/ide/cursor/.cursor/commands/dare-patterns.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-refine.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-reverse.md +2 -0
- package/templates/ide/cursor/.cursor/commands/dare-review.md +3 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dare-ax — shared types
|
|
3
|
+
* License: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface RateLimit {
|
|
7
|
+
scope: string;
|
|
8
|
+
limit: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Endpoint {
|
|
12
|
+
method: string;
|
|
13
|
+
path: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ProjectConfig {
|
|
18
|
+
/** Project name */
|
|
19
|
+
name: string;
|
|
20
|
+
/** One-paragraph description of what the project does */
|
|
21
|
+
projectOverview: string;
|
|
22
|
+
/** Primary language (Rust, TypeScript, Python, Ruby, Go, PHP, etc.) */
|
|
23
|
+
language: string;
|
|
24
|
+
/** Framework (Axum, NestJS, FastAPI, Rails, Gin, Laravel, etc.) */
|
|
25
|
+
framework: string;
|
|
26
|
+
/** Database (Postgres, MongoDB, Redis, None, etc.) */
|
|
27
|
+
database: string;
|
|
28
|
+
/** List of 5-10 key dependencies */
|
|
29
|
+
keyDependencies: string[];
|
|
30
|
+
/** 3-5 sentence architecture description */
|
|
31
|
+
architectureDescription: string;
|
|
32
|
+
/** ASCII directory tree (optional) */
|
|
33
|
+
directoryStructure?: string;
|
|
34
|
+
/** HTTP endpoints (optional) */
|
|
35
|
+
endpoints?: Endpoint[];
|
|
36
|
+
/** Config file name (default: "config.json") */
|
|
37
|
+
configFile?: string;
|
|
38
|
+
/** Whether project has docker-compose.yml */
|
|
39
|
+
hasDocker?: boolean;
|
|
40
|
+
/** Whether project has a Makefile */
|
|
41
|
+
hasMakefile?: boolean;
|
|
42
|
+
/** Whether project has tasks.json / Taskfile */
|
|
43
|
+
hasTaskfile?: boolean;
|
|
44
|
+
/** Getting started command (default: "make dev") */
|
|
45
|
+
gettingStartedCommand?: string;
|
|
46
|
+
/** Rate limit definitions (default: public 100/min, auth 10/min) */
|
|
47
|
+
rateLimits?: RateLimit[];
|
|
48
|
+
/** Additional security notes */
|
|
49
|
+
extraSecurityNotes?: string[];
|
|
50
|
+
/** CLI binary name (default: project name) */
|
|
51
|
+
cliBinary?: string;
|
|
52
|
+
/** Additional notes for AI agents */
|
|
53
|
+
agentNotes?: string[];
|
|
54
|
+
/** If true, skip AX validation in CI */
|
|
55
|
+
axNotApplicable?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ValidationResult {
|
|
59
|
+
valid: boolean;
|
|
60
|
+
errors: ValidationError[];
|
|
61
|
+
warnings: ValidationWarning[];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ValidationError {
|
|
65
|
+
code: string;
|
|
66
|
+
message: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ValidationWarning {
|
|
70
|
+
code: string;
|
|
71
|
+
message: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface MetricResult {
|
|
75
|
+
id: string;
|
|
76
|
+
pass: boolean;
|
|
77
|
+
description: string;
|
|
78
|
+
detail?: string;
|
|
79
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dare-ax — DareAxValidator
|
|
3
|
+
* Validates the structure and security of llms.txt.
|
|
4
|
+
* License: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import { ValidationResult, ValidationError, ValidationWarning } from './types.js';
|
|
9
|
+
import { findAllSecrets } from './secret-detector.js';
|
|
10
|
+
|
|
11
|
+
/** Required top-level sections in a valid llms.txt */
|
|
12
|
+
const REQUIRED_SECTIONS = [
|
|
13
|
+
'Project Overview',
|
|
14
|
+
'Tech Stack',
|
|
15
|
+
'Architecture',
|
|
16
|
+
'Key Endpoints',
|
|
17
|
+
'For AI Agents',
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
/** Optional but recommended sections */
|
|
21
|
+
const RECOMMENDED_SECTIONS = [
|
|
22
|
+
'Directory Structure',
|
|
23
|
+
'Getting Started',
|
|
24
|
+
'Rate Limits',
|
|
25
|
+
'Security Notes',
|
|
26
|
+
'Important Files',
|
|
27
|
+
] as const;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Minimum character count for a non-trivial section body.
|
|
31
|
+
* A section with < MIN_SECTION_BODY chars is considered empty/stub.
|
|
32
|
+
*/
|
|
33
|
+
const MIN_SECTION_BODY = 10;
|
|
34
|
+
|
|
35
|
+
export class DareAxValidator {
|
|
36
|
+
/**
|
|
37
|
+
* Validates a llms.txt file at the given path.
|
|
38
|
+
*
|
|
39
|
+
* @param llmsTxtPath - Absolute path to the llms.txt file.
|
|
40
|
+
* @returns ValidationResult with errors and warnings.
|
|
41
|
+
*/
|
|
42
|
+
validate(llmsTxtPath: string): ValidationResult {
|
|
43
|
+
const errors: ValidationError[] = [];
|
|
44
|
+
const warnings: ValidationWarning[] = [];
|
|
45
|
+
|
|
46
|
+
// Check file existence
|
|
47
|
+
if (!fs.existsSync(llmsTxtPath)) {
|
|
48
|
+
errors.push({
|
|
49
|
+
code: 'E_FILE_NOT_FOUND',
|
|
50
|
+
message: `llms.txt not found at path: ${llmsTxtPath}`,
|
|
51
|
+
});
|
|
52
|
+
return { valid: false, errors, warnings };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let content: string;
|
|
56
|
+
try {
|
|
57
|
+
content = fs.readFileSync(llmsTxtPath, 'utf-8');
|
|
58
|
+
} catch (err) {
|
|
59
|
+
errors.push({
|
|
60
|
+
code: 'E_FILE_READ_ERROR',
|
|
61
|
+
message: `Failed to read llms.txt: ${(err as Error).message}`,
|
|
62
|
+
});
|
|
63
|
+
return { valid: false, errors, warnings };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check empty file
|
|
67
|
+
if (!content.trim()) {
|
|
68
|
+
errors.push({
|
|
69
|
+
code: 'E_EMPTY_FILE',
|
|
70
|
+
message: 'llms.txt is empty.',
|
|
71
|
+
});
|
|
72
|
+
return { valid: false, errors, warnings };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Parse sections: lines starting with "## Section Name"
|
|
76
|
+
const sections = parseSections(content);
|
|
77
|
+
|
|
78
|
+
// Check required sections
|
|
79
|
+
for (const required of REQUIRED_SECTIONS) {
|
|
80
|
+
if (!sections.has(required)) {
|
|
81
|
+
errors.push({
|
|
82
|
+
code: 'E_MISSING_SECTION',
|
|
83
|
+
message: `Required section "## ${required}" is missing from llms.txt.`,
|
|
84
|
+
});
|
|
85
|
+
} else {
|
|
86
|
+
const body = sections.get(required)!.trim();
|
|
87
|
+
if (body.length < MIN_SECTION_BODY) {
|
|
88
|
+
errors.push({
|
|
89
|
+
code: 'E_EMPTY_SECTION',
|
|
90
|
+
message: `Section "## ${required}" exists but appears to be empty or a stub (body: "${body.slice(0, 40)}").`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Check recommended sections (warnings only)
|
|
97
|
+
for (const recommended of RECOMMENDED_SECTIONS) {
|
|
98
|
+
if (!sections.has(recommended)) {
|
|
99
|
+
warnings.push({
|
|
100
|
+
code: 'W_MISSING_RECOMMENDED_SECTION',
|
|
101
|
+
message: `Recommended section "## ${recommended}" is missing from llms.txt.`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Check for secrets
|
|
107
|
+
const secrets = findAllSecrets(content);
|
|
108
|
+
for (const secret of secrets) {
|
|
109
|
+
errors.push({
|
|
110
|
+
code: 'E_SECRET_DETECTED',
|
|
111
|
+
message: `Secret detected in llms.txt at line ${secret.line}: [${secret.pattern}]. ` +
|
|
112
|
+
`Content: "${secret.lineContent.slice(0, 80)}". llms.txt is a public file — remove all secrets.`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Check that "For AI Agents" section mentions OpenAPI
|
|
117
|
+
const forAiSection = sections.get('For AI Agents');
|
|
118
|
+
if (forAiSection && !forAiSection.toLowerCase().includes('openapi')) {
|
|
119
|
+
warnings.push({
|
|
120
|
+
code: 'W_MISSING_OPENAPI_REFERENCE',
|
|
121
|
+
message: 'Section "## For AI Agents" does not mention OpenAPI. Consider adding a reference to /openapi.json.',
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Check that "For AI Agents" section mentions --json
|
|
126
|
+
if (forAiSection && !forAiSection.includes('--json')) {
|
|
127
|
+
warnings.push({
|
|
128
|
+
code: 'W_MISSING_JSON_FLAG_REFERENCE',
|
|
129
|
+
message: 'Section "## For AI Agents" does not mention --json CLI flag.',
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const valid = errors.length === 0;
|
|
134
|
+
return { valid, errors, warnings };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Validates raw llms.txt content (string) without reading from disk.
|
|
139
|
+
* Useful for previewing generated content before writing.
|
|
140
|
+
*/
|
|
141
|
+
validateContent(content: string): ValidationResult {
|
|
142
|
+
const errors: ValidationError[] = [];
|
|
143
|
+
const warnings: ValidationWarning[] = [];
|
|
144
|
+
|
|
145
|
+
if (!content.trim()) {
|
|
146
|
+
errors.push({ code: 'E_EMPTY_FILE', message: 'Content is empty.' });
|
|
147
|
+
return { valid: false, errors, warnings };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const sections = parseSections(content);
|
|
151
|
+
|
|
152
|
+
for (const required of REQUIRED_SECTIONS) {
|
|
153
|
+
if (!sections.has(required)) {
|
|
154
|
+
errors.push({
|
|
155
|
+
code: 'E_MISSING_SECTION',
|
|
156
|
+
message: `Required section "## ${required}" is missing.`,
|
|
157
|
+
});
|
|
158
|
+
} else {
|
|
159
|
+
const body = sections.get(required)!.trim();
|
|
160
|
+
if (body.length < MIN_SECTION_BODY) {
|
|
161
|
+
errors.push({
|
|
162
|
+
code: 'E_EMPTY_SECTION',
|
|
163
|
+
message: `Section "## ${required}" is empty or a stub.`,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
for (const recommended of RECOMMENDED_SECTIONS) {
|
|
170
|
+
if (!sections.has(recommended)) {
|
|
171
|
+
warnings.push({
|
|
172
|
+
code: 'W_MISSING_RECOMMENDED_SECTION',
|
|
173
|
+
message: `Recommended section "## ${recommended}" is missing.`,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const secrets = findAllSecrets(content);
|
|
179
|
+
for (const secret of secrets) {
|
|
180
|
+
errors.push({
|
|
181
|
+
code: 'E_SECRET_DETECTED',
|
|
182
|
+
message: `Secret detected at line ${secret.line}: [${secret.pattern}].`,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const forAiSection = sections.get('For AI Agents');
|
|
187
|
+
if (forAiSection && !forAiSection.toLowerCase().includes('openapi')) {
|
|
188
|
+
warnings.push({
|
|
189
|
+
code: 'W_MISSING_OPENAPI_REFERENCE',
|
|
190
|
+
message: '"## For AI Agents" does not mention OpenAPI.',
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (forAiSection && !forAiSection.includes('--json')) {
|
|
195
|
+
warnings.push({
|
|
196
|
+
code: 'W_MISSING_JSON_FLAG_REFERENCE',
|
|
197
|
+
message: '"## For AI Agents" does not mention --json flag.',
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Parses section headings (## Section Name) and their body text from a llms.txt string.
|
|
207
|
+
* Returns a Map<sectionName, bodyText>.
|
|
208
|
+
*/
|
|
209
|
+
function parseSections(content: string): Map<string, string> {
|
|
210
|
+
const sections = new Map<string, string>();
|
|
211
|
+
const lines = content.split('\n');
|
|
212
|
+
|
|
213
|
+
let currentSection: string | null = null;
|
|
214
|
+
const bodyLines: string[] = [];
|
|
215
|
+
|
|
216
|
+
for (const line of lines) {
|
|
217
|
+
// Match "## Section Name" (exactly two hashes, not more)
|
|
218
|
+
const sectionMatch = /^##\s+(.+)$/.exec(line);
|
|
219
|
+
|
|
220
|
+
if (sectionMatch) {
|
|
221
|
+
// Save previous section body
|
|
222
|
+
if (currentSection !== null) {
|
|
223
|
+
sections.set(currentSection, bodyLines.join('\n'));
|
|
224
|
+
}
|
|
225
|
+
currentSection = sectionMatch[1].trim();
|
|
226
|
+
bodyLines.length = 0;
|
|
227
|
+
} else if (currentSection !== null) {
|
|
228
|
+
bodyLines.push(line);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Save last section
|
|
233
|
+
if (currentSection !== null) {
|
|
234
|
+
sections.set(currentSection, bodyLines.join('\n'));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return sections;
|
|
238
|
+
}
|