ai-design-context 0.4.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/AGENTS.md +156 -0
- package/CHANGELOG.md +71 -0
- package/CODE_OF_CONDUCT.md +29 -0
- package/CONTRIBUTING.md +128 -0
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/RELEASE_NOTES_v0.1.0.md +45 -0
- package/RELEASE_NOTES_v0.3.0.md +47 -0
- package/RELEASE_NOTES_v0.4.0.md +29 -0
- package/RELEASE_READINESS.md +107 -0
- package/ROADMAP.md +60 -0
- package/SECURITY.md +40 -0
- package/assets/logo.svg +9 -0
- package/benchmarks/README.md +19 -0
- package/benchmarks/chat.md +37 -0
- package/benchmarks/mobile-home-screen.md +38 -0
- package/benchmarks/notes-app.md +37 -0
- package/benchmarks/settings.md +37 -0
- package/benchmarks/shopping-list.md +37 -0
- package/benchmarks/todo-app.md +144 -0
- package/checklists/DESIGN_QA.md +102 -0
- package/checklists/GENERATED_INDEX.md +7 -0
- package/docs/AGENT_CONTEXT.md +111 -0
- package/docs/BENCHMARK.md +170 -0
- package/docs/DESIGNLINT_READINESS.md +110 -0
- package/docs/DESIGN_SYSTEM.md +23 -0
- package/docs/EVALUATION_RUBRIC.md +154 -0
- package/docs/GITHUB_SETUP.md +28 -0
- package/docs/GLOSSARY.md +45 -0
- package/docs/INDEX.md +109 -0
- package/docs/KNOWLEDGE_ENGINE.md +594 -0
- package/docs/MOBILE_FIRST.md +18 -0
- package/docs/NPM_RELEASE.md +43 -0
- package/docs/PATTERN_SPEC.md +113 -0
- package/docs/PHILOSOPHY.md +25 -0
- package/docs/PRODUCT_THINKING.md +26 -0
- package/docs/STYLE_GUIDE.md +49 -0
- package/docs/TRACEABILITY.md +45 -0
- package/evidence/README.md +64 -0
- package/evidence/TEMPLATE.md +46 -0
- package/evidence/chat/.gitkeep +1 -0
- package/evidence/mobile-home/.gitkeep +1 -0
- package/evidence/notes/.gitkeep +1 -0
- package/evidence/settings/.gitkeep +1 -0
- package/evidence/shopping/.gitkeep +1 -0
- package/evidence/todo/.gitkeep +1 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/EVALUATION.md +66 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/README.md +40 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/ai-design-rules/generated-output.md +163 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/ai-design-rules/metadata.json +38 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/ai-design-rules/notes.md +20 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/ai-design-rules/prompt.md +16 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/ai-design-rules/scores.md +18 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/baseline/generated-output.md +98 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/baseline/metadata.json +19 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/baseline/notes.md +19 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/baseline/prompt.md +9 -0
- package/evidence/todo/2026-06-25-codex-gpt-5/baseline/scores.md +18 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/EVALUATION.md +70 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/README.md +52 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/GENERATION_NOTES.md +133 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/app.js +289 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/context/context-preserving-preview.json +443 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/context/daily-home-surface.json +373 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/context/quick-capture.json +301 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/context/sources-read.txt +36 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/generated-output.md +11 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/index.html +64 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/launch-prompt.md +1 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/metadata.json +55 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/notes.md +15 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/parent-status-message.md +1 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/prompt.md +49 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/runtime-checks.json +776 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/scores.md +20 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-completed.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-default.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-detail-reduced-motion.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-detail.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-empty.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-keyboard-focus.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-save-error.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-saved.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-saving.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/desktop-validation.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-completed.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-default.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-detail-reduced-motion.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-detail.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-empty.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-keyboard-focus.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-save-error.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-saved.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-saving.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/screenshots/mobile-validation.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/source-hashes.json +5 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/ai-design-rules/styles.css +122 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/GENERATION_NOTES.md +86 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/app.js +303 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/generated-output.md +11 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/index.html +71 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/launch-prompt.md +1 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/metadata.json +55 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/notes.md +15 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/parent-status-message.md +1 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/prompt.md +49 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/runtime-checks.json +772 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/scores.md +20 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-completed.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-default.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-detail-reduced-motion.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-detail.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-empty.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-keyboard-focus.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-save-error.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-saved.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-saving.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/desktop-validation.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-completed.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-default.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-detail-reduced-motion.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-detail.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-empty.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-keyboard-focus.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-save-error.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-saved.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-saving.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/screenshots/mobile-validation.png +0 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/source-hashes.json +5 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/baseline/styles.css +9 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/capture-ai-design-rules.js +60 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/capture-baseline.js +60 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/common/brief.md +35 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/common/knowledge-files.json +127 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/common/knowledge.patch +890 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/common/review-context.json +550 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/common/seed.json +86 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/common/setup.json +47 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/common/technical-envelope.md +11 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/layout-metrics.json +133 -0
- package/evidence/todo/2026-09-28-codex-paired-todo/layout-probe.js +15 -0
- package/examples/GENERATED_INDEX.md +8 -0
- package/examples/INDEX.md +16 -0
- package/examples/README.md +15 -0
- package/examples/consequential-action-confirmation-reference.md +83 -0
- package/examples/todo-app-benchmark.md +117 -0
- package/examples/todo-reference/README.md +29 -0
- package/examples/todo-reference/app.js +154 -0
- package/examples/todo-reference/favicon.svg +4 -0
- package/examples/todo-reference/index.html +67 -0
- package/examples/todo-reference/review-evidence/2026-07-15/desktop-default.png +0 -0
- package/examples/todo-reference/review-evidence/2026-07-15/desktop-detail.png +0 -0
- package/examples/todo-reference/review-evidence/2026-07-15/mobile-detail.png +0 -0
- package/examples/todo-reference/review-evidence/2026-07-15/mobile-error.png +0 -0
- package/examples/todo-reference/styles.css +241 -0
- package/graph/GENERATED_GRAPH.md +71 -0
- package/observations/README.md +23 -0
- package/observations/accessibility/reduced-interaction-motion.md +49 -0
- package/observations/accessibility/textual-error-recovery.md +50 -0
- package/observations/accessibility/visible-keyboard-focus.md +49 -0
- package/observations/ai/agent-consequential-action-controls.md +56 -0
- package/observations/ai/agent-work-visibility-and-intervention.md +51 -0
- package/observations/ai/figma-agent-context-and-skills.md +52 -0
- package/observations/finance/high-risk-wallet-recovery-flows.md +55 -0
- package/observations/finance/market-interface-adaptive-trading-surfaces.md +55 -0
- package/observations/interaction/chrome-scoped-view-transitions.md +52 -0
- package/observations/interaction/figma-motion-as-system-capability.md +53 -0
- package/observations/mobile/mobile-bottom-sheet-choice-contracts.md +55 -0
- package/observations/performance/reserved-loading-space.md +51 -0
- package/observations/product-repos/pinned-ai-design-rules-integration.md +49 -0
- package/observations/visual/apple-liquid-glass-functional-layer.md +52 -0
- package/observations/visual/chrome-content-first-adaptive-ui.md +51 -0
- package/observations/visual/material-3-expressive-system.md +52 -0
- package/package.json +65 -0
- package/patterns/GENERATED_INDEX.md +13 -0
- package/patterns/INDEX.md +41 -0
- package/patterns/README.md +5 -0
- package/patterns/consequential-action-confirmation.md +127 -0
- package/patterns/context-preserving-preview.md +145 -0
- package/patterns/daily-home-surface.md +134 -0
- package/patterns/mobile-primary-action.md +110 -0
- package/patterns/object-status-list.md +114 -0
- package/patterns/progressive-detail.md +113 -0
- package/patterns/quick-capture.md +132 -0
- package/prompts/CONSEQUENTIAL_ACTION_REVIEW.md +100 -0
- package/prompts/DESIGN_EVIDENCE_REVIEW.md +49 -0
- package/prompts/GENERATED_INDEX.md +11 -0
- package/prompts/INDEX.md +24 -0
- package/prompts/PROTOTYPE_REVIEW.md +189 -0
- package/prompts/QUICK_CAPTURE_STATE_REVIEW.md +74 -0
- package/prompts/TODO_APP_BENCHMARK.md +88 -0
- package/registry/objects.json +568 -0
- package/registry/relationships.json +972 -0
- package/research/GENERATED_INDEX.md +18 -0
- package/research/INDEX.md +40 -0
- package/research/accessibility/keyboard-focus-and-interaction-motion.md +62 -0
- package/research/accessibility/textual-error-recovery.md +57 -0
- package/research/performance/reserved-loading-space.md +56 -0
- package/research/products/apple-reminders.md +59 -0
- package/research/products/arc.md +61 -0
- package/research/products/linear.md +62 -0
- package/research/products/telegram.md +61 -0
- package/research/products/things-3.md +60 -0
- package/research/ux/contextual-agentic-interface.md +68 -0
- package/research/ux/high-risk-operational-flows.md +89 -0
- package/research/ux/motion-as-state-continuity.md +71 -0
- package/research/visual/expressive-system-ui-2026.md +75 -0
- package/reviews/GENERATED_INDEX.md +9 -0
- package/reviews/README.md +25 -0
- package/reviews/consequential-action-confirmation-review.md +92 -0
- package/reviews/todo-app-benchmark-reference-review.md +86 -0
- package/reviews/todo-reference-fixture-review.md +77 -0
- package/rules/GENERATED_INDEX.md +23 -0
- package/rules/INDEX.md +37 -0
- package/rules/accessibility/A11Y-001.md +58 -0
- package/rules/accessibility/A11Y-002.md +55 -0
- package/rules/accessibility/A11Y-003.md +54 -0
- package/rules/accessibility/A11Y-004.md +54 -0
- package/rules/ia/IA-001.md +60 -0
- package/rules/ia/IA-002.md +61 -0
- package/rules/performance/PERF-001.md +55 -0
- package/rules/product/PRD-001.md +61 -0
- package/rules/product/PRD-002.md +61 -0
- package/rules/ux/UX-001.md +58 -0
- package/rules/ux/UX-002.md +61 -0
- package/rules/ux/UX-003.md +60 -0
- package/rules/ux/UX-004.md +61 -0
- package/rules/ux/UX-005.md +62 -0
- package/rules/ux/UX-006.md +69 -0
- package/rules/visual/VIS-001.md +59 -0
- package/rules/visual/VIS-002.md +59 -0
- package/schema/checklist.schema.json +21 -0
- package/schema/common.schema.json +178 -0
- package/schema/observation.schema.json +21 -0
- package/schema/pattern.schema.json +21 -0
- package/schema/prompt.schema.json +21 -0
- package/schema/reference-project.schema.json +21 -0
- package/schema/research.schema.json +21 -0
- package/schema/review.schema.json +21 -0
- package/schema/rule.schema.json +21 -0
- package/skills/README.md +48 -0
- package/skills/accessibility-reviewer/SKILL.md +101 -0
- package/skills/agent-context/SKILL.md +34 -0
- package/skills/agent-context/agents/openai.yaml +4 -0
- package/skills/design-evidence-researcher/SKILL.md +47 -0
- package/skills/design-evidence-researcher/agents/openai.yaml +4 -0
- package/skills/design-reviewer/SKILL.md +113 -0
- package/skills/design-system-architect/SKILL.md +101 -0
- package/skills/information-architect/SKILL.md +97 -0
- package/skills/interaction-designer/SKILL.md +104 -0
- package/skills/knowledge-graph-architect/SKILL.md +96 -0
- package/skills/mobile-ux-expert/SKILL.md +105 -0
- package/skills/motion-designer/SKILL.md +100 -0
- package/skills/performance-reviewer/SKILL.md +97 -0
- package/skills/product-designer/SKILL.md +104 -0
- package/skills/prompt-architect/SKILL.md +105 -0
- package/skills/reference-driven-design/SKILL.md +119 -0
- package/skills/ux-reviewer/SKILL.md +99 -0
- package/skills/visual-designer/SKILL.md +107 -0
- package/starter-kit/AGENTS.md +37 -0
- package/starter-kit/BOOTSTRAP.md +13 -0
- package/starter-kit/INSTALL_WITH_AGENT.md +133 -0
- package/starter-kit/PROJECT_INTEGRATION.md +60 -0
- package/starter-kit/README.md +41 -0
- package/starter-kit/benchmarks/BENCHMARK_CHECKLIST.md +10 -0
- package/starter-kit/docs/DESIGN_DECISIONS.md +22 -0
- package/starter-kit/docs/INFORMATION_ARCHITECTURE.md +25 -0
- package/starter-kit/docs/PERSONAS.md +14 -0
- package/starter-kit/docs/PRD.md +32 -0
- package/starter-kit/docs/USER_FLOWS.md +19 -0
- package/starter-kit/reviews/DESIGN_REVIEW.md +49 -0
- package/starter-kit/templates/FEATURE_TEMPLATE.md +36 -0
- package/starter-kit/templates/TASK_TEMPLATE.md +22 -0
- package/templates/CHECKLIST_TEMPLATE.md +43 -0
- package/templates/OBSERVATION_TEMPLATE.md +41 -0
- package/templates/PATTERN_TEMPLATE.md +100 -0
- package/templates/PROMPT_TEMPLATE.md +46 -0
- package/templates/PROTOTYPE_REVIEW.md +50 -0
- package/templates/REFERENCE_PROJECT_TEMPLATE.md +49 -0
- package/templates/REVIEW_TEMPLATE.md +55 -0
- package/templates/RULE_TEMPLATE.md +57 -0
- package/tools/cli.mjs +46 -0
- package/tools/context.mjs +342 -0
- package/tools/designlint.mjs +77 -0
- package/tools/generate-indexes.mjs +621 -0
- package/tools/init.mjs +99 -0
- package/tools/validate-benchmark-evidence.mjs +248 -0
- package/tools/validate-knowledge.mjs +481 -0
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const generatedNotice = 'This file is generated from registry metadata. Do not edit manually.';
|
|
6
|
+
|
|
7
|
+
function readRegistry(root) {
|
|
8
|
+
const objects = JSON.parse(fs.readFileSync(path.join(root, 'registry/objects.json'), 'utf8')).objects;
|
|
9
|
+
const relationships = JSON.parse(
|
|
10
|
+
fs.readFileSync(path.join(root, 'registry/relationships.json'), 'utf8'),
|
|
11
|
+
).relationships;
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
objects,
|
|
15
|
+
relationships,
|
|
16
|
+
objectsById: new Map(objects.map((object) => [object.id, object])),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function escapeCell(value) {
|
|
21
|
+
return String(value ?? 'None').replaceAll('|', '\\|');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function objectLabel(object) {
|
|
25
|
+
if (!object) {
|
|
26
|
+
return 'Missing object';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const alias = object.alias ? `${object.alias} / ` : '';
|
|
30
|
+
return `${alias}${object.id} ${object.title}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function listOrNone(values) {
|
|
34
|
+
return values.length > 0 ? values.join('<br>') : 'None';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function linesOrNone(values) {
|
|
38
|
+
return values.length > 0 ? values.map((value) => `- ${value}`).join('\n') : 'None';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function table(headers, rows) {
|
|
42
|
+
return [
|
|
43
|
+
`| ${headers.map(escapeCell).join(' | ')} |`,
|
|
44
|
+
`| ${headers.map(() => '---').join(' | ')} |`,
|
|
45
|
+
...rows.map((row) => `| ${row.map(escapeCell).join(' | ')} |`),
|
|
46
|
+
].join('\n');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function relationshipsFor(relationships, id) {
|
|
50
|
+
return relationships.filter((relationship) => relationship.source === id || relationship.target === id);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function generateRulesIndex(registry) {
|
|
54
|
+
const rules = registry.objects
|
|
55
|
+
.filter((object) => object.object_type === 'rule')
|
|
56
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
57
|
+
|
|
58
|
+
const rows = rules.map((rule) => {
|
|
59
|
+
const usedByPatterns = registry.relationships
|
|
60
|
+
.filter(
|
|
61
|
+
(relationship) =>
|
|
62
|
+
relationship.type === 'requires' &&
|
|
63
|
+
relationship.target === rule.id &&
|
|
64
|
+
registry.objectsById.get(relationship.source)?.object_type === 'pattern',
|
|
65
|
+
)
|
|
66
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.source)));
|
|
67
|
+
|
|
68
|
+
const relatedObjects = relationshipsFor(registry.relationships, rule.id)
|
|
69
|
+
.filter((relationship) => relationship.type !== 'requires')
|
|
70
|
+
.map((relationship) => {
|
|
71
|
+
const otherId = relationship.source === rule.id ? relationship.target : relationship.source;
|
|
72
|
+
return `${relationship.type}: ${objectLabel(registry.objectsById.get(otherId))}`;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return [
|
|
76
|
+
rule.id,
|
|
77
|
+
rule.alias,
|
|
78
|
+
rule.title,
|
|
79
|
+
rule.category,
|
|
80
|
+
rule.status,
|
|
81
|
+
rule.maturity,
|
|
82
|
+
rule.path,
|
|
83
|
+
listOrNone(usedByPatterns),
|
|
84
|
+
listOrNone(relatedObjects),
|
|
85
|
+
];
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return [
|
|
89
|
+
'# Generated Rules Index',
|
|
90
|
+
'',
|
|
91
|
+
generatedNotice,
|
|
92
|
+
'',
|
|
93
|
+
table(
|
|
94
|
+
['ID', 'Alias', 'Title', 'Category', 'Status', 'Maturity', 'File Path', 'Used By Patterns', 'Related Objects'],
|
|
95
|
+
rows,
|
|
96
|
+
),
|
|
97
|
+
'',
|
|
98
|
+
].join('\n');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function generateResearchIndex(registry) {
|
|
102
|
+
const researchObjects = registry.objects
|
|
103
|
+
.filter((object) => object.object_type === 'research')
|
|
104
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
105
|
+
|
|
106
|
+
const rows = researchObjects.map((research) => {
|
|
107
|
+
const derivedRules = registry.relationships
|
|
108
|
+
.filter(
|
|
109
|
+
(relationship) =>
|
|
110
|
+
['derived_from', 'inspired_by'].includes(relationship.type) &&
|
|
111
|
+
relationship.target === research.id &&
|
|
112
|
+
registry.objectsById.get(relationship.source)?.object_type === 'rule',
|
|
113
|
+
)
|
|
114
|
+
.map((relationship) => `${relationship.type}: ${objectLabel(registry.objectsById.get(relationship.source))}`);
|
|
115
|
+
|
|
116
|
+
return [
|
|
117
|
+
research.id,
|
|
118
|
+
research.alias,
|
|
119
|
+
research.title,
|
|
120
|
+
research.category,
|
|
121
|
+
research.status,
|
|
122
|
+
research.maturity,
|
|
123
|
+
research.path,
|
|
124
|
+
listOrNone(derivedRules),
|
|
125
|
+
];
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return [
|
|
129
|
+
'# Generated Research Index',
|
|
130
|
+
'',
|
|
131
|
+
generatedNotice,
|
|
132
|
+
'',
|
|
133
|
+
table(['ID', 'Alias', 'Title', 'Category', 'Status', 'Maturity', 'File Path', 'Derived Or Inspired Rules'], rows),
|
|
134
|
+
'',
|
|
135
|
+
].join('\n');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function generatePatternsIndex(registry) {
|
|
139
|
+
const patterns = registry.objects
|
|
140
|
+
.filter((object) => object.object_type === 'pattern')
|
|
141
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
142
|
+
|
|
143
|
+
const rows = patterns.map((pattern) => {
|
|
144
|
+
const requiredRules = registry.relationships
|
|
145
|
+
.filter(
|
|
146
|
+
(relationship) =>
|
|
147
|
+
relationship.type === 'requires' &&
|
|
148
|
+
relationship.source === pattern.id &&
|
|
149
|
+
registry.objectsById.get(relationship.target)?.object_type === 'rule',
|
|
150
|
+
)
|
|
151
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.target)));
|
|
152
|
+
|
|
153
|
+
const directResearch = registry.relationships
|
|
154
|
+
.filter(
|
|
155
|
+
(relationship) =>
|
|
156
|
+
relationship.source === pattern.id &&
|
|
157
|
+
['derived_from', 'cites', 'inspired_by'].includes(relationship.type) &&
|
|
158
|
+
registry.objectsById.get(relationship.target)?.object_type === 'research',
|
|
159
|
+
)
|
|
160
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.target)));
|
|
161
|
+
|
|
162
|
+
const researchFromRules = requiredRules.length
|
|
163
|
+
? registry.relationships
|
|
164
|
+
.filter(
|
|
165
|
+
(relationship) =>
|
|
166
|
+
['derived_from', 'inspired_by'].includes(relationship.type) &&
|
|
167
|
+
registry.objectsById.get(relationship.source)?.object_type === 'rule' &&
|
|
168
|
+
registry.objectsById.get(relationship.target)?.object_type === 'research' &&
|
|
169
|
+
registry.relationships.some(
|
|
170
|
+
(requiredRelationship) =>
|
|
171
|
+
requiredRelationship.type === 'requires' &&
|
|
172
|
+
requiredRelationship.source === pattern.id &&
|
|
173
|
+
requiredRelationship.target === relationship.source,
|
|
174
|
+
),
|
|
175
|
+
)
|
|
176
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.target)))
|
|
177
|
+
: [];
|
|
178
|
+
|
|
179
|
+
const relatedResearch = [...new Set([...directResearch, ...researchFromRules])];
|
|
180
|
+
|
|
181
|
+
return [
|
|
182
|
+
pattern.id,
|
|
183
|
+
pattern.alias,
|
|
184
|
+
pattern.title,
|
|
185
|
+
pattern.category,
|
|
186
|
+
pattern.status,
|
|
187
|
+
pattern.maturity,
|
|
188
|
+
pattern.path,
|
|
189
|
+
listOrNone(requiredRules),
|
|
190
|
+
listOrNone(relatedResearch),
|
|
191
|
+
];
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
return [
|
|
195
|
+
'# Generated Patterns Index',
|
|
196
|
+
'',
|
|
197
|
+
generatedNotice,
|
|
198
|
+
'',
|
|
199
|
+
table(
|
|
200
|
+
['ID', 'Alias', 'Title', 'Category', 'Status', 'Maturity', 'File Path', 'Required Rules', 'Related Research'],
|
|
201
|
+
rows,
|
|
202
|
+
),
|
|
203
|
+
'',
|
|
204
|
+
].join('\n');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function generatePromptsIndex(registry) {
|
|
208
|
+
const prompts = registry.objects
|
|
209
|
+
.filter((object) => object.object_type === 'prompt')
|
|
210
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
211
|
+
|
|
212
|
+
const rows = prompts.map((prompt) => {
|
|
213
|
+
const patternReferences = registry.relationships
|
|
214
|
+
.filter(
|
|
215
|
+
(relationship) =>
|
|
216
|
+
['requires', 'related_to'].includes(relationship.type) &&
|
|
217
|
+
relationship.source === prompt.id &&
|
|
218
|
+
registry.objectsById.get(relationship.target)?.object_type === 'pattern',
|
|
219
|
+
)
|
|
220
|
+
.map((relationship) => `${relationship.type}: ${objectLabel(registry.objectsById.get(relationship.target))}`);
|
|
221
|
+
|
|
222
|
+
const ruleReferences = registry.relationships
|
|
223
|
+
.filter(
|
|
224
|
+
(relationship) =>
|
|
225
|
+
['requires', 'related_to'].includes(relationship.type) &&
|
|
226
|
+
relationship.source === prompt.id &&
|
|
227
|
+
registry.objectsById.get(relationship.target)?.object_type === 'rule',
|
|
228
|
+
)
|
|
229
|
+
.map((relationship) => `${relationship.type}: ${objectLabel(registry.objectsById.get(relationship.target))}`);
|
|
230
|
+
|
|
231
|
+
const checklistReferences = registry.relationships
|
|
232
|
+
.filter(
|
|
233
|
+
(relationship) =>
|
|
234
|
+
['requires', 'related_to'].includes(relationship.type) &&
|
|
235
|
+
relationship.source === prompt.id &&
|
|
236
|
+
registry.objectsById.get(relationship.target)?.object_type === 'checklist',
|
|
237
|
+
)
|
|
238
|
+
.map((relationship) => `${relationship.type}: ${objectLabel(registry.objectsById.get(relationship.target))}`);
|
|
239
|
+
|
|
240
|
+
return [
|
|
241
|
+
prompt.id,
|
|
242
|
+
prompt.alias,
|
|
243
|
+
prompt.title,
|
|
244
|
+
prompt.category,
|
|
245
|
+
prompt.status,
|
|
246
|
+
prompt.maturity,
|
|
247
|
+
prompt.path,
|
|
248
|
+
listOrNone(patternReferences),
|
|
249
|
+
listOrNone(ruleReferences),
|
|
250
|
+
listOrNone(checklistReferences),
|
|
251
|
+
];
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
return [
|
|
255
|
+
'# Generated Prompts Index',
|
|
256
|
+
'',
|
|
257
|
+
generatedNotice,
|
|
258
|
+
'',
|
|
259
|
+
table(
|
|
260
|
+
[
|
|
261
|
+
'ID',
|
|
262
|
+
'Alias',
|
|
263
|
+
'Title',
|
|
264
|
+
'Category',
|
|
265
|
+
'Status',
|
|
266
|
+
'Maturity',
|
|
267
|
+
'File Path',
|
|
268
|
+
'Pattern References',
|
|
269
|
+
'Rule References',
|
|
270
|
+
'Checklist References',
|
|
271
|
+
],
|
|
272
|
+
rows,
|
|
273
|
+
),
|
|
274
|
+
'',
|
|
275
|
+
].join('\n');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function generateChecklistsIndex(registry) {
|
|
279
|
+
const checklists = registry.objects
|
|
280
|
+
.filter((object) => object.object_type === 'checklist')
|
|
281
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
282
|
+
|
|
283
|
+
const rows = checklists.map((checklist) => {
|
|
284
|
+
const coverageReferences = registry.relationships
|
|
285
|
+
.filter(
|
|
286
|
+
(relationship) =>
|
|
287
|
+
relationship.target === checklist.id &&
|
|
288
|
+
['prompt', 'review', 'skill'].includes(registry.objectsById.get(relationship.source)?.object_type),
|
|
289
|
+
)
|
|
290
|
+
.map((relationship) => `${relationship.type}: ${objectLabel(registry.objectsById.get(relationship.source))}`);
|
|
291
|
+
|
|
292
|
+
const relatedRules = registry.relationships
|
|
293
|
+
.filter(
|
|
294
|
+
(relationship) =>
|
|
295
|
+
relationship.source === checklist.id &&
|
|
296
|
+
registry.objectsById.get(relationship.target)?.object_type === 'rule',
|
|
297
|
+
)
|
|
298
|
+
.map((relationship) => `${relationship.type}: ${objectLabel(registry.objectsById.get(relationship.target))}`);
|
|
299
|
+
|
|
300
|
+
return [
|
|
301
|
+
checklist.id,
|
|
302
|
+
checklist.alias,
|
|
303
|
+
checklist.title,
|
|
304
|
+
checklist.category,
|
|
305
|
+
checklist.status,
|
|
306
|
+
checklist.maturity,
|
|
307
|
+
checklist.path,
|
|
308
|
+
listOrNone(relatedRules),
|
|
309
|
+
listOrNone(coverageReferences),
|
|
310
|
+
];
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
return [
|
|
314
|
+
'# Generated Checklists Index',
|
|
315
|
+
'',
|
|
316
|
+
generatedNotice,
|
|
317
|
+
'',
|
|
318
|
+
table(
|
|
319
|
+
['ID', 'Alias', 'Title', 'Category', 'Status', 'Maturity', 'File Path', 'Rule Coverage', 'Used By'],
|
|
320
|
+
rows,
|
|
321
|
+
),
|
|
322
|
+
'',
|
|
323
|
+
].join('\n');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function generateReviewsIndex(registry) {
|
|
327
|
+
const reviews = registry.objects
|
|
328
|
+
.filter((object) => object.object_type === 'review')
|
|
329
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
330
|
+
|
|
331
|
+
const rows = reviews.map((review) => {
|
|
332
|
+
const requiredChecklists = registry.relationships
|
|
333
|
+
.filter(
|
|
334
|
+
(relationship) =>
|
|
335
|
+
relationship.type === 'requires' &&
|
|
336
|
+
relationship.source === review.id &&
|
|
337
|
+
registry.objectsById.get(relationship.target)?.object_type === 'checklist',
|
|
338
|
+
)
|
|
339
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.target)));
|
|
340
|
+
|
|
341
|
+
const validatedObjects = registry.relationships
|
|
342
|
+
.filter((relationship) => relationship.type === 'validates' && relationship.source === review.id)
|
|
343
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.target)));
|
|
344
|
+
|
|
345
|
+
return [
|
|
346
|
+
review.id,
|
|
347
|
+
review.alias,
|
|
348
|
+
review.title,
|
|
349
|
+
review.category,
|
|
350
|
+
review.status,
|
|
351
|
+
review.maturity,
|
|
352
|
+
review.path,
|
|
353
|
+
listOrNone(requiredChecklists),
|
|
354
|
+
listOrNone(validatedObjects),
|
|
355
|
+
];
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
return [
|
|
359
|
+
'# Generated Reviews Index',
|
|
360
|
+
'',
|
|
361
|
+
generatedNotice,
|
|
362
|
+
'',
|
|
363
|
+
table(
|
|
364
|
+
['ID', 'Alias', 'Title', 'Category', 'Status', 'Maturity', 'File Path', 'Required Checklists', 'Validates'],
|
|
365
|
+
rows,
|
|
366
|
+
),
|
|
367
|
+
'',
|
|
368
|
+
].join('\n');
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function generateExamplesIndex(registry) {
|
|
372
|
+
const referenceProjects = registry.objects
|
|
373
|
+
.filter((object) => object.object_type === 'reference_project')
|
|
374
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
375
|
+
|
|
376
|
+
const rows = referenceProjects.map((referenceProject) => {
|
|
377
|
+
const implementedPrompts = registry.relationships
|
|
378
|
+
.filter(
|
|
379
|
+
(relationship) =>
|
|
380
|
+
relationship.type === 'implements' &&
|
|
381
|
+
relationship.source === referenceProject.id &&
|
|
382
|
+
registry.objectsById.get(relationship.target)?.object_type === 'prompt',
|
|
383
|
+
)
|
|
384
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.target)));
|
|
385
|
+
|
|
386
|
+
const validatedObjects = registry.relationships
|
|
387
|
+
.filter((relationship) => relationship.type === 'validates' && relationship.source === referenceProject.id)
|
|
388
|
+
.map((relationship) => objectLabel(registry.objectsById.get(relationship.target)));
|
|
389
|
+
|
|
390
|
+
return [
|
|
391
|
+
referenceProject.id,
|
|
392
|
+
referenceProject.alias,
|
|
393
|
+
referenceProject.title,
|
|
394
|
+
referenceProject.category,
|
|
395
|
+
referenceProject.status,
|
|
396
|
+
referenceProject.maturity,
|
|
397
|
+
referenceProject.path,
|
|
398
|
+
listOrNone(implementedPrompts),
|
|
399
|
+
listOrNone(validatedObjects),
|
|
400
|
+
];
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
return [
|
|
404
|
+
'# Generated Examples Index',
|
|
405
|
+
'',
|
|
406
|
+
generatedNotice,
|
|
407
|
+
'',
|
|
408
|
+
table(
|
|
409
|
+
['ID', 'Alias', 'Title', 'Category', 'Status', 'Maturity', 'File Path', 'Implements', 'Validates'],
|
|
410
|
+
rows,
|
|
411
|
+
),
|
|
412
|
+
'',
|
|
413
|
+
].join('\n');
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function countBy(items, getKey) {
|
|
417
|
+
const counts = new Map();
|
|
418
|
+
for (const item of items) {
|
|
419
|
+
const key = getKey(item);
|
|
420
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
421
|
+
}
|
|
422
|
+
return [...counts.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function generateGraphReport(registry) {
|
|
426
|
+
const relationshipCounts = countBy(registry.relationships, (relationship) => relationship.type);
|
|
427
|
+
const objectCounts = countBy(registry.objects, (object) => object.object_type);
|
|
428
|
+
const knownIds = new Set(registry.objects.map((object) => object.id));
|
|
429
|
+
const connectedIds = new Set();
|
|
430
|
+
const missingTargets = [];
|
|
431
|
+
|
|
432
|
+
for (const relationship of registry.relationships) {
|
|
433
|
+
if (knownIds.has(relationship.source)) {
|
|
434
|
+
connectedIds.add(relationship.source);
|
|
435
|
+
} else {
|
|
436
|
+
missingTargets.push(`source ${relationship.source} in ${relationship.type}`);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (knownIds.has(relationship.target)) {
|
|
440
|
+
connectedIds.add(relationship.target);
|
|
441
|
+
} else {
|
|
442
|
+
missingTargets.push(`target ${relationship.target} in ${relationship.type}`);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const orphanObjects = registry.objects
|
|
447
|
+
.filter((object) => !connectedIds.has(object.id))
|
|
448
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
449
|
+
.map(objectLabel);
|
|
450
|
+
|
|
451
|
+
const connectionCounts = registry.objects
|
|
452
|
+
.map((object) => ({
|
|
453
|
+
object,
|
|
454
|
+
count: registry.relationships.filter(
|
|
455
|
+
(relationship) => relationship.source === object.id || relationship.target === object.id,
|
|
456
|
+
).length,
|
|
457
|
+
}))
|
|
458
|
+
.sort((a, b) => b.count - a.count || a.object.id.localeCompare(b.object.id))
|
|
459
|
+
.slice(0, 10)
|
|
460
|
+
.map(({ object, count }) => `${objectLabel(object)}: ${count}`);
|
|
461
|
+
|
|
462
|
+
const patternsWithoutRequiredRules = registry.objects
|
|
463
|
+
.filter((object) => object.object_type === 'pattern')
|
|
464
|
+
.filter(
|
|
465
|
+
(pattern) =>
|
|
466
|
+
!registry.relationships.some(
|
|
467
|
+
(relationship) =>
|
|
468
|
+
relationship.type === 'requires' &&
|
|
469
|
+
relationship.source === pattern.id &&
|
|
470
|
+
registry.objectsById.get(relationship.target)?.object_type === 'rule',
|
|
471
|
+
),
|
|
472
|
+
)
|
|
473
|
+
.map(objectLabel);
|
|
474
|
+
|
|
475
|
+
const rulesNotUsedByAnyPattern = registry.objects
|
|
476
|
+
.filter((object) => object.object_type === 'rule')
|
|
477
|
+
.filter(
|
|
478
|
+
(rule) =>
|
|
479
|
+
!registry.relationships.some(
|
|
480
|
+
(relationship) =>
|
|
481
|
+
relationship.type === 'requires' &&
|
|
482
|
+
relationship.target === rule.id &&
|
|
483
|
+
registry.objectsById.get(relationship.source)?.object_type === 'pattern',
|
|
484
|
+
),
|
|
485
|
+
)
|
|
486
|
+
.map(objectLabel);
|
|
487
|
+
|
|
488
|
+
const researchWithoutDerivedOrInspiredRules = registry.objects
|
|
489
|
+
.filter((object) => object.object_type === 'research')
|
|
490
|
+
.filter(
|
|
491
|
+
(research) =>
|
|
492
|
+
!registry.relationships.some(
|
|
493
|
+
(relationship) =>
|
|
494
|
+
['derived_from', 'inspired_by'].includes(relationship.type) &&
|
|
495
|
+
relationship.target === research.id &&
|
|
496
|
+
registry.objectsById.get(relationship.source)?.object_type === 'rule',
|
|
497
|
+
),
|
|
498
|
+
)
|
|
499
|
+
.map(objectLabel);
|
|
500
|
+
|
|
501
|
+
const rulesWithoutResearch = registry.objects
|
|
502
|
+
.filter((object) => object.object_type === 'rule')
|
|
503
|
+
.filter(
|
|
504
|
+
(rule) =>
|
|
505
|
+
!registry.relationships.some(
|
|
506
|
+
(relationship) =>
|
|
507
|
+
['derived_from', 'inspired_by'].includes(relationship.type) &&
|
|
508
|
+
relationship.source === rule.id &&
|
|
509
|
+
registry.objectsById.get(relationship.target)?.object_type === 'research',
|
|
510
|
+
),
|
|
511
|
+
)
|
|
512
|
+
.map(objectLabel);
|
|
513
|
+
|
|
514
|
+
const promptsWithoutKnowledgeReferences = registry.objects
|
|
515
|
+
.filter((object) => object.object_type === 'prompt')
|
|
516
|
+
.filter(
|
|
517
|
+
(prompt) =>
|
|
518
|
+
!registry.relationships.some(
|
|
519
|
+
(relationship) =>
|
|
520
|
+
['requires', 'related_to'].includes(relationship.type) &&
|
|
521
|
+
relationship.source === prompt.id &&
|
|
522
|
+
['pattern', 'rule', 'checklist'].includes(registry.objectsById.get(relationship.target)?.object_type),
|
|
523
|
+
),
|
|
524
|
+
)
|
|
525
|
+
.map(objectLabel);
|
|
526
|
+
|
|
527
|
+
const referenceProjectsWithoutValidatesRelationships = registry.objects
|
|
528
|
+
.filter((object) => object.object_type === 'reference_project')
|
|
529
|
+
.filter(
|
|
530
|
+
(referenceProject) =>
|
|
531
|
+
!registry.relationships.some(
|
|
532
|
+
(relationship) => relationship.type === 'validates' && relationship.source === referenceProject.id,
|
|
533
|
+
),
|
|
534
|
+
)
|
|
535
|
+
.map(objectLabel);
|
|
536
|
+
|
|
537
|
+
return [
|
|
538
|
+
'# Generated Graph Report',
|
|
539
|
+
'',
|
|
540
|
+
generatedNotice,
|
|
541
|
+
'',
|
|
542
|
+
'## Object Counts By Type',
|
|
543
|
+
'',
|
|
544
|
+
table(['Object Type', 'Count'], objectCounts.map(([type, count]) => [type, count])),
|
|
545
|
+
'',
|
|
546
|
+
'## Relationship Counts By Type',
|
|
547
|
+
'',
|
|
548
|
+
table(['Relationship Type', 'Count'], relationshipCounts.map(([type, count]) => [type, count])),
|
|
549
|
+
'',
|
|
550
|
+
'## Orphan Objects',
|
|
551
|
+
'',
|
|
552
|
+
linesOrNone(orphanObjects),
|
|
553
|
+
'',
|
|
554
|
+
'## Missing Targets',
|
|
555
|
+
'',
|
|
556
|
+
linesOrNone(missingTargets),
|
|
557
|
+
'',
|
|
558
|
+
'## Research Without Derived Or Inspired Rules',
|
|
559
|
+
'',
|
|
560
|
+
linesOrNone(researchWithoutDerivedOrInspiredRules),
|
|
561
|
+
'',
|
|
562
|
+
'## Rules Without Research',
|
|
563
|
+
'',
|
|
564
|
+
linesOrNone(rulesWithoutResearch),
|
|
565
|
+
'',
|
|
566
|
+
'## Prompts Without Knowledge References',
|
|
567
|
+
'',
|
|
568
|
+
linesOrNone(promptsWithoutKnowledgeReferences),
|
|
569
|
+
'',
|
|
570
|
+
'## Reference Projects Without Validates Relationships',
|
|
571
|
+
'',
|
|
572
|
+
linesOrNone(referenceProjectsWithoutValidatesRelationships),
|
|
573
|
+
'',
|
|
574
|
+
'## Most Connected Objects',
|
|
575
|
+
'',
|
|
576
|
+
linesOrNone(connectionCounts),
|
|
577
|
+
'',
|
|
578
|
+
'## Patterns Without Required Rules',
|
|
579
|
+
'',
|
|
580
|
+
linesOrNone(patternsWithoutRequiredRules),
|
|
581
|
+
'',
|
|
582
|
+
'## Rules Not Used By Any Pattern',
|
|
583
|
+
'',
|
|
584
|
+
linesOrNone(rulesNotUsedByAnyPattern),
|
|
585
|
+
'',
|
|
586
|
+
].join('\n');
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export function generateIndexFiles(root = process.cwd()) {
|
|
590
|
+
const registry = readRegistry(root);
|
|
591
|
+
|
|
592
|
+
return {
|
|
593
|
+
'research/GENERATED_INDEX.md': generateResearchIndex(registry),
|
|
594
|
+
'rules/GENERATED_INDEX.md': generateRulesIndex(registry),
|
|
595
|
+
'patterns/GENERATED_INDEX.md': generatePatternsIndex(registry),
|
|
596
|
+
'prompts/GENERATED_INDEX.md': generatePromptsIndex(registry),
|
|
597
|
+
'checklists/GENERATED_INDEX.md': generateChecklistsIndex(registry),
|
|
598
|
+
'reviews/GENERATED_INDEX.md': generateReviewsIndex(registry),
|
|
599
|
+
'examples/GENERATED_INDEX.md': generateExamplesIndex(registry),
|
|
600
|
+
'graph/GENERATED_GRAPH.md': generateGraphReport(registry),
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export function writeGeneratedIndexes(root = process.cwd()) {
|
|
605
|
+
const files = generateIndexFiles(root);
|
|
606
|
+
|
|
607
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
608
|
+
const fullPath = path.join(root, filePath);
|
|
609
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
610
|
+
fs.writeFileSync(fullPath, content, 'utf8');
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return files;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
617
|
+
const files = writeGeneratedIndexes();
|
|
618
|
+
for (const filePath of Object.keys(files)) {
|
|
619
|
+
console.log(`Generated ${filePath}`);
|
|
620
|
+
}
|
|
621
|
+
}
|