@guanlin4924/devflow-pi 0.1.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 +164 -0
- package/docs/OMP-NATIVE-ARCHITECTURE.md +104 -0
- package/package.json +40 -0
- package/plugins/devflow-core/extensions/devflow-core.ts +1642 -0
- package/plugins/devflow-core/package.json +14 -0
- package/plugins/devflow-core/runtime/hooks/context_sync_gate.py +174 -0
- package/plugins/devflow-core/runtime/hooks/hook_common.py +696 -0
- package/plugins/devflow-core/runtime/hooks/index_gate.py +63 -0
- package/plugins/devflow-core/runtime/hooks/injection_code_specification.py +7 -0
- package/plugins/devflow-core/runtime/hooks/post_tool.py +44 -0
- package/plugins/devflow-core/runtime/hooks/start.py +288 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/SKILL.md +265 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/agents/openai.yaml +4 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +520 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/control_io.rb +42 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/init_state.rb +138 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/init_workflow.rb +121 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +553 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/manage_lessons.rb +219 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/sync_artifacts.rb +168 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/update_triage_route.rb +110 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +565 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +783 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/uat-remediation.yaml +143 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/workflows-README.md +10 -0
- package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +117 -0
- package/plugins/devflow-core/skills/workflow-pipeline/references/pipeline-flow.md +167 -0
- package/plugins/devflow-core/skills/workflow-pipeline/references/slice-safety-guide.md +125 -0
- package/plugins/devflow-core/skills/workflow-project-context/SKILL.md +819 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/agents-md-template.md +25 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-backend-spec-template.md +68 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-frontend-spec-template.md +64 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-navigation-template.md +168 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/context-domain-index-template.md +43 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/context-spec-index-template.md +45 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/execution-contract-template.md +57 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/navigation-index-template.md +40 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/project-initialization-template.md +109 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/rules-index-template.md +80 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/run-manifest-template.json +40 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/directory-structure.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/engine.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/errors.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/locator.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/model.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/repository.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/router.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/scheduler.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/schema.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/service.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/backend/testing.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/api-client.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/case-editor.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/components.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/directory-structure.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/forms.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/routing.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/state.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/spec-templates/frontend/testing.md +46 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/stack-spec-template.md +106 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/state-template.md +77 -0
- package/plugins/devflow-core/skills/workflow-project-context/assets/toolchain-template.md +37 -0
- package/plugins/devflow-core/skills/workflow-project-context/references/navigation-guide.md +262 -0
- package/plugins/devflow-core/skills/workflow-project-context/scripts/validate_initialization.py +545 -0
- package/plugins/devflow-design/agents/contract-auditor.md +18 -0
- package/plugins/devflow-design/extensions/devflow-design.ts +47 -0
- package/plugins/devflow-design/package.json +14 -0
- package/plugins/devflow-design/skills/workflow-api-call-guide/SKILL.md +142 -0
- package/plugins/devflow-design/skills/workflow-api-contract/SKILL.md +150 -0
- package/plugins/devflow-design/skills/workflow-api-supplement/SKILL.md +121 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/SKILL.md +257 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/assets/adr-template.md +57 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/assets/backend-spec-template.md +205 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/affected-module-exploration.md +59 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/backend-conventions.md +30 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/code-explore-guide.md +40 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/project-rule-contract.md +66 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/SKILL.md +91 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/index.md +71 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/accessibility.md +31 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/component-library.md +31 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/design-systems.md +47 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/responsive-grid.md +29 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/stack-guidelines.md +31 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/ux-patterns.md +40 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tokens/project-tokens.md +19 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/SKILL.md +377 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/charts.csv +26 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/colors.csv +97 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/icons.csv +101 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/landing.csv +31 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/products.csv +97 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/styles.csv +68 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/typography.csv +58 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/scripts/core.py +253 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/scripts/search.py +114 -0
- package/plugins/devflow-design/skills/workflow-design-rule-pack/scripts/install.py +67 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/SKILL.md +370 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/admin-system-template.md +57 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/api-service-template.md +42 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/c-end-system-template.md +25 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/output-template.md +139 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/references/bug-rules.md +12 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/references/exception-checklist.md +31 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/references/trace-integrity-guide.md +153 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/references/writing-guide.md +92 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/SKILL.md +223 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/assets/frontend-spec-template.md +204 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/affected-module-exploration.md +58 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/component-patterns.md +42 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-conventions.md +28 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/common-web.md +53 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/next.md +40 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/react.md +41 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/frontend-stack-slots/vue.md +41 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/project-rule-contract.md +95 -0
- package/plugins/devflow-design/skills/workflow-integration-verify/SKILL.md +172 -0
- package/plugins/devflow-design/skills/workflow-ui-spec/SKILL.md +302 -0
- package/plugins/devflow-design/skills/workflow-ui-spec/assets/ui-spec-template.md +244 -0
- package/plugins/devflow-design/skills/workflow-ui-spec/references/affected-module-exploration.md +55 -0
- package/plugins/devflow-implementation/agents/implementation-worker.md +20 -0
- package/plugins/devflow-implementation/package.json +6 -0
- package/plugins/devflow-implementation/skills/workflow-bug-fix/SKILL.md +124 -0
- package/plugins/devflow-implementation/skills/workflow-bug-fix/references/INDEX.md +13 -0
- package/plugins/devflow-implementation/skills/workflow-bug-fix/references/adversarial-review.md +35 -0
- package/plugins/devflow-implementation/skills/workflow-bug-fix/references/first-principles.md +26 -0
- package/plugins/devflow-implementation/skills/workflow-bug-fix/references/lesson-format.md +28 -0
- package/plugins/devflow-implementation/skills/workflow-bug-fix/references/root-cause-ladder.md +51 -0
- package/plugins/devflow-implementation/skills/workflow-bug-fix/references/seam-analysis.md +30 -0
- package/plugins/devflow-implementation/skills/workflow-change-plan/SKILL.md +160 -0
- package/plugins/devflow-implementation/skills/workflow-change-plan/references/code-conventions.md +33 -0
- package/plugins/devflow-implementation/skills/workflow-change-plan/references/ddl-guidelines.md +60 -0
- package/plugins/devflow-implementation/skills/workflow-change-plan/references/output-template.md +217 -0
- package/plugins/devflow-implementation/skills/workflow-change-plan/references/project-rule-contract.md +55 -0
- package/plugins/devflow-implementation/skills/workflow-execute-phase/SKILL.md +271 -0
- package/plugins/devflow-implementation/skills/workflow-execute-phase/references/execute-phase.md +1251 -0
- package/plugins/devflow-implementation/skills/workflow-execute-phase/references/ui-brand.md +160 -0
- package/plugins/devflow-intel/agents/project-scout.md +27 -0
- package/plugins/devflow-intel/extensions/devflow-intel.ts +104 -0
- package/plugins/devflow-intel/package.json +14 -0
- package/plugins/devflow-intel/skills/code-index-query/SKILL.md +37 -0
- package/plugins/devflow-intel/skills/code-index-query/references/query-patterns.md +27 -0
- package/plugins/devflow-intel/skills/workflow-code-index/SKILL.md +68 -0
- package/plugins/devflow-intel/skills/workflow-code-index/references/adapter-contract.md +38 -0
- package/plugins/devflow-intel/skills/workflow-code-index/references/audit-checklist.md +10 -0
- package/plugins/devflow-intel/skills/workflow-code-index/references/confidence-rules.md +43 -0
- package/plugins/devflow-intel/skills/workflow-code-index/references/data-model.md +74 -0
- package/plugins/devflow-intel/skills/workflow-code-index/references/discovery.md +24 -0
- package/plugins/devflow-intel/skills/workflow-code-index/references/query-guide.md +20 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/__init__.py +1 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/base.py +30 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/generic_text.py +287 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/adapters/registry.py +17 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +437 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/__init__.py +1 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/discovery.py +139 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/hashing.py +11 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/scanner.py +115 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/schema.py +123 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/__init__.py +1 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/project_binding_check.py +66 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/relation_check.py +36 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/schema_validate.py +11 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/stale_check.py +42 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/__init__.py +1 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/jsonl_writer.py +25 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/markdown_writer.py +106 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/writers/sqlite_writer.py +143 -0
- package/plugins/devflow-intel/skills/workflow-context-sync/SKILL.md +381 -0
- package/plugins/devflow-intel/skills/workflow-context-sync/agents/openai.yaml +4 -0
- package/plugins/devflow-intel/skills/workflow-context-sync/scripts/context_sync_cursor.py +241 -0
- package/plugins/devflow-intel/skills/workflow-update-navigation/SKILL.md +186 -0
- package/plugins/devflow-intel/skills/workflow-update-navigation/references/incremental-update-guide.md +47 -0
- package/plugins/devflow-quality/agents/code-reviewer.md +18 -0
- package/plugins/devflow-quality/agents/verification-runner.md +21 -0
- package/plugins/devflow-quality/extensions/devflow-quality.ts +59 -0
- package/plugins/devflow-quality/package.json +14 -0
- package/plugins/devflow-quality/skills/code-review/SKILL.md +288 -0
- package/plugins/devflow-quality/skills/code-review/references/cross-layer-checklist.md +70 -0
- package/plugins/devflow-quality/skills/code-review/references/dao-checklist.md +70 -0
- package/plugins/devflow-quality/skills/code-review/references/handler-checklist.md +48 -0
- package/plugins/devflow-quality/skills/code-review/references/repository-checklist.md +44 -0
- package/plugins/devflow-quality/skills/code-review/references/service-checklist.md +57 -0
- package/plugins/devflow-quality/skills/code-review/references/spec-checklist.md +34 -0
- package/plugins/devflow-quality/skills/code-review/references/vo-checklist.md +26 -0
- package/plugins/devflow-quality/skills/workflow-audit-milestone/SKILL.md +31 -0
- package/plugins/devflow-quality/skills/workflow-audit-milestone/references/audit-milestone.md +328 -0
- package/plugins/devflow-quality/skills/workflow-complete-milestone/SKILL.md +132 -0
- package/plugins/devflow-quality/skills/workflow-complete-milestone/assets/milestone-archive.md +123 -0
- package/plugins/devflow-quality/skills/workflow-complete-milestone/references/complete-milestone.md +775 -0
- package/plugins/devflow-quality/skills/workflow-complete-milestone/references/milestone-archive.md +123 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +126 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/api-mainflow-rules.md +27 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/codebase-discovery.md +54 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/intermediate-format.md +244 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/mainflow-selection.md +36 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/project-dsl-contract.md +190 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/ui-mainflow-rules.md +110 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/compile_dsl.py +583 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/discover_codebases.py +199 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/normalize_case_payloads.py +177 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/validate_case_payloads.py +370 -0
- package/plugins/devflow-quality/skills/workflow-verify-work/SKILL.md +106 -0
- package/plugins/devflow-quality/skills/workflow-verify-work/assets/UAT.md +265 -0
- package/plugins/devflow-quality/skills/workflow-verify-work/references/verify-work.md +759 -0
- package/plugins/devflow-requirements/agents/requirements-auditor.md +20 -0
- package/plugins/devflow-requirements/package.json +6 -0
- package/plugins/devflow-requirements/skills/requirement-feasibility-review/SKILL.md +219 -0
- package/plugins/devflow-requirements/skills/requirement-feasibility-review/agents/openai.yaml +4 -0
- package/plugins/devflow-requirements/skills/requirement-feasibility-review/references/review-method.md +257 -0
- package/plugins/devflow-requirements/skills/requirement-feasibility-review/references/review-template.md +80 -0
- package/plugins/devflow-requirements/skills/workflow-demand-clarify/SKILL.md +325 -0
- package/plugins/devflow-requirements/skills/workflow-domain-modeling/SKILL.md +163 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/SKILL.md +748 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/assets/baseline-template.md +281 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/antipatterns.md +69 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/challenge-review-guide.md +158 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/decomposition-guide.md +115 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/project-context-guide.md +119 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/questioning.md +76 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/requirement-review-checklist.md +115 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-triage/SKILL.md +204 -0
- package/plugins/devflow-requirements/skills/workflow-wayfinder/SKILL.md +183 -0
- package/src/cli.ts +76 -0
- package/src/constants.ts +15 -0
- package/src/doctor.ts +66 -0
- package/src/paths.ts +37 -0
- package/src/platform-extension.ts +46 -0
- package/src/project-context.ts +165 -0
- package/src/runtime.ts +167 -0
- package/src/usage-stats.ts +101 -0
- package/templates/commands/start.md +58 -0
- package/templates/omp/AGENTS.md +36 -0
- package/templates/omp/config.yml +112 -0
- package/templates/omp/hook-config.json +18 -0
- package/templates/omp/index-policy.json +57 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Iterable, List, Sequence
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
DEFAULT_EXCLUDES = {
|
|
8
|
+
".git",
|
|
9
|
+
"node_modules",
|
|
10
|
+
"vendor",
|
|
11
|
+
"dist",
|
|
12
|
+
"build",
|
|
13
|
+
"coverage",
|
|
14
|
+
"target",
|
|
15
|
+
".next",
|
|
16
|
+
".nuxt",
|
|
17
|
+
".cache",
|
|
18
|
+
".pytest_cache",
|
|
19
|
+
".mypy_cache",
|
|
20
|
+
".gradle",
|
|
21
|
+
".dart_tool",
|
|
22
|
+
"__pycache__",
|
|
23
|
+
"Pods",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
TEXT_EXTENSIONS = {
|
|
27
|
+
".py",
|
|
28
|
+
".js",
|
|
29
|
+
".jsx",
|
|
30
|
+
".ts",
|
|
31
|
+
".tsx",
|
|
32
|
+
".vue",
|
|
33
|
+
".go",
|
|
34
|
+
".rs",
|
|
35
|
+
".php",
|
|
36
|
+
".java",
|
|
37
|
+
".kt",
|
|
38
|
+
".kts",
|
|
39
|
+
".dart",
|
|
40
|
+
".c",
|
|
41
|
+
".cc",
|
|
42
|
+
".cpp",
|
|
43
|
+
".h",
|
|
44
|
+
".hpp",
|
|
45
|
+
".cs",
|
|
46
|
+
".rb",
|
|
47
|
+
".swift",
|
|
48
|
+
".sql",
|
|
49
|
+
".sh",
|
|
50
|
+
".yaml",
|
|
51
|
+
".yml",
|
|
52
|
+
".json",
|
|
53
|
+
".toml",
|
|
54
|
+
".xml",
|
|
55
|
+
".md",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def scan_files(root: Path, excludes: Iterable[str] = (), max_bytes: int = 1_500_000) -> List[Path]:
|
|
60
|
+
root = root.resolve()
|
|
61
|
+
excluded = DEFAULT_EXCLUDES | set(excludes)
|
|
62
|
+
paths = _scan_with_rg(root, excluded) or _scan_with_walk(root, excluded)
|
|
63
|
+
result: List[Path] = []
|
|
64
|
+
for path in sorted(paths):
|
|
65
|
+
if not path.is_file():
|
|
66
|
+
continue
|
|
67
|
+
if _is_excluded(path, root, excluded):
|
|
68
|
+
continue
|
|
69
|
+
if path.suffix and path.suffix.lower() not in TEXT_EXTENSIONS:
|
|
70
|
+
continue
|
|
71
|
+
try:
|
|
72
|
+
if path.stat().st_size > max_bytes:
|
|
73
|
+
continue
|
|
74
|
+
except OSError:
|
|
75
|
+
continue
|
|
76
|
+
result.append(path)
|
|
77
|
+
return result
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _scan_with_rg(root: Path, excluded: Sequence[str]) -> List[Path]:
|
|
81
|
+
ignore_args = []
|
|
82
|
+
for name in excluded:
|
|
83
|
+
ignore_args.extend(["--glob", f"!**/{name}/**"])
|
|
84
|
+
try:
|
|
85
|
+
proc = subprocess.run(
|
|
86
|
+
["rg", "--files", *ignore_args],
|
|
87
|
+
cwd=str(root),
|
|
88
|
+
text=True,
|
|
89
|
+
stdout=subprocess.PIPE,
|
|
90
|
+
stderr=subprocess.DEVNULL,
|
|
91
|
+
check=False,
|
|
92
|
+
)
|
|
93
|
+
except (OSError, FileNotFoundError):
|
|
94
|
+
return []
|
|
95
|
+
if proc.returncode not in (0, 1):
|
|
96
|
+
return []
|
|
97
|
+
return [root / line.strip() for line in proc.stdout.splitlines() if line.strip()]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _scan_with_walk(root: Path, excluded: Sequence[str]) -> List[Path]:
|
|
101
|
+
paths: List[Path] = []
|
|
102
|
+
for current, dirs, files in os.walk(root):
|
|
103
|
+
dirs[:] = [name for name in dirs if name not in excluded]
|
|
104
|
+
for filename in files:
|
|
105
|
+
paths.append(Path(current) / filename)
|
|
106
|
+
return paths
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _is_excluded(path: Path, root: Path, excluded: Sequence[str]) -> bool:
|
|
110
|
+
try:
|
|
111
|
+
parts = path.resolve().relative_to(root).parts
|
|
112
|
+
except ValueError:
|
|
113
|
+
return True
|
|
114
|
+
return any(part in excluded for part in parts)
|
|
115
|
+
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
import re
|
|
4
|
+
from typing import Dict, Iterable, List
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
RELATION_TYPES = {
|
|
8
|
+
"contains",
|
|
9
|
+
"imports",
|
|
10
|
+
"calls",
|
|
11
|
+
"extends",
|
|
12
|
+
"implements",
|
|
13
|
+
"routes_to",
|
|
14
|
+
"reads",
|
|
15
|
+
"writes",
|
|
16
|
+
"tested_by",
|
|
17
|
+
"config_uses",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
CONFIDENCE = {"exact", "inferred", "heuristic"}
|
|
21
|
+
|
|
22
|
+
SYMBOL_KINDS = {
|
|
23
|
+
"function",
|
|
24
|
+
"method",
|
|
25
|
+
"class",
|
|
26
|
+
"struct",
|
|
27
|
+
"interface",
|
|
28
|
+
"trait",
|
|
29
|
+
"route",
|
|
30
|
+
"file",
|
|
31
|
+
"table",
|
|
32
|
+
"config",
|
|
33
|
+
"test",
|
|
34
|
+
"component",
|
|
35
|
+
"module",
|
|
36
|
+
"variable",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
DIAGNOSTIC_SEVERITY = {"info", "warning", "error"}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def stable_key(value: str) -> str:
|
|
43
|
+
value = value.strip().replace("\\", "/")
|
|
44
|
+
value = re.sub(r"[^A-Za-z0-9_./:$#-]+", ".", value)
|
|
45
|
+
value = re.sub(r"\.+", ".", value).strip(".")
|
|
46
|
+
return value or "unknown"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def short_hash(value: str, length: int = 12) -> str:
|
|
50
|
+
return hashlib.sha256(value.encode("utf-8", errors="ignore")).hexdigest()[:length]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def json_dumps(value) -> str:
|
|
54
|
+
return json.dumps(value or {}, ensure_ascii=False, sort_keys=True)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def validate_file(record: Dict) -> List[str]:
|
|
58
|
+
required = ["id", "codebase", "path", "language", "size_bytes", "content_hash", "indexed_at", "parser"]
|
|
59
|
+
return _missing(record, required)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def validate_symbol(record: Dict) -> List[str]:
|
|
63
|
+
required = [
|
|
64
|
+
"id",
|
|
65
|
+
"codebase",
|
|
66
|
+
"kind",
|
|
67
|
+
"name",
|
|
68
|
+
"path",
|
|
69
|
+
"line_start",
|
|
70
|
+
"line_end",
|
|
71
|
+
"language",
|
|
72
|
+
"content_hash",
|
|
73
|
+
]
|
|
74
|
+
errors = _missing(record, required)
|
|
75
|
+
if record.get("kind") not in SYMBOL_KINDS:
|
|
76
|
+
errors.append(f"invalid symbol kind: {record.get('kind')}")
|
|
77
|
+
if int(record.get("line_start", 0) or 0) < 1:
|
|
78
|
+
errors.append("line_start must be >= 1")
|
|
79
|
+
if int(record.get("line_end", 0) or 0) < int(record.get("line_start", 0) or 0):
|
|
80
|
+
errors.append("line_end must be >= line_start")
|
|
81
|
+
return errors
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def validate_relation(record: Dict) -> List[str]:
|
|
85
|
+
required = ["from_id", "relation_type", "evidence_path", "evidence_line", "confidence", "parser"]
|
|
86
|
+
errors = _missing(record, required)
|
|
87
|
+
if not record.get("to_id") and not record.get("to_external"):
|
|
88
|
+
errors.append("relation requires to_id or to_external")
|
|
89
|
+
if record.get("relation_type") not in RELATION_TYPES:
|
|
90
|
+
errors.append(f"invalid relation_type: {record.get('relation_type')}")
|
|
91
|
+
if record.get("confidence") not in CONFIDENCE:
|
|
92
|
+
errors.append(f"invalid confidence: {record.get('confidence')}")
|
|
93
|
+
if int(record.get("evidence_line", 0) or 0) < 1:
|
|
94
|
+
errors.append("evidence_line must be >= 1")
|
|
95
|
+
return errors
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def validate_diagnostic(record: Dict) -> List[str]:
|
|
99
|
+
required = ["codebase", "severity", "kind", "message"]
|
|
100
|
+
errors = _missing(record, required)
|
|
101
|
+
if record.get("severity") not in DIAGNOSTIC_SEVERITY:
|
|
102
|
+
errors.append(f"invalid diagnostic severity: {record.get('severity')}")
|
|
103
|
+
return errors
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def validate_records(kind: str, records: Iterable[Dict]) -> List[str]:
|
|
107
|
+
validators = {
|
|
108
|
+
"files": validate_file,
|
|
109
|
+
"symbols": validate_symbol,
|
|
110
|
+
"relations": validate_relation,
|
|
111
|
+
"diagnostics": validate_diagnostic,
|
|
112
|
+
}
|
|
113
|
+
validate = validators[kind]
|
|
114
|
+
errors: List[str] = []
|
|
115
|
+
for index, record in enumerate(records, start=1):
|
|
116
|
+
for error in validate(record):
|
|
117
|
+
errors.append(f"{kind}[{index}]: {error}")
|
|
118
|
+
return errors
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _missing(record: Dict, required: List[str]) -> List[str]:
|
|
122
|
+
return [f"missing required field: {field}" for field in required if record.get(field) in (None, "")]
|
|
123
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/project_binding_check.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
PLACEHOLDER_OK = re.compile(r"\{[A-Za-z0-9_:-]+\}")
|
|
6
|
+
|
|
7
|
+
GENERIC_TOKENS = (
|
|
8
|
+
".planning/",
|
|
9
|
+
".context/",
|
|
10
|
+
".skills/",
|
|
11
|
+
"references/",
|
|
12
|
+
"scripts/",
|
|
13
|
+
"core/",
|
|
14
|
+
"adapters/",
|
|
15
|
+
"writers/",
|
|
16
|
+
"validators/",
|
|
17
|
+
"path/to/",
|
|
18
|
+
"name/path/kind",
|
|
19
|
+
"tree-sitter-",
|
|
20
|
+
"lsp-",
|
|
21
|
+
"framework-",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def audit_project_binding(paths):
|
|
26
|
+
findings = []
|
|
27
|
+
path_like = re.compile(r"(?<![`{])(?:[A-Za-z0-9_.-]+/){2,}[A-Za-z0-9_.-]+")
|
|
28
|
+
code_id_like = re.compile(r"\b(?:[a-z]+:)?[A-Za-z0-9_-]+:[A-Za-z0-9_./-]+:[A-Za-z0-9_.:$#-]+")
|
|
29
|
+
for root in paths:
|
|
30
|
+
root = Path(root)
|
|
31
|
+
if not root.exists():
|
|
32
|
+
continue
|
|
33
|
+
for path in root.rglob("*"):
|
|
34
|
+
if not path.is_file() or path.suffix.lower() not in {".md", ".py", ".yaml", ".yml"}:
|
|
35
|
+
continue
|
|
36
|
+
text = path.read_text(encoding="utf-8", errors="ignore")
|
|
37
|
+
for lineno, line in enumerate(text.splitlines(), start=1):
|
|
38
|
+
if line.startswith("#!") or any(token in line for token in GENERIC_TOKENS):
|
|
39
|
+
continue
|
|
40
|
+
stripped = PLACEHOLDER_OK.sub("", line)
|
|
41
|
+
if (
|
|
42
|
+
path_like.search(stripped)
|
|
43
|
+
and ".planning/" not in stripped
|
|
44
|
+
and ".context/" not in stripped
|
|
45
|
+
and ".skills/" not in stripped
|
|
46
|
+
):
|
|
47
|
+
findings.append(
|
|
48
|
+
{
|
|
49
|
+
"severity": "warning",
|
|
50
|
+
"kind": "project_binding",
|
|
51
|
+
"message": "possible project-specific path in generic skill artifact",
|
|
52
|
+
"path": str(path),
|
|
53
|
+
"line": lineno,
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
if code_id_like.search(stripped) and "{codebase}" not in line:
|
|
57
|
+
findings.append(
|
|
58
|
+
{
|
|
59
|
+
"severity": "info",
|
|
60
|
+
"kind": "project_binding",
|
|
61
|
+
"message": "possible concrete code-index id in generic skill artifact",
|
|
62
|
+
"path": str(path),
|
|
63
|
+
"line": lineno,
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
return findings
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
def audit_relations(symbols, relations):
|
|
2
|
+
symbol_ids = {record["id"] for record in symbols}
|
|
3
|
+
findings = []
|
|
4
|
+
for index, relation in enumerate(relations, start=1):
|
|
5
|
+
if relation.get("to_id") and relation["to_id"] not in symbol_ids:
|
|
6
|
+
findings.append(
|
|
7
|
+
{
|
|
8
|
+
"severity": "error",
|
|
9
|
+
"kind": "dangling_relation",
|
|
10
|
+
"message": f"relations[{index}] points to missing symbol {relation['to_id']}",
|
|
11
|
+
"path": relation.get("evidence_path"),
|
|
12
|
+
"line": relation.get("evidence_line"),
|
|
13
|
+
}
|
|
14
|
+
)
|
|
15
|
+
if not relation.get("evidence_path") or not relation.get("evidence_line"):
|
|
16
|
+
findings.append(
|
|
17
|
+
{
|
|
18
|
+
"severity": "error",
|
|
19
|
+
"kind": "missing_evidence",
|
|
20
|
+
"message": f"relations[{index}] has no evidence path/line",
|
|
21
|
+
"path": relation.get("evidence_path"),
|
|
22
|
+
"line": relation.get("evidence_line"),
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
if relation.get("confidence") == "exact" and relation.get("to_external", "").startswith("call:"):
|
|
26
|
+
findings.append(
|
|
27
|
+
{
|
|
28
|
+
"severity": "warning",
|
|
29
|
+
"kind": "confidence_mismatch",
|
|
30
|
+
"message": f"relations[{index}] marks unresolved call as exact",
|
|
31
|
+
"path": relation.get("evidence_path"),
|
|
32
|
+
"line": relation.get("evidence_line"),
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
return findings
|
|
36
|
+
|
package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/schema_validate.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from core.schema import validate_records
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def validate_index(files, symbols, relations, diagnostics):
|
|
5
|
+
errors = []
|
|
6
|
+
errors.extend(validate_records("files", files))
|
|
7
|
+
errors.extend(validate_records("symbols", symbols))
|
|
8
|
+
errors.extend(validate_records("relations", relations))
|
|
9
|
+
errors.extend(validate_records("diagnostics", diagnostics))
|
|
10
|
+
return errors
|
|
11
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from core.hashing import file_sha256
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def audit_stale(root: Path, files):
|
|
7
|
+
findings = []
|
|
8
|
+
for record in files:
|
|
9
|
+
path = root / record["path"]
|
|
10
|
+
if not path.exists():
|
|
11
|
+
findings.append(
|
|
12
|
+
{
|
|
13
|
+
"severity": "error",
|
|
14
|
+
"kind": "stale_index",
|
|
15
|
+
"message": f"indexed file no longer exists: {record['path']}",
|
|
16
|
+
"path": record["path"],
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
continue
|
|
20
|
+
try:
|
|
21
|
+
current = file_sha256(path)
|
|
22
|
+
except OSError as exc:
|
|
23
|
+
findings.append(
|
|
24
|
+
{
|
|
25
|
+
"severity": "warning",
|
|
26
|
+
"kind": "stale_index",
|
|
27
|
+
"message": f"could not hash indexed file: {exc}",
|
|
28
|
+
"path": record["path"],
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
continue
|
|
32
|
+
if current != record["content_hash"]:
|
|
33
|
+
findings.append(
|
|
34
|
+
{
|
|
35
|
+
"severity": "error",
|
|
36
|
+
"kind": "stale_index",
|
|
37
|
+
"message": f"indexed hash differs from source hash: {record['path']}",
|
|
38
|
+
"path": record["path"],
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
return findings
|
|
42
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Iterable
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def write_jsonl(path: Path, records: Iterable[dict]) -> None:
|
|
8
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
9
|
+
with path.open("w", encoding="utf-8") as handle:
|
|
10
|
+
for record in records:
|
|
11
|
+
handle.write(json.dumps(record, ensure_ascii=False, sort_keys=True) + "\n")
|
|
12
|
+
handle.flush()
|
|
13
|
+
os.fsync(handle.fileno())
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def read_jsonl(path: Path):
|
|
17
|
+
if not path.exists():
|
|
18
|
+
return []
|
|
19
|
+
records = []
|
|
20
|
+
with path.open("r", encoding="utf-8") as handle:
|
|
21
|
+
for line in handle:
|
|
22
|
+
line = line.strip()
|
|
23
|
+
if line:
|
|
24
|
+
records.append(json.loads(line))
|
|
25
|
+
return records
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from collections import Counter, defaultdict
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def write_markdown(output: Path, files, symbols, relations, diagnostics) -> None:
|
|
7
|
+
output.mkdir(parents=True, exist_ok=True)
|
|
8
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
9
|
+
_write_index(output / "INDEX.md", now, files, symbols, relations, diagnostics)
|
|
10
|
+
_write_symbols(output / "SYMBOLS.md", now, symbols)
|
|
11
|
+
_write_relations(output / "RELATIONS.md", now, relations)
|
|
12
|
+
_write_entrypoints(output / "ENTRYPOINTS.md", now, symbols)
|
|
13
|
+
_write_dataflow(output / "DATAFLOW.md", now, relations)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def write_audit(output: Path, audit) -> None:
|
|
17
|
+
output.mkdir(parents=True, exist_ok=True)
|
|
18
|
+
lines = ["# Code Index Audit", "", f"- Generated at: {datetime.now(timezone.utc).isoformat()}", ""]
|
|
19
|
+
lines.append("## Summary")
|
|
20
|
+
lines.append("")
|
|
21
|
+
lines.append(f"- Status: {'pass' if not audit else 'fail'}")
|
|
22
|
+
lines.append(f"- Findings: {len(audit)}")
|
|
23
|
+
lines.append("")
|
|
24
|
+
if audit:
|
|
25
|
+
lines.append("## Findings")
|
|
26
|
+
lines.append("")
|
|
27
|
+
for item in audit:
|
|
28
|
+
lines.append(f"- **{item.get('severity', 'warning')}** `{item.get('kind', 'unknown')}`: {item.get('message', '')}")
|
|
29
|
+
if item.get("path"):
|
|
30
|
+
lines.append(f" - Path: `{item.get('path')}`")
|
|
31
|
+
if item.get("line"):
|
|
32
|
+
lines.append(f" - Line: `{item.get('line')}`")
|
|
33
|
+
(output / "AUDIT.md").write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _write_index(path: Path, now: str, files, symbols, relations, diagnostics) -> None:
|
|
37
|
+
codebases = Counter(record["codebase"] for record in files)
|
|
38
|
+
languages = Counter(record["language"] for record in files)
|
|
39
|
+
lines = ["# Code Index", "", f"- Generated at: {now}", "- Index version: 1", ""]
|
|
40
|
+
lines.extend(["## Coverage", "", "| Codebase | Files |", "|----------|-------|"])
|
|
41
|
+
for name, count in sorted(codebases.items()):
|
|
42
|
+
lines.append(f"| `{name}` | {count} |")
|
|
43
|
+
lines.extend(["", "## Languages", "", "| Language | Files |", "|----------|-------|"])
|
|
44
|
+
for name, count in sorted(languages.items()):
|
|
45
|
+
lines.append(f"| `{name}` | {count} |")
|
|
46
|
+
lines.extend(["", "## Counts", ""])
|
|
47
|
+
lines.append(f"- Files: {len(files)}")
|
|
48
|
+
lines.append(f"- Symbols: {len(symbols)}")
|
|
49
|
+
lines.append(f"- Relations: {len(relations)}")
|
|
50
|
+
lines.append(f"- Diagnostics: {len(diagnostics)}")
|
|
51
|
+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _write_symbols(path: Path, now: str, symbols) -> None:
|
|
55
|
+
grouped = defaultdict(Counter)
|
|
56
|
+
for symbol in symbols:
|
|
57
|
+
grouped[symbol["codebase"]][symbol["kind"]] += 1
|
|
58
|
+
lines = ["# Symbols", "", f"- Generated at: {now}", ""]
|
|
59
|
+
for codebase in sorted(grouped):
|
|
60
|
+
lines.extend([f"## `{codebase}`", "", "| Kind | Count |", "|------|-------|"])
|
|
61
|
+
for kind, count in sorted(grouped[codebase].items()):
|
|
62
|
+
lines.append(f"| `{kind}` | {count} |")
|
|
63
|
+
lines.append("")
|
|
64
|
+
lines.extend(["## Sample", "", "| Symbol | Kind | Path | Lines |", "|--------|------|------|-------|"])
|
|
65
|
+
for symbol in symbols[:200]:
|
|
66
|
+
lines.append(
|
|
67
|
+
f"| `{symbol['name']}` | `{symbol['kind']}` | `{symbol['path']}` | {symbol['line_start']}-{symbol['line_end']} |"
|
|
68
|
+
)
|
|
69
|
+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _write_relations(path: Path, now: str, relations) -> None:
|
|
73
|
+
counts = Counter((record["relation_type"], record["confidence"]) for record in relations)
|
|
74
|
+
lines = ["# Relations", "", f"- Generated at: {now}", "", "| Relation | Confidence | Count |", "|----------|------------|-------|"]
|
|
75
|
+
for (relation_type, confidence), count in sorted(counts.items()):
|
|
76
|
+
lines.append(f"| `{relation_type}` | `{confidence}` | {count} |")
|
|
77
|
+
lines.extend(["", "## Sample", "", "| Type | From | To | Evidence | Confidence |", "|------|------|----|----------|------------|"])
|
|
78
|
+
for record in relations[:200]:
|
|
79
|
+
target = record.get("to_id") or record.get("to_external") or ""
|
|
80
|
+
lines.append(
|
|
81
|
+
f"| `{record['relation_type']}` | `{record['from_id']}` | `{target}` | `{record['evidence_path']}:{record['evidence_line']}` | `{record['confidence']}` |"
|
|
82
|
+
)
|
|
83
|
+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _write_entrypoints(path: Path, now: str, symbols) -> None:
|
|
87
|
+
entry_kinds = {"route", "test", "component", "module", "file"}
|
|
88
|
+
lines = ["# Entrypoints", "", f"- Generated at: {now}", "", "| Symbol | Kind | Path | Lines |", "|--------|------|------|-------|"]
|
|
89
|
+
for symbol in symbols:
|
|
90
|
+
if symbol["kind"] in entry_kinds:
|
|
91
|
+
lines.append(
|
|
92
|
+
f"| `{symbol['name']}` | `{symbol['kind']}` | `{symbol['path']}` | {symbol['line_start']}-{symbol['line_end']} |"
|
|
93
|
+
)
|
|
94
|
+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _write_dataflow(path: Path, now: str, relations) -> None:
|
|
98
|
+
lines = ["# Dataflow", "", f"- Generated at: {now}", "", "| Type | Target | Evidence | Confidence |", "|------|--------|----------|------------|"]
|
|
99
|
+
for record in relations:
|
|
100
|
+
if record["relation_type"] in {"reads", "writes", "config_uses"}:
|
|
101
|
+
target = record.get("to_id") or record.get("to_external") or ""
|
|
102
|
+
lines.append(
|
|
103
|
+
f"| `{record['relation_type']}` | `{target}` | `{record['evidence_path']}:{record['evidence_line']}` | `{record['confidence']}` |"
|
|
104
|
+
)
|
|
105
|
+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
106
|
+
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from core.schema import json_dumps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
SCHEMA = """
|
|
9
|
+
CREATE TABLE IF NOT EXISTS code_files (
|
|
10
|
+
id TEXT PRIMARY KEY,
|
|
11
|
+
codebase TEXT NOT NULL,
|
|
12
|
+
path TEXT NOT NULL,
|
|
13
|
+
language TEXT NOT NULL,
|
|
14
|
+
size_bytes INTEGER NOT NULL,
|
|
15
|
+
content_hash TEXT NOT NULL,
|
|
16
|
+
indexed_at TEXT NOT NULL,
|
|
17
|
+
parser TEXT NOT NULL
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS symbols (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
codebase TEXT NOT NULL,
|
|
23
|
+
kind TEXT NOT NULL,
|
|
24
|
+
name TEXT NOT NULL,
|
|
25
|
+
qualified_name TEXT,
|
|
26
|
+
container_id TEXT,
|
|
27
|
+
path TEXT NOT NULL,
|
|
28
|
+
line_start INTEGER NOT NULL,
|
|
29
|
+
line_end INTEGER NOT NULL,
|
|
30
|
+
signature TEXT,
|
|
31
|
+
language TEXT NOT NULL,
|
|
32
|
+
content_hash TEXT NOT NULL,
|
|
33
|
+
visibility TEXT,
|
|
34
|
+
metadata_json TEXT
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
CREATE TABLE IF NOT EXISTS relations (
|
|
38
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
39
|
+
from_id TEXT NOT NULL,
|
|
40
|
+
relation_type TEXT NOT NULL,
|
|
41
|
+
to_id TEXT,
|
|
42
|
+
to_external TEXT,
|
|
43
|
+
evidence_path TEXT NOT NULL,
|
|
44
|
+
evidence_line INTEGER NOT NULL,
|
|
45
|
+
confidence TEXT NOT NULL,
|
|
46
|
+
parser TEXT NOT NULL,
|
|
47
|
+
metadata_json TEXT
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
CREATE TABLE IF NOT EXISTS diagnostics (
|
|
51
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
52
|
+
codebase TEXT NOT NULL,
|
|
53
|
+
path TEXT,
|
|
54
|
+
line INTEGER,
|
|
55
|
+
severity TEXT NOT NULL,
|
|
56
|
+
kind TEXT NOT NULL,
|
|
57
|
+
message TEXT NOT NULL,
|
|
58
|
+
parser TEXT
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(
|
|
62
|
+
id UNINDEXED,
|
|
63
|
+
codebase UNINDEXED,
|
|
64
|
+
name,
|
|
65
|
+
qualified_name,
|
|
66
|
+
signature,
|
|
67
|
+
path,
|
|
68
|
+
metadata_json
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_codebase ON symbols(codebase);
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_path ON symbols(path);
|
|
73
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name);
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_relations_from ON relations(from_id);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_relations_to ON relations(to_id);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_relations_type ON relations(relation_type);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_relations_external ON relations(to_external);
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def write_sqlite(path: Path, files, symbols, relations, diagnostics) -> None:
|
|
82
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
83
|
+
if path.exists():
|
|
84
|
+
path.unlink()
|
|
85
|
+
conn = sqlite3.connect(str(path))
|
|
86
|
+
try:
|
|
87
|
+
conn.executescript(SCHEMA)
|
|
88
|
+
conn.executemany(
|
|
89
|
+
"""
|
|
90
|
+
INSERT INTO code_files(id, codebase, path, language, size_bytes, content_hash, indexed_at, parser)
|
|
91
|
+
VALUES(:id, :codebase, :path, :language, :size_bytes, :content_hash, :indexed_at, :parser)
|
|
92
|
+
""",
|
|
93
|
+
files,
|
|
94
|
+
)
|
|
95
|
+
conn.executemany(
|
|
96
|
+
"""
|
|
97
|
+
INSERT INTO symbols(id, codebase, kind, name, qualified_name, container_id, path, line_start, line_end,
|
|
98
|
+
signature, language, content_hash, visibility, metadata_json)
|
|
99
|
+
VALUES(:id, :codebase, :kind, :name, :qualified_name, :container_id, :path, :line_start, :line_end,
|
|
100
|
+
:signature, :language, :content_hash, :visibility, :metadata_json)
|
|
101
|
+
""",
|
|
102
|
+
[_symbol_row(record) for record in symbols],
|
|
103
|
+
)
|
|
104
|
+
conn.executemany(
|
|
105
|
+
"""
|
|
106
|
+
INSERT INTO relations(from_id, relation_type, to_id, to_external, evidence_path, evidence_line,
|
|
107
|
+
confidence, parser, metadata_json)
|
|
108
|
+
VALUES(:from_id, :relation_type, :to_id, :to_external, :evidence_path, :evidence_line,
|
|
109
|
+
:confidence, :parser, :metadata_json)
|
|
110
|
+
""",
|
|
111
|
+
[_relation_row(record) for record in relations],
|
|
112
|
+
)
|
|
113
|
+
conn.executemany(
|
|
114
|
+
"""
|
|
115
|
+
INSERT INTO diagnostics(codebase, path, line, severity, kind, message, parser)
|
|
116
|
+
VALUES(:codebase, :path, :line, :severity, :kind, :message, :parser)
|
|
117
|
+
""",
|
|
118
|
+
diagnostics,
|
|
119
|
+
)
|
|
120
|
+
conn.executemany(
|
|
121
|
+
"""
|
|
122
|
+
INSERT INTO symbols_fts(id, codebase, name, qualified_name, signature, path, metadata_json)
|
|
123
|
+
VALUES(:id, :codebase, :name, :qualified_name, :signature, :path, :metadata_json)
|
|
124
|
+
""",
|
|
125
|
+
[_symbol_row(record) for record in symbols],
|
|
126
|
+
)
|
|
127
|
+
conn.commit()
|
|
128
|
+
finally:
|
|
129
|
+
conn.close()
|
|
130
|
+
with path.open("rb") as handle:
|
|
131
|
+
os.fsync(handle.fileno())
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _symbol_row(record):
|
|
135
|
+
row = dict(record)
|
|
136
|
+
row["metadata_json"] = json_dumps(row.pop("metadata", {}))
|
|
137
|
+
return row
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _relation_row(record):
|
|
141
|
+
row = dict(record)
|
|
142
|
+
row["metadata_json"] = json_dumps(row.pop("metadata", {}))
|
|
143
|
+
return row
|