@ahmed-g-gad/apothem 0.1.1
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/CHANGELOG.md +60 -0
- package/LICENSE +21 -0
- package/LICENSES/MIT.txt +18 -0
- package/LICENSES/PSF-2.0.txt +47 -0
- package/README.md +549 -0
- package/bin/README.md +37 -0
- package/bin/apothem.mjs +78 -0
- package/package.json +75 -0
- package/pyproject.toml +347 -0
- package/src/apothem/README.md +52 -0
- package/src/apothem/__init__.py +66 -0
- package/src/apothem/__main__.py +28 -0
- package/src/apothem/_vendor/.keep +0 -0
- package/src/apothem/_vendor/__init__.py +25 -0
- package/src/apothem/_vendor/attr/__init__.py +104 -0
- package/src/apothem/_vendor/attr/__init__.pyi +389 -0
- package/src/apothem/_vendor/attr/_cmp.py +160 -0
- package/src/apothem/_vendor/attr/_cmp.pyi +13 -0
- package/src/apothem/_vendor/attr/_compat.py +99 -0
- package/src/apothem/_vendor/attr/_config.py +31 -0
- package/src/apothem/_vendor/attr/_funcs.py +497 -0
- package/src/apothem/_vendor/attr/_make.py +3406 -0
- package/src/apothem/_vendor/attr/_next_gen.py +674 -0
- package/src/apothem/_vendor/attr/_typing_compat.pyi +15 -0
- package/src/apothem/_vendor/attr/_version_info.py +89 -0
- package/src/apothem/_vendor/attr/_version_info.pyi +9 -0
- package/src/apothem/_vendor/attr/converters.py +162 -0
- package/src/apothem/_vendor/attr/converters.pyi +19 -0
- package/src/apothem/_vendor/attr/exceptions.py +95 -0
- package/src/apothem/_vendor/attr/exceptions.pyi +17 -0
- package/src/apothem/_vendor/attr/filters.py +72 -0
- package/src/apothem/_vendor/attr/filters.pyi +6 -0
- package/src/apothem/_vendor/attr/py.typed +0 -0
- package/src/apothem/_vendor/attr/setters.py +79 -0
- package/src/apothem/_vendor/attr/setters.pyi +20 -0
- package/src/apothem/_vendor/attr/validators.py +750 -0
- package/src/apothem/_vendor/attr/validators.pyi +140 -0
- package/src/apothem/_vendor/attr.LICENSE +21 -0
- package/src/apothem/_vendor/attrs/__init__.py +72 -0
- package/src/apothem/_vendor/attrs/__init__.pyi +314 -0
- package/src/apothem/_vendor/attrs/converters.py +3 -0
- package/src/apothem/_vendor/attrs/exceptions.py +3 -0
- package/src/apothem/_vendor/attrs/filters.py +3 -0
- package/src/apothem/_vendor/attrs/py.typed +0 -0
- package/src/apothem/_vendor/attrs/setters.py +3 -0
- package/src/apothem/_vendor/attrs/validators.py +3 -0
- package/src/apothem/_vendor/attrs.LICENSE +21 -0
- package/src/apothem/_vendor/jsonschema/__init__.py +120 -0
- package/src/apothem/_vendor/jsonschema/__main__.py +6 -0
- package/src/apothem/_vendor/jsonschema/_format.py +546 -0
- package/src/apothem/_vendor/jsonschema/_keywords.py +449 -0
- package/src/apothem/_vendor/jsonschema/_legacy_keywords.py +449 -0
- package/src/apothem/_vendor/jsonschema/_types.py +204 -0
- package/src/apothem/_vendor/jsonschema/_typing.py +29 -0
- package/src/apothem/_vendor/jsonschema/_utils.py +355 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/__init__.py +5 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/const_vs_enum.py +30 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/contains.py +28 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/import_benchmark.py +31 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/issue232/issue.json +2653 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/issue232.py +25 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/json_schema_test_suite.py +12 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/nested_schemas.py +56 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/subcomponents.py +42 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/unused_registry.py +35 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/useless_applicator_schemas.py +106 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/useless_keywords.py +32 -0
- package/src/apothem/_vendor/jsonschema/benchmarks/validator_creation.py +14 -0
- package/src/apothem/_vendor/jsonschema/cli.py +292 -0
- package/src/apothem/_vendor/jsonschema/exceptions.py +490 -0
- package/src/apothem/_vendor/jsonschema/protocols.py +230 -0
- package/src/apothem/_vendor/jsonschema/validators.py +1410 -0
- package/src/apothem/_vendor/jsonschema.LICENSE +19 -0
- package/src/apothem/_vendor/jsonschema_specifications/__init__.py +12 -0
- package/src/apothem/_vendor/jsonschema_specifications/_core.py +38 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/metaschema.json +42 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/applicator +56 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/content +17 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/core +57 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/format +14 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data +37 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/validation +98 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/metaschema.json +58 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/applicator +48 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/content +17 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/core +51 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation +14 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion +14 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data +37 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated +15 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/validation +98 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft3/metaschema.json +172 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft4/metaschema.json +149 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft6/metaschema.json +153 -0
- package/src/apothem/_vendor/jsonschema_specifications/schemas/draft7/metaschema.json +166 -0
- package/src/apothem/_vendor/jsonschema_specifications.LICENSE +19 -0
- package/src/apothem/_vendor/referencing/__init__.py +7 -0
- package/src/apothem/_vendor/referencing/_attrs.py +31 -0
- package/src/apothem/_vendor/referencing/_attrs.pyi +21 -0
- package/src/apothem/_vendor/referencing/_core.py +739 -0
- package/src/apothem/_vendor/referencing/exceptions.py +165 -0
- package/src/apothem/_vendor/referencing/jsonschema.py +642 -0
- package/src/apothem/_vendor/referencing/py.typed +0 -0
- package/src/apothem/_vendor/referencing/retrieval.py +94 -0
- package/src/apothem/_vendor/referencing/typing.py +61 -0
- package/src/apothem/_vendor/referencing.LICENSE +19 -0
- package/src/apothem/_vendor/rpds/__init__.py +251 -0
- package/src/apothem/_vendor/typing_extensions.LICENSE +279 -0
- package/src/apothem/_vendor/typing_extensions.py +4317 -0
- package/src/apothem/_vendor/vendor.txt +22 -0
- package/src/apothem/_vendor/yaml/__init__.py +389 -0
- package/src/apothem/_vendor/yaml/composer.py +138 -0
- package/src/apothem/_vendor/yaml/constructor.py +748 -0
- package/src/apothem/_vendor/yaml/cyaml.py +100 -0
- package/src/apothem/_vendor/yaml/dumper.py +61 -0
- package/src/apothem/_vendor/yaml/emitter.py +1137 -0
- package/src/apothem/_vendor/yaml/error.py +74 -0
- package/src/apothem/_vendor/yaml/events.py +85 -0
- package/src/apothem/_vendor/yaml/loader.py +63 -0
- package/src/apothem/_vendor/yaml/nodes.py +48 -0
- package/src/apothem/_vendor/yaml/parser.py +588 -0
- package/src/apothem/_vendor/yaml/reader.py +185 -0
- package/src/apothem/_vendor/yaml/representer.py +388 -0
- package/src/apothem/_vendor/yaml/resolver.py +226 -0
- package/src/apothem/_vendor/yaml/scanner.py +1435 -0
- package/src/apothem/_vendor/yaml/serializer.py +110 -0
- package/src/apothem/_vendor/yaml/tokens.py +103 -0
- package/src/apothem/_vendor/yaml.LICENSE +20 -0
- package/src/apothem/agents/README.md +60 -0
- package/src/apothem/agents/codebase-explorer.md +91 -0
- package/src/apothem/agents/convention-auditor.md +93 -0
- package/src/apothem/agents/dependency-auditor.md +97 -0
- package/src/apothem/agents/fact-checker.md +84 -0
- package/src/apothem/agents/mcp-builder.md +86 -0
- package/src/apothem/agents/memory-auditor.md +93 -0
- package/src/apothem/agents/prompt-evaluator.md +87 -0
- package/src/apothem/agents/quality-gate.md +103 -0
- package/src/apothem/agents/refactor-surgeon.md +74 -0
- package/src/apothem/agents/research-scout.md +73 -0
- package/src/apothem/agents/security-scanner.md +83 -0
- package/src/apothem/agents/test-runner.md +84 -0
- package/src/apothem/audit/README.md +73 -0
- package/src/apothem/audit/_scan_lib.py +182 -0
- package/src/apothem/audit/analyze_graph.py +260 -0
- package/src/apothem/audit/build_capability_graph.py +607 -0
- package/src/apothem/audit/build_inventory.py +657 -0
- package/src/apothem/audit/build_plans_provenance.py +997 -0
- package/src/apothem/audit/check_links.py +389 -0
- package/src/apothem/audit/classify_artifacts.py +381 -0
- package/src/apothem/audit/deprecated-tokens.txt +10 -0
- package/src/apothem/audit/execute_plans_migration.py +491 -0
- package/src/apothem/audit/known-projects.txt +15 -0
- package/src/apothem/audit/render_capability_index.py +467 -0
- package/src/apothem/audit/render_inventory.py +405 -0
- package/src/apothem/audit/scan_ai_surfaces.py +1125 -0
- package/src/apothem/audit/scan_ai_surfaces_coarse.py +261 -0
- package/src/apothem/audit/scan_drift_features.py +143 -0
- package/src/apothem/audit/scan_frontmatter.py +293 -0
- package/src/apothem/audit/scan_header_coverage.py +1134 -0
- package/src/apothem/audit/scan_plan_leakage.py +540 -0
- package/src/apothem/audit/scan_plans_discipline.py +188 -0
- package/src/apothem/audit/scan_secrets_pii.py +245 -0
- package/src/apothem/audit/scan_stale_tokens.py +296 -0
- package/src/apothem/audit/synthesize_drift.py +205 -0
- package/src/apothem/benchmarks/README.md +33 -0
- package/src/apothem/benchmarks/__init__.py +3 -0
- package/src/apothem/benchmarks/bench_agents.py +63 -0
- package/src/apothem/benchmarks/bench_hooks.py +93 -0
- package/src/apothem/benchmarks/bench_install.py +58 -0
- package/src/apothem/benchmarks/bench_tests.py +93 -0
- package/src/apothem/benchmarks/bench_validate_ecosystem.py +84 -0
- package/src/apothem/cli/README.md +33 -0
- package/src/apothem/cli/__init__.py +229 -0
- package/src/apothem/cli/_cmd_completion.py +88 -0
- package/src/apothem/cli/_cmd_diff.py +181 -0
- package/src/apothem/cli/_cmd_doctor.py +143 -0
- package/src/apothem/cli/_cmd_harnesses.py +167 -0
- package/src/apothem/cli/_cmd_install.py +327 -0
- package/src/apothem/cli/_cmd_migrate_workspace.py +143 -0
- package/src/apothem/cli/_cmd_profile.py +341 -0
- package/src/apothem/cli/_cmd_status.py +180 -0
- package/src/apothem/cli/_cmd_uninstall.py +215 -0
- package/src/apothem/cli/_cmd_update.py +397 -0
- package/src/apothem/cli/_cmd_verify.py +194 -0
- package/src/apothem/cli/_common_flags.py +90 -0
- package/src/apothem/cli/_epilogs.py +296 -0
- package/src/apothem/cli/_helpers.py +857 -0
- package/src/apothem/cli/_json_formatter.py +21 -0
- package/src/apothem/cli/_materialize.py +376 -0
- package/src/apothem/cli/completions/apothem.bash +30 -0
- package/src/apothem/cli/completions/apothem.fish +19 -0
- package/src/apothem/cli/completions/apothem.ps1 +27 -0
- package/src/apothem/cli/completions/apothem.zsh +42 -0
- package/src/apothem/cli/reference_export.py +126 -0
- package/src/apothem/commands/README.md +125 -0
- package/src/apothem/commands/a11y-audit.md +203 -0
- package/src/apothem/commands/architecture-review.md +194 -0
- package/src/apothem/commands/audit.md +165 -0
- package/src/apothem/commands/code-audit.md +218 -0
- package/src/apothem/commands/code-review.md +193 -0
- package/src/apothem/commands/dependency-audit.md +209 -0
- package/src/apothem/commands/docs-review.md +199 -0
- package/src/apothem/commands/elevate.md +285 -0
- package/src/apothem/commands/eval.md +149 -0
- package/src/apothem/commands/fortress.md +172 -0
- package/src/apothem/commands/freshify.md +168 -0
- package/src/apothem/commands/github-deploy-fresh.md +178 -0
- package/src/apothem/commands/github-deploy-next.md +167 -0
- package/src/apothem/commands/perf-audit.md +198 -0
- package/src/apothem/commands/plan-amend.md +104 -0
- package/src/apothem/commands/plan-audit.md +127 -0
- package/src/apothem/commands/plan-design.md +257 -0
- package/src/apothem/commands/plan-execute.md +495 -0
- package/src/apothem/commands/plan-generate.md +351 -0
- package/src/apothem/commands/plan-review.md +555 -0
- package/src/apothem/commands/plan-spec.md +359 -0
- package/src/apothem/commands/plan-status.md +222 -0
- package/src/apothem/commands/plan.md +173 -0
- package/src/apothem/commands/projectify.md +142 -0
- package/src/apothem/commands/release-readiness.md +142 -0
- package/src/apothem/commands/research-analysis.md +241 -0
- package/src/apothem/commands/research-design.md +231 -0
- package/src/apothem/commands/research-disseminate.md +225 -0
- package/src/apothem/commands/research-experiment.md +232 -0
- package/src/apothem/commands/research-ideate.md +213 -0
- package/src/apothem/commands/research-paper.md +252 -0
- package/src/apothem/commands/research-proposal.md +220 -0
- package/src/apothem/commands/research-publish.md +255 -0
- package/src/apothem/commands/research-review.md +251 -0
- package/src/apothem/commands/research-sources.md +266 -0
- package/src/apothem/commands/research-spec.md +255 -0
- package/src/apothem/commands/research-synthesis.md +233 -0
- package/src/apothem/commands/research-theory.md +218 -0
- package/src/apothem/commands/research.md +181 -0
- package/src/apothem/commands/security-audit.md +196 -0
- package/src/apothem/commands/supply-chain-audit.md +192 -0
- package/src/apothem/commands/test-suite.md +146 -0
- package/src/apothem/commands/threat-model-audit.md +199 -0
- package/src/apothem/commands/ux-review.md +202 -0
- package/src/apothem/commands/workflow.md +162 -0
- package/src/apothem/conformity/README.md +173 -0
- package/src/apothem/conformity/__init__.py +1 -0
- package/src/apothem/conformity/_grep_base.py +93 -0
- package/src/apothem/conformity/agent_capability_grep.py +306 -0
- package/src/apothem/conformity/agents_md_coverage_grep.py +382 -0
- package/src/apothem/conformity/agnosticism_grep.py +311 -0
- package/src/apothem/conformity/always_on_budget_grep.py +318 -0
- package/src/apothem/conformity/bare_except_grep.py +115 -0
- package/src/apothem/conformity/binding_reciprocity_grep.py +151 -0
- package/src/apothem/conformity/brand_mark_grep.py +272 -0
- package/src/apothem/conformity/commented_out_code_grep.py +176 -0
- package/src/apothem/conformity/completion_claim_grep.py +169 -0
- package/src/apothem/conformity/conventional_commit_grep.py +319 -0
- package/src/apothem/conformity/copilot_instructions_presence_grep.py +324 -0
- package/src/apothem/conformity/cross_platform_matrix_grep.py +297 -0
- package/src/apothem/conformity/determinism_grep.py +306 -0
- package/src/apothem/conformity/diagram_staleness_grep.py +154 -0
- package/src/apothem/conformity/dynamism_grep.py +284 -0
- package/src/apothem/conformity/editorconfig_presence_grep.py +281 -0
- package/src/apothem/conformity/file_header_grep.py +502 -0
- package/src/apothem/conformity/freshness_token_grep.py +233 -0
- package/src/apothem/conformity/frontmatter_grep.py +274 -0
- package/src/apothem/conformity/frontmatter_value_grep.py +386 -0
- package/src/apothem/conformity/gate.py +1386 -0
- package/src/apothem/conformity/gitattributes_presence_grep.py +238 -0
- package/src/apothem/conformity/harden_runner_grep.py +320 -0
- package/src/apothem/conformity/hedging_grep.py +129 -0
- package/src/apothem/conformity/license_author_consistency_grep.py +204 -0
- package/src/apothem/conformity/link_check.py +327 -0
- package/src/apothem/conformity/magic_number_grep.py +182 -0
- package/src/apothem/conformity/multi_surface_coherence_grep.py +620 -0
- package/src/apothem/conformity/naming_grep.py +224 -0
- package/src/apothem/conformity/no_global_plans_grep.py +339 -0
- package/src/apothem/conformity/no_toplevel_docs_grep.py +120 -0
- package/src/apothem/conformity/oidc_trusted_publishing_grep.py +291 -0
- package/src/apothem/conformity/option_annotation_grep.py +352 -0
- package/src/apothem/conformity/orphan_output_grep.py +206 -0
- package/src/apothem/conformity/permissions_minimum_scope_grep.py +299 -0
- package/src/apothem/conformity/plain_language_grep.py +559 -0
- package/src/apothem/conformity/plan_next_step_consistency_grep.py +450 -0
- package/src/apothem/conformity/plan_suite_structure_grep.py +534 -0
- package/src/apothem/conformity/plans_discipline_language_grep.py +245 -0
- package/src/apothem/conformity/production_ready_pr_grep.py +200 -0
- package/src/apothem/conformity/recommend_next_step_grep.py +250 -0
- package/src/apothem/conformity/redundancy_grep.py +401 -0
- package/src/apothem/conformity/reference_token_grep.py +230 -0
- package/src/apothem/conformity/registry_capability_consistency_grep.py +368 -0
- package/src/apothem/conformity/secret_leak_grep.py +193 -0
- package/src/apothem/conformity/semver_stability_grep.py +358 -0
- package/src/apothem/conformity/smoke_install_grep.py +194 -0
- package/src/apothem/conformity/static_version_grep.py +284 -0
- package/src/apothem/conformity/token_efficiency_grep.py +185 -0
- package/src/apothem/conformity/unpinned_action_grep.py +115 -0
- package/src/apothem/conformity/user_confirm_grep.py +74 -0
- package/src/apothem/conformity/workflow_concurrency_grep.py +283 -0
- package/src/apothem/harnesses/README.md +63 -0
- package/src/apothem/harnesses/__init__.py +16 -0
- package/src/apothem/harnesses/_shared/README.md +36 -0
- package/src/apothem/harnesses/_shared/__init__.py +12 -0
- package/src/apothem/harnesses/_shared/install_driver.py +281 -0
- package/src/apothem/harnesses/_shared/install_driver_apply.py +612 -0
- package/src/apothem/harnesses/_shared/install_driver_backup.py +535 -0
- package/src/apothem/harnesses/_shared/install_driver_converters.py +310 -0
- package/src/apothem/harnesses/_shared/install_driver_lifecycle.py +495 -0
- package/src/apothem/harnesses/_shared/install_driver_materialize.py +675 -0
- package/src/apothem/harnesses/_shared/install_driver_merge.py +656 -0
- package/src/apothem/harnesses/_shared/install_driver_pathsafety.py +137 -0
- package/src/apothem/harnesses/_shared/install_driver_planvalidation.py +240 -0
- package/src/apothem/harnesses/_shared/install_driver_removal.py +366 -0
- package/src/apothem/harnesses/_shared/install_driver_treeops.py +248 -0
- package/src/apothem/harnesses/_shared/install_driver_types.py +330 -0
- package/src/apothem/harnesses/_shared/wrapper_factories.py +448 -0
- package/src/apothem/harnesses/antigravity/STANDARD-CONVENTION-PIN.md +91 -0
- package/src/apothem/harnesses/antigravity/__init__.py +70 -0
- package/src/apothem/harnesses/antigravity/capabilities.yml +40 -0
- package/src/apothem/harnesses/antigravity/install.py +63 -0
- package/src/apothem/harnesses/antigravity/templates/GEMINI.md +40 -0
- package/src/apothem/harnesses/antigravity/templates/plugin.json +5 -0
- package/src/apothem/harnesses/antigravity/uninstall.py +22 -0
- package/src/apothem/harnesses/antigravity/update.py +10 -0
- package/src/apothem/harnesses/antigravity/verify.py +11 -0
- package/src/apothem/harnesses/claude_code/STANDARD-CONVENTION-PIN.md +65 -0
- package/src/apothem/harnesses/claude_code/__init__.py +107 -0
- package/src/apothem/harnesses/claude_code/capabilities.yml +42 -0
- package/src/apothem/harnesses/claude_code/install.py +147 -0
- package/src/apothem/harnesses/claude_code/templates/settings.json +351 -0
- package/src/apothem/harnesses/claude_code/uninstall.py +23 -0
- package/src/apothem/harnesses/claude_code/update.py +10 -0
- package/src/apothem/harnesses/claude_code/verify.py +11 -0
- package/src/apothem/harnesses/codebuddy/STANDARD-CONVENTION-PIN.md +74 -0
- package/src/apothem/harnesses/codebuddy/__init__.py +49 -0
- package/src/apothem/harnesses/codebuddy/capabilities.yml +34 -0
- package/src/apothem/harnesses/codebuddy/install.py +40 -0
- package/src/apothem/harnesses/codebuddy/templates/apothem-rules.md +37 -0
- package/src/apothem/harnesses/codebuddy/uninstall.py +25 -0
- package/src/apothem/harnesses/codebuddy/update.py +10 -0
- package/src/apothem/harnesses/codebuddy/verify.py +11 -0
- package/src/apothem/harnesses/codex/STANDARD-CONVENTION-PIN.md +79 -0
- package/src/apothem/harnesses/codex/__init__.py +72 -0
- package/src/apothem/harnesses/codex/capabilities.yml +40 -0
- package/src/apothem/harnesses/codex/install.py +69 -0
- package/src/apothem/harnesses/codex/templates/AGENTS.md +40 -0
- package/src/apothem/harnesses/codex/templates/hooks.json +127 -0
- package/src/apothem/harnesses/codex/uninstall.py +23 -0
- package/src/apothem/harnesses/codex/update.py +10 -0
- package/src/apothem/harnesses/codex/verify.py +11 -0
- package/src/apothem/harnesses/cursor/STANDARD-CONVENTION-PIN.md +79 -0
- package/src/apothem/harnesses/cursor/__init__.py +48 -0
- package/src/apothem/harnesses/cursor/capabilities.yml +42 -0
- package/src/apothem/harnesses/cursor/install.py +38 -0
- package/src/apothem/harnesses/cursor/templates/apothem-rules.mdc +40 -0
- package/src/apothem/harnesses/cursor/uninstall.py +25 -0
- package/src/apothem/harnesses/cursor/update.py +10 -0
- package/src/apothem/harnesses/cursor/verify.py +11 -0
- package/src/apothem/harnesses/gemini_cli/STANDARD-CONVENTION-PIN.md +102 -0
- package/src/apothem/harnesses/gemini_cli/__init__.py +52 -0
- package/src/apothem/harnesses/gemini_cli/capabilities.yml +43 -0
- package/src/apothem/harnesses/gemini_cli/install.py +43 -0
- package/src/apothem/harnesses/gemini_cli/templates/GEMINI.md +38 -0
- package/src/apothem/harnesses/gemini_cli/uninstall.py +25 -0
- package/src/apothem/harnesses/gemini_cli/update.py +10 -0
- package/src/apothem/harnesses/gemini_cli/verify.py +11 -0
- package/src/apothem/harnesses/github_copilot/STANDARD-CONVENTION-PIN.md +84 -0
- package/src/apothem/harnesses/github_copilot/__init__.py +47 -0
- package/src/apothem/harnesses/github_copilot/capabilities.yml +42 -0
- package/src/apothem/harnesses/github_copilot/install.py +40 -0
- package/src/apothem/harnesses/github_copilot/templates/copilot-instructions.md +33 -0
- package/src/apothem/harnesses/github_copilot/uninstall.py +25 -0
- package/src/apothem/harnesses/github_copilot/update.py +10 -0
- package/src/apothem/harnesses/github_copilot/verify.py +11 -0
- package/src/apothem/harnesses/glm/STANDARD-CONVENTION-PIN.md +77 -0
- package/src/apothem/harnesses/glm/__init__.py +56 -0
- package/src/apothem/harnesses/glm/capabilities.yml +33 -0
- package/src/apothem/harnesses/glm/install.py +45 -0
- package/src/apothem/harnesses/glm/templates/glm.toml +58 -0
- package/src/apothem/harnesses/glm/uninstall.py +25 -0
- package/src/apothem/harnesses/glm/update.py +10 -0
- package/src/apothem/harnesses/glm/verify.py +11 -0
- package/src/apothem/harnesses/hermes/STANDARD-CONVENTION-PIN.md +57 -0
- package/src/apothem/harnesses/hermes/__init__.py +33 -0
- package/src/apothem/harnesses/hermes/capabilities.yml +36 -0
- package/src/apothem/harnesses/hermes/install.py +17 -0
- package/src/apothem/harnesses/hermes/materializer.py +35 -0
- package/src/apothem/harnesses/hermes/uninstall.py +33 -0
- package/src/apothem/harnesses/hermes/update.py +10 -0
- package/src/apothem/harnesses/hermes/verify.py +11 -0
- package/src/apothem/harnesses/kimi_code/STANDARD-CONVENTION-PIN.md +128 -0
- package/src/apothem/harnesses/kimi_code/__init__.py +59 -0
- package/src/apothem/harnesses/kimi_code/capabilities.yml +40 -0
- package/src/apothem/harnesses/kimi_code/install.py +42 -0
- package/src/apothem/harnesses/kimi_code/templates/AGENTS.md +43 -0
- package/src/apothem/harnesses/kimi_code/uninstall.py +27 -0
- package/src/apothem/harnesses/kimi_code/update.py +10 -0
- package/src/apothem/harnesses/kimi_code/verify.py +11 -0
- package/src/apothem/harnesses/kiro/STANDARD-CONVENTION-PIN.md +77 -0
- package/src/apothem/harnesses/kiro/__init__.py +49 -0
- package/src/apothem/harnesses/kiro/capabilities.yml +36 -0
- package/src/apothem/harnesses/kiro/install.py +39 -0
- package/src/apothem/harnesses/kiro/templates/apothem-rules.md +36 -0
- package/src/apothem/harnesses/kiro/uninstall.py +25 -0
- package/src/apothem/harnesses/kiro/update.py +10 -0
- package/src/apothem/harnesses/kiro/verify.py +11 -0
- package/src/apothem/harnesses/open_claw/STANDARD-CONVENTION-PIN.md +62 -0
- package/src/apothem/harnesses/open_claw/__init__.py +35 -0
- package/src/apothem/harnesses/open_claw/capabilities.yml +35 -0
- package/src/apothem/harnesses/open_claw/install.py +17 -0
- package/src/apothem/harnesses/open_claw/materializer.py +36 -0
- package/src/apothem/harnesses/open_claw/uninstall.py +32 -0
- package/src/apothem/harnesses/open_claw/update.py +10 -0
- package/src/apothem/harnesses/open_claw/verify.py +11 -0
- package/src/apothem/harnesses/opencode/STANDARD-CONVENTION-PIN.md +76 -0
- package/src/apothem/harnesses/opencode/__init__.py +35 -0
- package/src/apothem/harnesses/opencode/capabilities.yml +43 -0
- package/src/apothem/harnesses/opencode/install.py +17 -0
- package/src/apothem/harnesses/opencode/materializer.py +31 -0
- package/src/apothem/harnesses/opencode/uninstall.py +34 -0
- package/src/apothem/harnesses/opencode/update.py +10 -0
- package/src/apothem/harnesses/opencode/verify.py +11 -0
- package/src/apothem/harnesses/qwen_code/STANDARD-CONVENTION-PIN.md +87 -0
- package/src/apothem/harnesses/qwen_code/__init__.py +37 -0
- package/src/apothem/harnesses/qwen_code/capabilities.yml +43 -0
- package/src/apothem/harnesses/qwen_code/install.py +19 -0
- package/src/apothem/harnesses/qwen_code/materializer.py +174 -0
- package/src/apothem/harnesses/qwen_code/templates/QWEN.md +30 -0
- package/src/apothem/harnesses/qwen_code/uninstall.py +34 -0
- package/src/apothem/harnesses/qwen_code/update.py +10 -0
- package/src/apothem/harnesses/qwen_code/verify.py +11 -0
- package/src/apothem/harnesses/trae/STANDARD-CONVENTION-PIN.md +70 -0
- package/src/apothem/harnesses/trae/__init__.py +49 -0
- package/src/apothem/harnesses/trae/capabilities.yml +34 -0
- package/src/apothem/harnesses/trae/install.py +38 -0
- package/src/apothem/harnesses/trae/templates/apothem-rules.md +37 -0
- package/src/apothem/harnesses/trae/uninstall.py +25 -0
- package/src/apothem/harnesses/trae/update.py +10 -0
- package/src/apothem/harnesses/trae/verify.py +11 -0
- package/src/apothem/harnesses/windsurf/STANDARD-CONVENTION-PIN.md +91 -0
- package/src/apothem/harnesses/windsurf/__init__.py +52 -0
- package/src/apothem/harnesses/windsurf/capabilities.yml +40 -0
- package/src/apothem/harnesses/windsurf/install.py +41 -0
- package/src/apothem/harnesses/windsurf/templates/apothem-rules.md +37 -0
- package/src/apothem/harnesses/windsurf/uninstall.py +25 -0
- package/src/apothem/harnesses/windsurf/update.py +10 -0
- package/src/apothem/harnesses/windsurf/verify.py +11 -0
- package/src/apothem/harnesses/zed/STANDARD-CONVENTION-PIN.md +92 -0
- package/src/apothem/harnesses/zed/__init__.py +57 -0
- package/src/apothem/harnesses/zed/capabilities.yml +38 -0
- package/src/apothem/harnesses/zed/install.py +41 -0
- package/src/apothem/harnesses/zed/templates/apothem-rules.md +32 -0
- package/src/apothem/harnesses/zed/uninstall.py +28 -0
- package/src/apothem/harnesses/zed/update.py +10 -0
- package/src/apothem/harnesses/zed/verify.py +11 -0
- package/src/apothem/hooks/README.md +81 -0
- package/src/apothem/hooks/__init__.py +24 -0
- package/src/apothem/hooks/askuserquestion_validator.py +380 -0
- package/src/apothem/hooks/dispatch.py +296 -0
- package/src/apothem/hooks/emit_hook_context.py +444 -0
- package/src/apothem/hooks/hooks.json +318 -0
- package/src/apothem/hooks/lib/README.md +39 -0
- package/src/apothem/hooks/lib/__init__.py +18 -0
- package/src/apothem/hooks/lib/bootstrap.ps1 +129 -0
- package/src/apothem/hooks/lib/bootstrap.sh +103 -0
- package/src/apothem/hooks/lib/events.py +51 -0
- package/src/apothem/hooks/lib/find-pwsh.ps1 +78 -0
- package/src/apothem/hooks/lib/find-pwsh.sh +76 -0
- package/src/apothem/hooks/lib/find-python.ps1 +63 -0
- package/src/apothem/hooks/lib/find-python.sh +97 -0
- package/src/apothem/hooks/lib/log.py +43 -0
- package/src/apothem/hooks/lib/resolve_root.py +264 -0
- package/src/apothem/hooks/messages/postcompact.md +14 -0
- package/src/apothem/hooks/messages/posttooluse-proactive-compaction.md +46 -0
- package/src/apothem/hooks/messages/precompact.md +14 -0
- package/src/apothem/hooks/messages/pretooluse-askuserquestion-recommended.md +65 -0
- package/src/apothem/hooks/messages/pretooluse-bash-plan-guard.md +97 -0
- package/src/apothem/hooks/messages/pretooluse-bash.md +39 -0
- package/src/apothem/hooks/messages/pretooluse-conformity.md +70 -0
- package/src/apothem/hooks/messages/pretooluse-dependency-guard.md +21 -0
- package/src/apothem/hooks/messages/pretooluse-edit-header-guard.md +61 -0
- package/src/apothem/hooks/messages/pretooluse-edit.md +21 -0
- package/src/apothem/hooks/messages/pretooluse-eval-guard.md +39 -0
- package/src/apothem/hooks/messages/pretooluse-notebookedit.md +11 -0
- package/src/apothem/hooks/messages/pretooluse-write-header-guard.md +45 -0
- package/src/apothem/hooks/messages/pretooluse-write-plan-guard.md +72 -0
- package/src/apothem/hooks/messages/pretooluse-write.md +21 -0
- package/src/apothem/hooks/messages/sessionstart.md +15 -0
- package/src/apothem/hooks/messages/stop.md +27 -0
- package/src/apothem/hooks/proactive_compaction_tracker.py +327 -0
- package/src/apothem/hooks/session_start_bootstrap.py +472 -0
- package/src/apothem/lib/README.md +42 -0
- package/src/apothem/lib/__init__.py +13 -0
- package/src/apothem/lib/atomic_io.py +189 -0
- package/src/apothem/lib/auditor.py +687 -0
- package/src/apothem/lib/clean_slate.py +396 -0
- package/src/apothem/lib/contexts.py +352 -0
- package/src/apothem/lib/data_home.py +255 -0
- package/src/apothem/lib/frontmatter.py +101 -0
- package/src/apothem/lib/harness_materializer.py +213 -0
- package/src/apothem/lib/harness_protocol.py +59 -0
- package/src/apothem/lib/harness_registry.py +282 -0
- package/src/apothem/lib/harness_registry_data.py +843 -0
- package/src/apothem/lib/install_ledger.py +347 -0
- package/src/apothem/lib/learning.py +540 -0
- package/src/apothem/lib/memory.py +347 -0
- package/src/apothem/lib/parallel_sweep.py +234 -0
- package/src/apothem/lib/plan_tiers.py +200 -0
- package/src/apothem/lib/plugin_bootstrap.py +132 -0
- package/src/apothem/lib/plugin_tree.py +599 -0
- package/src/apothem/lib/profile.py +755 -0
- package/src/apothem/lib/profile_projection.py +198 -0
- package/src/apothem/lib/propagation-manifest.yaml +878 -0
- package/src/apothem/lib/propagation.py +220 -0
- package/src/apothem/lib/python_resolver.py +189 -0
- package/src/apothem/lib/reporter.py +62 -0
- package/src/apothem/lib/workspace_migration.py +323 -0
- package/src/apothem/output-styles/README.md +41 -0
- package/src/apothem/output-styles/concise-engineer.md +49 -0
- package/src/apothem/output-styles/default-architect.md +52 -0
- package/src/apothem/output-styles/default.md +113 -0
- package/src/apothem/output-styles/forensic-auditor.md +63 -0
- package/src/apothem/py.typed +0 -0
- package/src/apothem/rules/README.md +121 -0
- package/src/apothem/rules/agent-capability-discipline-matrix.md +89 -0
- package/src/apothem/rules/agent-capability-discipline.md +78 -0
- package/src/apothem/rules/agent-orchestration-patterns.md +144 -0
- package/src/apothem/rules/agent-orchestration.md +65 -0
- package/src/apothem/rules/agents-md-convention.md +86 -0
- package/src/apothem/rules/agile-sprints-elements.md +135 -0
- package/src/apothem/rules/agile-sprints.md +64 -0
- package/src/apothem/rules/agnostic-posture-checklist.md +47 -0
- package/src/apothem/rules/agnostic-posture.md +48 -0
- package/src/apothem/rules/authoritative-referencing-quotation.md +50 -0
- package/src/apothem/rules/authoritative-referencing.md +66 -0
- package/src/apothem/rules/authority-inquiry-categories.md +58 -0
- package/src/apothem/rules/authority-inquiry.md +54 -0
- package/src/apothem/rules/auto-memory-topic-files.md +86 -0
- package/src/apothem/rules/auto-memory.md +67 -0
- package/src/apothem/rules/bidirectional-binding.md +123 -0
- package/src/apothem/rules/canonical-layout-reporting-tiers.md +212 -0
- package/src/apothem/rules/canonical-layout.md +60 -0
- package/src/apothem/rules/clean-architecture-layers.md +186 -0
- package/src/apothem/rules/clean-room-generation-protocols.md +124 -0
- package/src/apothem/rules/clean-room-generation.md +59 -0
- package/src/apothem/rules/code-craft-conventions.md +101 -0
- package/src/apothem/rules/code-craft-markdown.md +138 -0
- package/src/apothem/rules/code-craft-python.md +154 -0
- package/src/apothem/rules/code-craft-shell.md +192 -0
- package/src/apothem/rules/cognitive-identity-techniques.md +180 -0
- package/src/apothem/rules/cognitive-identity.md +81 -0
- package/src/apothem/rules/context-management-budget.md +46 -0
- package/src/apothem/rules/context-management-protocol.md +161 -0
- package/src/apothem/rules/context-management-scratch.md +128 -0
- package/src/apothem/rules/context-management.md +85 -0
- package/src/apothem/rules/definitiveness-virtues.md +67 -0
- package/src/apothem/rules/definitiveness.md +58 -0
- package/src/apothem/rules/determinism.md +81 -0
- package/src/apothem/rules/disclosure-ledger-markers.md +58 -0
- package/src/apothem/rules/disclosure-ledger.md +52 -0
- package/src/apothem/rules/dynamism.md +38 -0
- package/src/apothem/rules/etc-extension.md +57 -0
- package/src/apothem/rules/expertise-posture-elements.md +68 -0
- package/src/apothem/rules/expertise-posture.md +54 -0
- package/src/apothem/rules/freshness-facade.md +64 -0
- package/src/apothem/rules/harness-adapter-shape-schemas.md +162 -0
- package/src/apothem/rules/harness-adapter-shape.md +42 -0
- package/src/apothem/rules/host-discovery-manifests.md +50 -0
- package/src/apothem/rules/host-discovery.md +56 -0
- package/src/apothem/rules/i18n-discipline-locale-cohorts.md +120 -0
- package/src/apothem/rules/i18n-discipline.md +70 -0
- package/src/apothem/rules/interactive-questions-canonical-shapes.md +590 -0
- package/src/apothem/rules/interactive-questions-detail.md +41 -0
- package/src/apothem/rules/interactive-questions-sweep-matchers.md +184 -0
- package/src/apothem/rules/interactive-questions.md +89 -0
- package/src/apothem/rules/large-file-generation.md +112 -0
- package/src/apothem/rules/large-file-reading.md +59 -0
- package/src/apothem/rules/living-docs.md +85 -0
- package/src/apothem/rules/multi-agent-workflow.md +57 -0
- package/src/apothem/rules/operational-mandates-expanded.md +78 -0
- package/src/apothem/rules/operational-mandates.md +88 -0
- package/src/apothem/rules/option-annotation-form.md +60 -0
- package/src/apothem/rules/option-annotation.md +45 -0
- package/src/apothem/rules/own-voice-reimplementation.md +86 -0
- package/src/apothem/rules/performance-discipline.md +91 -0
- package/src/apothem/rules/persistent-conventions-vigilance-checklist.md +54 -0
- package/src/apothem/rules/persistent-conventions-vigilance.md +61 -0
- package/src/apothem/rules/plain-language.md +56 -0
- package/src/apothem/rules/planning-techniques.md +130 -0
- package/src/apothem/rules/pre-emission-gate-bars.md +86 -0
- package/src/apothem/rules/pre-emission-gate.md +54 -0
- package/src/apothem/rules/production-ready-prs-surfaces.md +162 -0
- package/src/apothem/rules/production-ready-prs.md +83 -0
- package/src/apothem/rules/propagation.md +63 -0
- package/src/apothem/rules/recommend-next-step.md +106 -0
- package/src/apothem/rules/refactoring-discipline.md +76 -0
- package/src/apothem/rules/session-closure.md +44 -0
- package/src/apothem/rules/sota-elevation-exemplars.md +76 -0
- package/src/apothem/rules/sota-elevation.md +52 -0
- package/src/apothem/rules/source-accessibility.md +58 -0
- package/src/apothem/rules/surgical-manipulation.md +48 -0
- package/src/apothem/rules/systemic-participation-relations.md +108 -0
- package/src/apothem/rules/systemic-participation.md +70 -0
- package/src/apothem/rules/ten-dimension-check-dimensions.md +52 -0
- package/src/apothem/rules/ten-dimension-check.md +59 -0
- package/src/apothem/rules/token-budget-discipline.md +81 -0
- package/src/apothem/rules/token-efficiency-rewrite-protocol.md +79 -0
- package/src/apothem/rules/token-efficiency-rewrite.md +77 -0
- package/src/apothem/rules/tool-use-discipline.md +48 -0
- package/src/apothem/rules/visual-leverage.md +102 -0
- package/src/apothem/schemas/NOTICE.md +9 -0
- package/src/apothem/schemas/README.md +104 -0
- package/src/apothem/schemas/__init__.py +176 -0
- package/src/apothem/schemas/advisory-finding.schema.json +111 -0
- package/src/apothem/schemas/agent.schema.json +106 -0
- package/src/apothem/schemas/authorship-header.txt +1 -0
- package/src/apothem/schemas/cohort-manifest.yaml +248 -0
- package/src/apothem/schemas/cohort-metadata-vocabulary.yaml +168 -0
- package/src/apothem/schemas/cohort.schema.json +113 -0
- package/src/apothem/schemas/command.schema.json +68 -0
- package/src/apothem/schemas/compatibility-matrix.yaml +432 -0
- package/src/apothem/schemas/context-fragment.schema.json +64 -0
- package/src/apothem/schemas/freshness-token-denylist.txt +51 -0
- package/src/apothem/schemas/handoff-manifest.yaml +353 -0
- package/src/apothem/schemas/header-exceptions.txt +141 -0
- package/src/apothem/schemas/header-visibility.yaml +39 -0
- package/src/apothem/schemas/learning-signal.schema.json +46 -0
- package/src/apothem/schemas/memory-record.schema.json +61 -0
- package/src/apothem/schemas/output-style.schema.json +40 -0
- package/src/apothem/schemas/plan.schema.json +51 -0
- package/src/apothem/schemas/plugin.schema.json +83 -0
- package/src/apothem/schemas/profile.example.yaml +70 -0
- package/src/apothem/schemas/profile.minimal.yaml +6 -0
- package/src/apothem/schemas/profile.schema.json +396 -0
- package/src/apothem/schemas/reference-token-denylist.txt +25 -0
- package/src/apothem/schemas/skill.schema.json +75 -0
- package/src/apothem/skills/README.md +93 -0
- package/src/apothem/skills/dependency-upgrade/SKILL.md +105 -0
- package/src/apothem/skills/dev-toolkit/SKILL.md +120 -0
- package/src/apothem/skills/diagram-authoring/SKILL.md +113 -0
- package/src/apothem/skills/document-authoring/SKILL.md +118 -0
- package/src/apothem/skills/ecosystem-audit/SKILL.md +108 -0
- package/src/apothem/skills/ecosystem-audit/references/audit-fortress.md +85 -0
- package/src/apothem/skills/ecosystem-audit/references/procedure.md +162 -0
- package/src/apothem/skills/eval-harness/SKILL.md +88 -0
- package/src/apothem/skills/incident-runbook/SKILL.md +92 -0
- package/src/apothem/skills/multi-source-research/SKILL.md +90 -0
- package/src/apothem/skills/plan-suite/SKILL.md +118 -0
- package/src/apothem/skills/plan-suite/master_template.md +1324 -0
- package/src/apothem/skills/projectify/SKILL.md +117 -0
- package/src/apothem/skills/prompt-engineering/SKILL.md +122 -0
- package/src/apothem/skills/refactor-extract/SKILL.md +85 -0
- package/src/apothem/skills/research-suite/SKILL.md +170 -0
- package/src/apothem/skills/research-suite/references/directory-structure.md +47 -0
- package/src/apothem/skills/research-suite/references/lifecycle.md +67 -0
- package/src/apothem/skills/research-suite/references/principal-investigator-framework.md +37 -0
- package/src/apothem/skills/research-suite/references/rigor-mandates.md +30 -0
- package/src/apothem/skills/research-suite/research_template.md +476 -0
- package/src/apothem/skills/secret-rotation/SKILL.md +87 -0
- package/src/apothem/skills/source-synthesis/SKILL.md +92 -0
- package/src/apothem/skills/surgical-guard/SKILL.md +118 -0
- package/src/apothem/skills/test-authoring/SKILL.md +85 -0
- package/src/apothem/skills/vuln-triage/SKILL.md +91 -0
- package/src/apothem/skills/workflow/SKILL.md +139 -0
- package/src/apothem/statuslines/README.md +26 -0
- package/src/apothem/statuslines/__init__.py +20 -0
- package/src/apothem/statuslines/conformity.json +5 -0
- package/src/apothem/statuslines/render.py +334 -0
- package/src/apothem/statuslines/statusline.md +50 -0
- package/src/apothem/templates/README.md +43 -0
- package/src/apothem/templates/agents-md-template.md +80 -0
- package/src/apothem/templates/consideration-log.md +39 -0
- package/src/apothem/templates/expertise-gap-log.md +56 -0
- package/src/apothem/templates/master-index-template.md +93 -0
- package/src/apothem/templates/potency-map.md +53 -0
- package/src/apothem/templates/preservation-audit.md +60 -0
- package/src/apothem/templates/question-resolution-audit.md +52 -0
- package/src/apothem/templates/trace-matrix-template.md +77 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# conformity
|
|
4
|
+
|
|
5
|
+
> **Role.** Pre-emission conformity validators. `gate.py` orchestrates a fleet of mechanical `*_grep` matchers (plus the link checker) against a Write/Edit input, returning a pass/fail verdict before the artifact is emitted.
|
|
6
|
+
|
|
7
|
+
## Orchestrator
|
|
8
|
+
|
|
9
|
+
| File | Purpose |
|
|
10
|
+
|------|---------|
|
|
11
|
+
| `gate.py` | The conformity-gate orchestrator — dispatches every matcher against a Write/Edit input and aggregates the verdicts. |
|
|
12
|
+
| `__init__.py` | Package marker. |
|
|
13
|
+
|
|
14
|
+
## Matcher families
|
|
15
|
+
|
|
16
|
+
### Authorship & structure
|
|
17
|
+
|
|
18
|
+
| File | Checks |
|
|
19
|
+
|------|--------|
|
|
20
|
+
| `file_header_grep.py` | Canonical authorship-header presence and form. |
|
|
21
|
+
| `frontmatter_grep.py` | Required frontmatter fields on artifact classes that carry them. |
|
|
22
|
+
| `frontmatter_value_grep.py` | Frontmatter `enum`/`pattern` values against the per-class JSON Schema (agents, commands, skills) — the value-level counterpart to `frontmatter_grep`'s key check. |
|
|
23
|
+
| `naming_grep.py` | Naming-convention conformance. |
|
|
24
|
+
| `binding_reciprocity_grep.py` | Reciprocal five-direction bindings — half-edge detection. |
|
|
25
|
+
| `always_on_budget_grep.py` | Always-on rule body token budget (the 500-token ceiling). |
|
|
26
|
+
| `agent_capability_grep.py` | Every harness declares its agentic-capability matrix. |
|
|
27
|
+
| `agents_md_coverage_grep.py` | Stale agent-companion files under the root-only AGENTS.md convention. |
|
|
28
|
+
| `registry_capability_consistency_grep.py` | Registry capability cells not backed by install / materializer / projection evidence. |
|
|
29
|
+
| `recommend_next_step_grep.py` | `## Recommended Next Step` block presence on command / skill terminal surfaces. |
|
|
30
|
+
| `determinism_grep.py` | Deterministic output shape across command and skill surfaces. |
|
|
31
|
+
| `no_toplevel_docs_grep.py` | A top-level `docs/` directory at the repository root. |
|
|
32
|
+
|
|
33
|
+
### Prose & narrative discipline
|
|
34
|
+
|
|
35
|
+
| File | Checks |
|
|
36
|
+
|------|--------|
|
|
37
|
+
| `hedging_grep.py` | Hedging vocabulary in prescriptive prose. |
|
|
38
|
+
| `option_annotation_grep.py` | Per-option `(Recommended)` label-to-body bind (H6): canonical capital postfix iff body `recommendation: recommended`, no spurious or lowercase postfix, at most one recommended option in a single-select set. |
|
|
39
|
+
| `completion_claim_grep.py` | Unsupported absolute-guarantee completion claims in cohort prose (spec §4.2 honesty) — e.g., "guaranteed to pass", "always works", "100% complete", "cannot fail". |
|
|
40
|
+
| `diagram_staleness_grep.py` | Diagram verification dates against the structure they abstract. |
|
|
41
|
+
| `multi_surface_coherence_grep.py` | Coherence across paired/multi-surface artifacts. |
|
|
42
|
+
| `plain_language_grep.py` | Mechanistic / harness-internal vocabulary in user-facing prose. |
|
|
43
|
+
| `token_efficiency_grep.py` | Filler phrases, throat-clearing openers, content-free qualifiers. |
|
|
44
|
+
| `redundancy_grep.py` | Substantively-duplicated paragraphs across the governed corpus. |
|
|
45
|
+
| `agnosticism_grep.py` | Harness bias and re-introduced enforcement presets in shipped surfaces. |
|
|
46
|
+
|
|
47
|
+
### Plans discipline
|
|
48
|
+
|
|
49
|
+
| File | Checks |
|
|
50
|
+
|------|--------|
|
|
51
|
+
| `no_global_plans_grep.py` | Writes to a global plans directory. |
|
|
52
|
+
| `plans_discipline_language_grep.py` | Plans-discipline language violations. |
|
|
53
|
+
| `orphan_output_grep.py` | Orphan outputs — no consumer / no index entry / no producer attribution. |
|
|
54
|
+
| `user_confirm_grep.py` | Unfilled `<USER-CONFIRM:…>` placeholders. |
|
|
55
|
+
| `plan_suite_structure_grep.py` | Plan-suite structure — suite-locality, closed vocabulary, numeric-prefix discipline. |
|
|
56
|
+
| `plan_next_step_consistency_grep.py` | Plan-suite infra files' Recommended-Next-Step footer consistency (advisory). |
|
|
57
|
+
|
|
58
|
+
### Code craft
|
|
59
|
+
|
|
60
|
+
| File | Checks |
|
|
61
|
+
|------|--------|
|
|
62
|
+
| `bare_except_grep.py` | Bare / overly-broad `except` clauses. |
|
|
63
|
+
| `commented_out_code_grep.py` | Commented-out code blocks. |
|
|
64
|
+
| `magic_number_grep.py` | Magic numbers in logic without named constants. |
|
|
65
|
+
|
|
66
|
+
### Supply chain & security
|
|
67
|
+
|
|
68
|
+
| File | Checks |
|
|
69
|
+
|------|--------|
|
|
70
|
+
| `secret_leak_grep.py` | Secret literals committed to source — vendor-prefixed credential patterns plus a high-entropy heuristic, with a canonical-banner allow-list. |
|
|
71
|
+
| `unpinned_action_grep.py` | Unpinned GitHub Actions `uses:` references. |
|
|
72
|
+
| `permissions_minimum_scope_grep.py` | Every workflow declares a minimum-scope `permissions:` block. |
|
|
73
|
+
| `harden_runner_grep.py` | Every workflow job opens with a conformant harden-runner step. |
|
|
74
|
+
| `workflow_concurrency_grep.py` | Concurrency group + per-job timeout discipline on workflows. |
|
|
75
|
+
| `oidc_trusted_publishing_grep.py` | Release workflows use OIDC trusted publishing. |
|
|
76
|
+
| `cross_platform_matrix_grep.py` | CI declares a cross-platform OS × Python matrix. |
|
|
77
|
+
| `editorconfig_presence_grep.py` | Canonical `.editorconfig` present at the project root. |
|
|
78
|
+
| `gitattributes_presence_grep.py` | Repo-root `.gitattributes` carries the canonical contract. |
|
|
79
|
+
|
|
80
|
+
### Release & branding
|
|
81
|
+
|
|
82
|
+
| File | Checks |
|
|
83
|
+
|------|--------|
|
|
84
|
+
| `production_ready_pr_grep.py` | Same-change-set production-readiness discipline. |
|
|
85
|
+
| `license_author_consistency_grep.py` | Verifies the root LICENSE carries an author line. |
|
|
86
|
+
| `brand_mark_grep.py` | Brand-mark usage. |
|
|
87
|
+
| `smoke_install_grep.py` | Install-script smoke-check markers. |
|
|
88
|
+
| `copilot_instructions_presence_grep.py` | `copilot-instructions.md` presence. |
|
|
89
|
+
| `dynamism_grep.py` | Static-string version embeds in dynamism-required surfaces. |
|
|
90
|
+
| `static_version_grep.py` | Version-bearing sites resolve dynamically, not as static literals. |
|
|
91
|
+
| `semver_stability_grep.py` | Semver stability (the change-set-scoped M15 mechanical fraction). |
|
|
92
|
+
| `conventional_commit_grep.py` | HEAD commit messages against the Conventional-Commits grammar. |
|
|
93
|
+
| `freshness_token_grep.py` | Freshness-narrative phrases on shipped public surfaces. |
|
|
94
|
+
|
|
95
|
+
### Link integrity
|
|
96
|
+
|
|
97
|
+
| File | Checks |
|
|
98
|
+
|------|--------|
|
|
99
|
+
| `link_check.py` | Validate Markdown internal links against the on-disk reference graph. |
|
|
100
|
+
|
|
101
|
+
## Operating contract
|
|
102
|
+
|
|
103
|
+
`gate.py` is the single dispatch surface. It owns two matcher registries —
|
|
104
|
+
`GREP_MODULES` (per-Write matchers with a `check(content, path)` signature, run
|
|
105
|
+
on the Write/Edit body) and `STANDALONE_MODULES` (corpus walkers that take a
|
|
106
|
+
root directory and walk the tree, git index, or a fixed surface set) — plus the
|
|
107
|
+
CLI surface (`--all`, `--check <name>`, `--list`, `--hook`, `--strict`) and the
|
|
108
|
+
scope/short-circuit logic. The invariants a matcher must hold to:
|
|
109
|
+
|
|
110
|
+
- **Advisory by default.** The gate reports findings and exits zero so the write
|
|
111
|
+
proceeds; strict blocking is opt-in via `--strict` or a truthy
|
|
112
|
+
`APOTHEM_CONFORMITY_STRICT`. A matcher's standalone `to_json()` carries
|
|
113
|
+
`"advisory": true`, and its CLI `_main` may exit non-zero on findings (the
|
|
114
|
+
orchestrator treats the standalone exit code as the strict signal). Never
|
|
115
|
+
hard-block a write from inside a matcher.
|
|
116
|
+
- **Fail-open isolation.** The orchestrator wraps every matcher load and
|
|
117
|
+
`check()` call; a raised exception is recorded and surfaced, never swallowed,
|
|
118
|
+
and never fail-closes the write. Do not catch-and-suppress inside a matcher;
|
|
119
|
+
let the orchestrator's boundary handle errors.
|
|
120
|
+
- **Dataclass result shape.** Matchers return a frozen `GrepResult` carrying
|
|
121
|
+
`passed: bool` and `findings: list[Finding]`; `Finding` carries the surface,
|
|
122
|
+
kind/issue, and a `detail` string. The orchestrator duck-types
|
|
123
|
+
`getattr(result, "passed", ...)` and `result.findings`, so the field names are
|
|
124
|
+
the contract.
|
|
125
|
+
- **Registry-name forms.** `STANDALONE_MODULES` entries are stored hyphenated
|
|
126
|
+
(`reference-token-grep`) for CLI ergonomics; the on-disk filename is
|
|
127
|
+
underscored (`reference_token_grep.py`). `GREP_MODULES` entries are
|
|
128
|
+
underscored. `_resolve_validator` normalizes both forms.
|
|
129
|
+
- **Plan/scope short-circuits are gate-owned.** `.plans/` paths, out-of-scope
|
|
130
|
+
writes, and harness runtime-state subtrees (`projects/`, `memory/`)
|
|
131
|
+
short-circuit to a silent pass in the orchestrator. A per-Write matcher MUST
|
|
132
|
+
NOT itself special-case `.plans/`; rely on the gate's `_is_plan_suite_path`
|
|
133
|
+
short-circuit.
|
|
134
|
+
- Denylist/schema data a matcher consumes lives in [`../schemas/`](../schemas/),
|
|
135
|
+
never inlined in the module.
|
|
136
|
+
|
|
137
|
+
## Adding or modifying a matcher
|
|
138
|
+
|
|
139
|
+
To **add a matcher**:
|
|
140
|
+
|
|
141
|
+
1. Author `<name>_grep.py` here. Define frozen `Finding` and `GrepResult`
|
|
142
|
+
dataclasses; `GrepResult.to_json()` emits `"advisory": true`. Expose the
|
|
143
|
+
entry callable — **per-Write**:
|
|
144
|
+
`check(content: str, path: Path | None = None) -> GrepResult`; **corpus
|
|
145
|
+
walker**: `check(root: Path) -> GrepResult` plus a `_main(argv)` that prints
|
|
146
|
+
JSON and returns `EXIT_PASS` (0) / `EXIT_FAIL` (2).
|
|
147
|
+
2. **Register** in `gate.py`: add the underscored name to `GREP_MODULES` for
|
|
148
|
+
per-Write, OR the hyphenated name to `STANDALONE_MODULES` for a corpus walker.
|
|
149
|
+
3. Add **fixtures and tests** under `tests/conformity/<name>/` (pass/fail cases)
|
|
150
|
+
and a test module under `tests/conformity/`. For standalone walkers, also
|
|
151
|
+
register the matcher in `tests/conformity/test_standalone_greps_inprocess.py`
|
|
152
|
+
so it runs in-process in the suite.
|
|
153
|
+
4. Keep within the **per-grep wall-clock budget** (`PER_GREP_BUDGET_SECONDS` in
|
|
154
|
+
`gate.py`); the hook has a 10s `PreToolUse` ceiling and the orchestrator flags
|
|
155
|
+
any matcher approaching the per-grep budget as a watch item. Cheap structural
|
|
156
|
+
scans run before expensive regex sweeps.
|
|
157
|
+
|
|
158
|
+
To **modify or remove a matcher**: keep the registry entry, fixtures, and the
|
|
159
|
+
in-process test list in sync in the same change-set; an orphaned entry or a
|
|
160
|
+
registered name with no script surfaces as a load error.
|
|
161
|
+
|
|
162
|
+
Validate every change here:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
python -m apothem.conformity.gate --all .
|
|
166
|
+
python -m pytest tests/conformity
|
|
167
|
+
python -m ruff check .
|
|
168
|
+
python -m mypy src/apothem/cli/ src/apothem/harnesses/
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Related
|
|
172
|
+
|
|
173
|
+
- [`hooks/`](../hooks/) — the dispatcher that fires the gate on PreToolUse Write/Edit events.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Shared scaffolding for path-based conformity matchers.
|
|
4
|
+
|
|
5
|
+
Why this module exists. The path-based conformity matchers
|
|
6
|
+
(``check(content, path) -> GrepResult``) each defined a byte-identical
|
|
7
|
+
``GrepResult`` dataclass, an identical ``to_json`` serialiser, and a
|
|
8
|
+
near-identical ``_read_input`` / ``_main`` / ``__main__`` skeleton. Hoisting
|
|
9
|
+
that boilerplate here removes the duplication while preserving every matcher's
|
|
10
|
+
observable behaviour: the JSON report shape, the exit codes, and the
|
|
11
|
+
stdin-or-path input contract are unchanged.
|
|
12
|
+
|
|
13
|
+
Scope. This base serves matchers whose canonical report payload is exactly
|
|
14
|
+
``{grep, path, passed, findings}`` — optionally carrying a ``note`` emitted
|
|
15
|
+
only when present. Matchers with ``root``-based payloads, extra report keys,
|
|
16
|
+
or always-emitted ``advisory`` flags keep their own ``GrepResult`` because
|
|
17
|
+
their serialised shape diverges from this one.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import json
|
|
23
|
+
import sys
|
|
24
|
+
from collections.abc import Callable
|
|
25
|
+
from dataclasses import asdict, dataclass, field
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Any, Final, Protocol
|
|
28
|
+
|
|
29
|
+
EXIT_PASS: Final[int] = 0
|
|
30
|
+
EXIT_FAIL: Final[int] = 2
|
|
31
|
+
STDIN_FLAG: Final[str] = "--stdin"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class _Finding(Protocol):
|
|
35
|
+
"""Structural type for a per-matcher finding dataclass."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class GrepResult:
|
|
40
|
+
"""Canonical path-based matcher report.
|
|
41
|
+
|
|
42
|
+
Pre-conditions: ``findings`` holds the matcher-specific finding dataclasses
|
|
43
|
+
(each a frozen ``@dataclass``). Post-conditions: ``to_json`` emits the
|
|
44
|
+
canonical ``{grep, path, passed, findings}`` payload, including ``note``
|
|
45
|
+
only when it is not ``None``.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
grep: str
|
|
49
|
+
path: str | None
|
|
50
|
+
passed: bool
|
|
51
|
+
findings: list[Any] = field(default_factory=list)
|
|
52
|
+
note: str | None = None
|
|
53
|
+
|
|
54
|
+
def to_json(self) -> str:
|
|
55
|
+
payload: dict[str, object] = {
|
|
56
|
+
"grep": self.grep,
|
|
57
|
+
"path": self.path,
|
|
58
|
+
"passed": self.passed,
|
|
59
|
+
"findings": [asdict(f) for f in self.findings],
|
|
60
|
+
}
|
|
61
|
+
if self.note is not None:
|
|
62
|
+
payload["note"] = self.note
|
|
63
|
+
return json.dumps(payload, indent=2)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def read_input(argv: list[str]) -> tuple[str, Path | None]:
|
|
67
|
+
"""Return ``(content, path)`` from a path argument or stdin.
|
|
68
|
+
|
|
69
|
+
Pre-conditions: ``argv`` is ``sys.argv`` (``argv[0]`` is the script name).
|
|
70
|
+
Post-conditions: when ``argv[1]`` is a path (not ``--stdin``), the file is
|
|
71
|
+
read and returned with its ``Path``; otherwise stdin is read with a
|
|
72
|
+
``None`` path.
|
|
73
|
+
"""
|
|
74
|
+
if len(argv) >= 2 and argv[1] != STDIN_FLAG:
|
|
75
|
+
path = Path(argv[1])
|
|
76
|
+
return path.read_text(encoding="utf-8"), path
|
|
77
|
+
return sys.stdin.read(), None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def run_grep(
|
|
81
|
+
check: Callable[[str, Path | None], GrepResult],
|
|
82
|
+
argv: list[str],
|
|
83
|
+
) -> int:
|
|
84
|
+
"""Run ``check`` over the resolved input, print the report, return the exit.
|
|
85
|
+
|
|
86
|
+
Pre-conditions: ``check`` returns a :class:`GrepResult`. Post-conditions:
|
|
87
|
+
the JSON report is printed to stdout; the return is ``EXIT_PASS`` when the
|
|
88
|
+
result passed, ``EXIT_FAIL`` otherwise.
|
|
89
|
+
"""
|
|
90
|
+
content, path = read_input(argv)
|
|
91
|
+
result = check(content, path)
|
|
92
|
+
print(result.to_json())
|
|
93
|
+
return EXIT_PASS if result.passed else EXIT_FAIL
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Verify every harness declares its agentic-capability matrix.
|
|
4
|
+
|
|
5
|
+
Why this validator exists. The agent-capability discipline (per
|
|
6
|
+
``rules/agent-capability-discipline.md``) requires every harness in
|
|
7
|
+
the 17-harness cohort to declare a structured capability matrix in its
|
|
8
|
+
template tree so adapter authors, operators, and downstream tooling can
|
|
9
|
+
reason about the harness's agentic surface without inspecting source.
|
|
10
|
+
The installed machine-readable projection names thirteen fields:
|
|
11
|
+
``mcp_servers`` (list of MCP servers the harness can host),
|
|
12
|
+
``sub_agent_dispatch`` (bool — whether the harness spawns sub-agents),
|
|
13
|
+
``custom_command_support`` (yes/no/discovery-pending),
|
|
14
|
+
``recommended_postfix_rendering`` (how recommended option labels render),
|
|
15
|
+
``long_context_compaction`` (native or profile-managed long-session
|
|
16
|
+
continuity), ``context_ignore_surface`` (native ignore surface or declared
|
|
17
|
+
absence), ``standard_convention_pin`` (the sibling pin file),
|
|
18
|
+
``tool_surface_restrictions`` (list of tool-surface constraints),
|
|
19
|
+
``system_prompt_template_path`` (str pointer to the harness's system-prompt
|
|
20
|
+
template), ``agent_memory_surface`` (str naming the harness's memory
|
|
21
|
+
surface), ``layered_context_surface`` (native hierarchy or profile-managed
|
|
22
|
+
projection), ``lsp_symbol_navigation`` (native/plugin-backed symbol lookup
|
|
23
|
+
or tracked gap), and ``hook_learning_capture`` (where recurring hook lessons
|
|
24
|
+
are persisted without pass-class chatter).
|
|
25
|
+
|
|
26
|
+
Detection. For each harness directory at
|
|
27
|
+
``src/apothem/harnesses/<harness>/`` that exists, look for one of three
|
|
28
|
+
declaration files: ``capabilities.yml`` / ``capabilities.yaml`` /
|
|
29
|
+
``agent_capabilities.md``. The YAML form is parsed; the Markdown form is
|
|
30
|
+
inspected for the thirteen field markers as ``- field_name:`` lines. A
|
|
31
|
+
harness whose directory is present but whose declaration is absent OR
|
|
32
|
+
whose declaration is missing any required projection field produces a
|
|
33
|
+
finding.
|
|
34
|
+
|
|
35
|
+
Pre-materialization tolerance. Some harness directories may not yet exist
|
|
36
|
+
on disk in early repository states. The validator is absence-tolerant: when zero harness
|
|
37
|
+
directories are present, it exits 0 with an informational
|
|
38
|
+
``harnesses_not_yet_materialized`` message so the gate does not block
|
|
39
|
+
the early absence-tolerant state. Once at least one harness directory exists, the
|
|
40
|
+
validator enforces the discipline on every present harness.
|
|
41
|
+
|
|
42
|
+
Exit semantics. Exits 0 when every present harness declares a complete
|
|
43
|
+
capability matrix (or when zero harness directories exist). Exits 2 on
|
|
44
|
+
any present harness lacking the declaration or missing any required
|
|
45
|
+
field. The exit-2 convention matches the conformity-gate orchestrator's
|
|
46
|
+
``EXIT_FAIL`` constant.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from __future__ import annotations
|
|
50
|
+
|
|
51
|
+
import json
|
|
52
|
+
import sys
|
|
53
|
+
from dataclasses import asdict, dataclass, field
|
|
54
|
+
from pathlib import Path
|
|
55
|
+
from typing import Final
|
|
56
|
+
|
|
57
|
+
import yaml
|
|
58
|
+
|
|
59
|
+
GREP_NAME: Final[str] = "agent-capability-grep"
|
|
60
|
+
RULE_ANCHOR: Final[str] = "agent-capability-discipline (per-harness capability matrix)"
|
|
61
|
+
|
|
62
|
+
EXIT_PASS: Final[int] = 0
|
|
63
|
+
EXIT_FAIL: Final[int] = 2
|
|
64
|
+
|
|
65
|
+
# The 17-harness cohort. Each entry is the directory name (package key)
|
|
66
|
+
# under src/apothem/harnesses/. The cohort is derived from the registry's
|
|
67
|
+
# SUPPORTED_PACKAGE_KEYS so a newly-registered adapter (e.g. codebuddy,
|
|
68
|
+
# kiro, trae, zed) is validated without editing this tuple. When the
|
|
69
|
+
# registry cannot be imported (an unusual mount layout the standalone
|
|
70
|
+
# subprocess cannot reach), the validator falls back to the static cohort
|
|
71
|
+
# so it never silently shrinks its sweep below the known full set.
|
|
72
|
+
_FALLBACK_HARNESS_COHORT: Final[tuple[str, ...]] = (
|
|
73
|
+
"antigravity",
|
|
74
|
+
"claude_code",
|
|
75
|
+
"codex",
|
|
76
|
+
"cursor",
|
|
77
|
+
"gemini_cli",
|
|
78
|
+
"github_copilot",
|
|
79
|
+
"hermes",
|
|
80
|
+
"kimi_code",
|
|
81
|
+
"open_claw",
|
|
82
|
+
"opencode",
|
|
83
|
+
"qwen_code",
|
|
84
|
+
"windsurf",
|
|
85
|
+
"codebuddy",
|
|
86
|
+
"kiro",
|
|
87
|
+
"trae",
|
|
88
|
+
"zed",
|
|
89
|
+
"glm",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _resolve_cohort() -> tuple[str, ...]:
|
|
94
|
+
"""Return the harness package-key cohort, derived from the registry.
|
|
95
|
+
|
|
96
|
+
Imports ``SUPPORTED_PACKAGE_KEYS`` from the harness registry so the
|
|
97
|
+
cohort tracks the registered adapter set automatically. Falls back to
|
|
98
|
+
the static full cohort if the import fails.
|
|
99
|
+
"""
|
|
100
|
+
try:
|
|
101
|
+
from apothem.lib.harness_registry import SUPPORTED_PACKAGE_KEYS
|
|
102
|
+
except Exception: # import boundary: fall back to the static cohort
|
|
103
|
+
return _FALLBACK_HARNESS_COHORT
|
|
104
|
+
return tuple(SUPPORTED_PACKAGE_KEYS)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
HARNESS_COHORT: Final[tuple[str, ...]] = _resolve_cohort()
|
|
108
|
+
|
|
109
|
+
# The required capability-matrix fields for the installed projection.
|
|
110
|
+
REQUIRED_FIELDS: Final[tuple[str, ...]] = (
|
|
111
|
+
"mcp_servers",
|
|
112
|
+
"sub_agent_dispatch",
|
|
113
|
+
"custom_command_support",
|
|
114
|
+
"recommended_postfix_rendering",
|
|
115
|
+
"long_context_compaction",
|
|
116
|
+
"context_ignore_surface",
|
|
117
|
+
"layered_context_surface",
|
|
118
|
+
"lsp_symbol_navigation",
|
|
119
|
+
"hook_learning_capture",
|
|
120
|
+
"standard_convention_pin",
|
|
121
|
+
"tool_surface_restrictions",
|
|
122
|
+
"system_prompt_template_path",
|
|
123
|
+
"agent_memory_surface",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Declaration filenames the validator probes per harness, in priority order.
|
|
127
|
+
DECLARATION_FILENAMES: Final[tuple[str, ...]] = (
|
|
128
|
+
"capabilities.yml",
|
|
129
|
+
"capabilities.yaml",
|
|
130
|
+
"agent_capabilities.md",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass(frozen=True)
|
|
135
|
+
class Finding:
|
|
136
|
+
"""One harness lacking a complete capability matrix."""
|
|
137
|
+
|
|
138
|
+
harness: str
|
|
139
|
+
detail: str
|
|
140
|
+
missing_fields: list[str] = field(default_factory=list)
|
|
141
|
+
rule: str = RULE_ANCHOR
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass(frozen=True)
|
|
145
|
+
class GrepResult:
|
|
146
|
+
"""Aggregated walk result for a single cohort sweep."""
|
|
147
|
+
|
|
148
|
+
grep: str
|
|
149
|
+
root: str
|
|
150
|
+
harnesses_present: int
|
|
151
|
+
harnesses_total: int
|
|
152
|
+
passed: bool
|
|
153
|
+
informational: str | None = None
|
|
154
|
+
findings: list[Finding] = field(default_factory=list)
|
|
155
|
+
|
|
156
|
+
def to_json(self) -> str:
|
|
157
|
+
payload = {
|
|
158
|
+
"grep": self.grep,
|
|
159
|
+
"root": self.root,
|
|
160
|
+
"harnesses_present": self.harnesses_present,
|
|
161
|
+
"harnesses_total": self.harnesses_total,
|
|
162
|
+
"passed": self.passed,
|
|
163
|
+
"informational": self.informational,
|
|
164
|
+
"findings": [asdict(f) for f in self.findings],
|
|
165
|
+
}
|
|
166
|
+
return json.dumps(payload, indent=2)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _harnesses_dir(root: Path) -> Path:
|
|
170
|
+
return root / "src" / "apothem" / "harnesses"
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _find_declaration(harness_dir: Path) -> Path | None:
|
|
174
|
+
"""Probe the harness directory tree for a declaration file.
|
|
175
|
+
|
|
176
|
+
Looks at the harness root and at ``templates/`` inside it (the
|
|
177
|
+
rule allows either location). Returns the first match in
|
|
178
|
+
``DECLARATION_FILENAMES`` priority order, or None when absent.
|
|
179
|
+
"""
|
|
180
|
+
candidate_dirs = (harness_dir, harness_dir / "templates")
|
|
181
|
+
for directory in candidate_dirs:
|
|
182
|
+
for filename in DECLARATION_FILENAMES:
|
|
183
|
+
candidate = directory / filename
|
|
184
|
+
if candidate.is_file():
|
|
185
|
+
return candidate
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _parse_yaml_declaration(path: Path) -> dict[str, object]:
|
|
190
|
+
"""Load a YAML declaration into a dict. Empty or non-mapping → {}."""
|
|
191
|
+
try:
|
|
192
|
+
raw = path.read_text(encoding="utf-8")
|
|
193
|
+
except OSError:
|
|
194
|
+
return {}
|
|
195
|
+
try:
|
|
196
|
+
loaded = yaml.safe_load(raw)
|
|
197
|
+
except yaml.YAMLError:
|
|
198
|
+
return {}
|
|
199
|
+
if isinstance(loaded, dict):
|
|
200
|
+
return loaded
|
|
201
|
+
return {}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _parse_markdown_declaration(path: Path) -> dict[str, object]:
|
|
205
|
+
"""Scan a Markdown declaration for ``- field_name:`` field markers.
|
|
206
|
+
|
|
207
|
+
The Markdown form admits any prose around the field markers; this
|
|
208
|
+
parser is presence-only — it records each required field's
|
|
209
|
+
presence (mapping to a placeholder True value) without inspecting
|
|
210
|
+
the field's substantive value. The YAML form is the rigorous
|
|
211
|
+
surface; the Markdown form is the lightweight alternative.
|
|
212
|
+
"""
|
|
213
|
+
try:
|
|
214
|
+
text = path.read_text(encoding="utf-8")
|
|
215
|
+
except OSError:
|
|
216
|
+
return {}
|
|
217
|
+
found: dict[str, object] = {}
|
|
218
|
+
for line in text.splitlines():
|
|
219
|
+
stripped = line.strip()
|
|
220
|
+
for field_name in REQUIRED_FIELDS:
|
|
221
|
+
# Accept `- field_name:` or `field_name:` at line start.
|
|
222
|
+
if stripped.startswith(f"- {field_name}:") or stripped.startswith(
|
|
223
|
+
f"{field_name}:"
|
|
224
|
+
):
|
|
225
|
+
found[field_name] = True
|
|
226
|
+
return found
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _missing_fields(declaration: dict[str, object]) -> list[str]:
|
|
230
|
+
return [f for f in REQUIRED_FIELDS if f not in declaration]
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def check(root: Path) -> GrepResult:
|
|
234
|
+
"""Walk the harness cohort under root; flag incomplete declarations."""
|
|
235
|
+
harnesses_dir = _harnesses_dir(root)
|
|
236
|
+
findings: list[Finding] = []
|
|
237
|
+
present_count = 0
|
|
238
|
+
for harness in HARNESS_COHORT:
|
|
239
|
+
harness_dir = harnesses_dir / harness
|
|
240
|
+
if not harness_dir.is_dir():
|
|
241
|
+
continue
|
|
242
|
+
present_count += 1
|
|
243
|
+
declaration_path = _find_declaration(harness_dir)
|
|
244
|
+
if declaration_path is None:
|
|
245
|
+
findings.append(
|
|
246
|
+
Finding(
|
|
247
|
+
harness=harness,
|
|
248
|
+
detail=(
|
|
249
|
+
"no capability declaration found; expected one of "
|
|
250
|
+
f"{list(DECLARATION_FILENAMES)} under {harness_dir} "
|
|
251
|
+
"or its templates/ subdirectory"
|
|
252
|
+
),
|
|
253
|
+
missing_fields=list(REQUIRED_FIELDS),
|
|
254
|
+
)
|
|
255
|
+
)
|
|
256
|
+
continue
|
|
257
|
+
if declaration_path.suffix in {".yml", ".yaml"}:
|
|
258
|
+
declaration = _parse_yaml_declaration(declaration_path)
|
|
259
|
+
else:
|
|
260
|
+
declaration = _parse_markdown_declaration(declaration_path)
|
|
261
|
+
missing = _missing_fields(declaration)
|
|
262
|
+
if missing:
|
|
263
|
+
findings.append(
|
|
264
|
+
Finding(
|
|
265
|
+
harness=harness,
|
|
266
|
+
detail=(
|
|
267
|
+
f"declaration at {declaration_path} is missing "
|
|
268
|
+
f"{len(missing)} of {len(REQUIRED_FIELDS)} required "
|
|
269
|
+
"capability-matrix fields"
|
|
270
|
+
),
|
|
271
|
+
missing_fields=missing,
|
|
272
|
+
)
|
|
273
|
+
)
|
|
274
|
+
informational: str | None = None
|
|
275
|
+
if present_count == 0:
|
|
276
|
+
informational = (
|
|
277
|
+
"harnesses_not_yet_materialized: zero of "
|
|
278
|
+
f"{len(HARNESS_COHORT)} harness directories present under "
|
|
279
|
+
f"{harnesses_dir}; validator is in an absence-tolerant pass"
|
|
280
|
+
)
|
|
281
|
+
return GrepResult(
|
|
282
|
+
grep=GREP_NAME,
|
|
283
|
+
root=str(root),
|
|
284
|
+
harnesses_present=present_count,
|
|
285
|
+
harnesses_total=len(HARNESS_COHORT),
|
|
286
|
+
passed=not findings,
|
|
287
|
+
informational=informational,
|
|
288
|
+
findings=findings,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _read_input(argv: list[str]) -> Path:
|
|
293
|
+
if len(argv) >= 2:
|
|
294
|
+
return Path(argv[1])
|
|
295
|
+
return Path.cwd()
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _main(argv: list[str]) -> int:
|
|
299
|
+
root = _read_input(argv)
|
|
300
|
+
result = check(root)
|
|
301
|
+
print(result.to_json())
|
|
302
|
+
return EXIT_PASS if result.passed else EXIT_FAIL
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
if __name__ == "__main__":
|
|
306
|
+
sys.exit(_main(sys.argv))
|