@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,154 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Flag diagrams whose verification date is missing or stale.
|
|
4
|
+
|
|
5
|
+
Why this enforcement exists. The visual-leverage rule M9 declares that
|
|
6
|
+
every diagram in a structural artifact carries a `%% verified: YYYY-MM-DD %%`
|
|
7
|
+
metadata comment naming the date the diagram was last reconciled with the
|
|
8
|
+
underlying structure. A diagram without the marker, or with a marker more
|
|
9
|
+
than ninety days old, is structurally untrusted — readers cannot tell
|
|
10
|
+
whether the depiction reflects current reality or aspirational state.
|
|
11
|
+
The pre-emission gate's mechanical bar 9 (M9 visual leverage) catches both the missing marker
|
|
12
|
+
and the stale marker so the operator either refreshes the verification
|
|
13
|
+
or marks the diagram aspirational explicitly.
|
|
14
|
+
|
|
15
|
+
Detection strategy. The grep walks every Mermaid fence (between
|
|
16
|
+
` ```mermaid ` openings and the matching ` ``` ` closings) and inspects the
|
|
17
|
+
fence body for a `%% verified: YYYY-MM-DD %%` comment. Two failure modes:
|
|
18
|
+
the marker is absent, or its date is older than the freshness threshold
|
|
19
|
+
named at `STALENESS_THRESHOLD_DAYS`.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import re
|
|
25
|
+
import sys
|
|
26
|
+
from dataclasses import dataclass
|
|
27
|
+
from datetime import date, datetime, timezone
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Final
|
|
30
|
+
|
|
31
|
+
from apothem.conformity._grep_base import GrepResult, run_grep
|
|
32
|
+
|
|
33
|
+
# Mermaid fence opening per the host's discovered Markdown convention. The
|
|
34
|
+
# language tag is `mermaid` for our visual-leverage rule's worked examples.
|
|
35
|
+
MERMAID_OPEN_RE: Final[re.Pattern[str]] = re.compile(r"^```mermaid\s*$")
|
|
36
|
+
FENCE_CLOSE_RE: Final[re.Pattern[str]] = re.compile(r"^```\s*$")
|
|
37
|
+
|
|
38
|
+
# Verified-date marker shape — `%% verified: 2026-04-28 %%`. The trailing
|
|
39
|
+
# `%%` is optional in some Mermaid dialects; we accept either form.
|
|
40
|
+
VERIFIED_DATE_RE: Final[re.Pattern[str]] = re.compile(
|
|
41
|
+
r"%%\s*verified:\s*(\d{4}-\d{2}-\d{2})\s*(?:%%)?"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Freshness threshold per the visual-leverage rule's staleness clause. A
|
|
45
|
+
# diagram older than this is flagged unless the operator has marked it
|
|
46
|
+
# aspirational explicitly. Ninety days matches the rule's recommended
|
|
47
|
+
# refresh cadence for structural artifacts.
|
|
48
|
+
STALENESS_THRESHOLD_DAYS: Final[int] = 90
|
|
49
|
+
|
|
50
|
+
GREP_NAME: Final[str] = "diagram-staleness-grep"
|
|
51
|
+
RULE_ANCHOR: Final[str] = "M9 visual-leverage §Fidelity"
|
|
52
|
+
EXIT_PASS: Final[int] = 0
|
|
53
|
+
EXIT_FAIL: Final[int] = 2
|
|
54
|
+
STDIN_FLAG: Final[str] = "--stdin"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True)
|
|
58
|
+
class Finding:
|
|
59
|
+
"""One stale or missing-verification diagram occurrence."""
|
|
60
|
+
|
|
61
|
+
line: int
|
|
62
|
+
issue: str
|
|
63
|
+
detail: str
|
|
64
|
+
rule: str = RULE_ANCHOR
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _today() -> date:
|
|
68
|
+
"""Return today's UTC date — separated for testability."""
|
|
69
|
+
return datetime.now(tz=timezone.utc).date()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _find_mermaid_fences(lines: list[str]) -> list[tuple[int, int]]:
|
|
73
|
+
"""Locate `(open_line, close_line)` pairs for every Mermaid fence.
|
|
74
|
+
|
|
75
|
+
Lines are 1-indexed in the returned tuples. A fence whose closing
|
|
76
|
+
delimiter is absent (truncated artifact) is omitted.
|
|
77
|
+
"""
|
|
78
|
+
fences: list[tuple[int, int]] = []
|
|
79
|
+
open_line: int | None = None
|
|
80
|
+
for index, line in enumerate(lines, start=1):
|
|
81
|
+
if open_line is None:
|
|
82
|
+
if MERMAID_OPEN_RE.match(line):
|
|
83
|
+
open_line = index
|
|
84
|
+
continue
|
|
85
|
+
if FENCE_CLOSE_RE.match(line):
|
|
86
|
+
fences.append((open_line, index))
|
|
87
|
+
open_line = None
|
|
88
|
+
return fences
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _verified_date(fence_body: list[str]) -> date | None:
|
|
92
|
+
"""Parse the verified-date marker out of a Mermaid fence body."""
|
|
93
|
+
for line in fence_body:
|
|
94
|
+
match = VERIFIED_DATE_RE.search(line)
|
|
95
|
+
if match is None:
|
|
96
|
+
continue
|
|
97
|
+
try:
|
|
98
|
+
return date.fromisoformat(match.group(1))
|
|
99
|
+
except ValueError:
|
|
100
|
+
# The marker present but date unparseable — treated as missing
|
|
101
|
+
# so the operator re-emits the marker in the canonical shape.
|
|
102
|
+
return None
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def check(content: str, path: Path | None = None) -> GrepResult:
|
|
107
|
+
"""Scan content; return a structured result.
|
|
108
|
+
|
|
109
|
+
Pre-conditions: `content` is the artifact body about to be emitted.
|
|
110
|
+
Post-conditions: `result.passed` is True iff every Mermaid fence
|
|
111
|
+
carries a verified-date marker no older than `STALENESS_THRESHOLD_DAYS`.
|
|
112
|
+
"""
|
|
113
|
+
lines = content.splitlines()
|
|
114
|
+
today = _today()
|
|
115
|
+
findings: list[Finding] = []
|
|
116
|
+
for open_line, close_line in _find_mermaid_fences(lines):
|
|
117
|
+
body = lines[open_line : close_line - 1]
|
|
118
|
+
verified = _verified_date(body)
|
|
119
|
+
if verified is None:
|
|
120
|
+
findings.append(
|
|
121
|
+
Finding(
|
|
122
|
+
line=open_line,
|
|
123
|
+
issue="missing verified-date marker",
|
|
124
|
+
detail=(
|
|
125
|
+
"Mermaid fence has no `%% verified: YYYY-MM-DD %%` "
|
|
126
|
+
"comment; structural artifacts require the marker "
|
|
127
|
+
"per the visual-leverage rule."
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
continue
|
|
132
|
+
age_days = (today - verified).days
|
|
133
|
+
if age_days > STALENESS_THRESHOLD_DAYS:
|
|
134
|
+
findings.append(
|
|
135
|
+
Finding(
|
|
136
|
+
line=open_line,
|
|
137
|
+
issue="stale verified-date marker",
|
|
138
|
+
detail=(
|
|
139
|
+
f"Verified {verified.isoformat()} ({age_days} days "
|
|
140
|
+
f"ago); freshness ceiling is "
|
|
141
|
+
f"{STALENESS_THRESHOLD_DAYS} days."
|
|
142
|
+
),
|
|
143
|
+
)
|
|
144
|
+
)
|
|
145
|
+
return GrepResult(
|
|
146
|
+
grep=GREP_NAME,
|
|
147
|
+
path=str(path) if path is not None else None,
|
|
148
|
+
passed=not findings,
|
|
149
|
+
findings=findings,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == "__main__":
|
|
154
|
+
sys.exit(run_grep(check, sys.argv))
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Flag static-string version embeds in dynamism-required surfaces.
|
|
4
|
+
|
|
5
|
+
Why this enforcement exists. The dynamism rule and the spec section 3.2.c
|
|
6
|
+
dynamism SLOs require that surfaces presented to operators — README
|
|
7
|
+
badges, documentation site pages, install/landing guides — resolve their
|
|
8
|
+
version strings through a single canonical source: ``pyproject.toml`` is
|
|
9
|
+
the manifest authority, surfaced at runtime through ``apothem.__version__``
|
|
10
|
+
and resolved publicly through GitHub Releases and the npm registry. When
|
|
11
|
+
a literal semver such as ``1.2.3`` or
|
|
12
|
+
``v1.2.3`` is hard-coded into a README badge URL or a documentation
|
|
13
|
+
page, the artifact drifts the moment the canonical version increments —
|
|
14
|
+
the badge shows yesterday's release, the docs claim a version the
|
|
15
|
+
codebase has surpassed, and the operator-facing surface tells two
|
|
16
|
+
incompatible truths.
|
|
17
|
+
|
|
18
|
+
Surfaces in scope. The validator walks the repository root and inspects
|
|
19
|
+
``README.md`` (top-level only — sub-tree READMEs follow their own
|
|
20
|
+
discipline) and every Markdown / MDX page under
|
|
21
|
+
``site/content/docs/``. Surfaces explicitly
|
|
22
|
+
out of scope: ``CHANGELOG.md`` and the documentation blog — the blog
|
|
23
|
+
exclusion is locale-aware, covering both the English-root blog at
|
|
24
|
+
``site/content/docs/blog/`` and every locale mirror at
|
|
25
|
+
``site/content/docs/<locale>/blog/`` (all record historical releases by
|
|
26
|
+
literal version, like dated release-announcement posts) — ``pyproject.toml``
|
|
27
|
+
(the canonical source-of-truth this rule defers to), generated reference
|
|
28
|
+
inventory blocks, the ``_spec/`` and ``.plans/`` trees (specification +
|
|
29
|
+
planning ephemera carry release identifiers in literal form), the
|
|
30
|
+
``tests/`` tree (fixtures must use literal versions to assert behaviour),
|
|
31
|
+
and ``*.py`` files outside docs (source modules consume ``__version__``
|
|
32
|
+
dynamically).
|
|
33
|
+
|
|
34
|
+
Detection strategy. The validator scans each in-scope file line by line
|
|
35
|
+
for the semver regex ``\\bv?\\d+\\.\\d+\\.\\d+\\b``. Hits inside fenced
|
|
36
|
+
code blocks are reported regardless — README install commands and docs
|
|
37
|
+
examples typically substitute via Jinja/templating and a literal version
|
|
38
|
+
there is still drift-prone. The operator triages each hit on one of two
|
|
39
|
+
paths: replace the literal with a dynamic substitution (e.g.,
|
|
40
|
+
site-build metadata, ``__version__`` for runtime
|
|
41
|
+
contexts, a shields.io endpoint badge that resolves from the npm
|
|
42
|
+
registry or GitHub Releases), or
|
|
43
|
+
demonstrate the literal is intentional and out-of-scope (a quoted
|
|
44
|
+
example of someone else's release, a historical reference) and migrate
|
|
45
|
+
the file out of the in-scope set.
|
|
46
|
+
|
|
47
|
+
Exit semantics. Exits 0 when no findings; exits 2 on any finding. The
|
|
48
|
+
exit-2 convention matches the conformity-gate orchestrator's EXIT_FAIL
|
|
49
|
+
constant.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from __future__ import annotations
|
|
53
|
+
|
|
54
|
+
import json
|
|
55
|
+
import re
|
|
56
|
+
import sys
|
|
57
|
+
from dataclasses import asdict, dataclass, field
|
|
58
|
+
from pathlib import Path
|
|
59
|
+
from typing import Final
|
|
60
|
+
|
|
61
|
+
GREP_NAME: Final[str] = "dynamism-grep"
|
|
62
|
+
RULE_ANCHOR: Final[str] = "rules/dynamism.md (static-version embeds)"
|
|
63
|
+
|
|
64
|
+
EXIT_PASS: Final[int] = 0
|
|
65
|
+
EXIT_FAIL: Final[int] = 2
|
|
66
|
+
|
|
67
|
+
# Semver-shaped match: optional leading 'v', three numeric segments
|
|
68
|
+
# separated by dots, word boundaries on both ends. Catches `1.0.0`,
|
|
69
|
+
# `v1.2.3`, and the `version = "0.X.Y"` pin pattern (the literal version
|
|
70
|
+
# string inside the quoted value matches independently).
|
|
71
|
+
_SEMVER_RE: Final[re.Pattern[str]] = re.compile(r"\bv?\d+\.\d+\.\d+\b")
|
|
72
|
+
|
|
73
|
+
# Path segments that exclude a file from the in-scope sweep. The matcher
|
|
74
|
+
# walks every Markdown file under the root and tests its parts against
|
|
75
|
+
# this set; any segment match short-circuits the file as out-of-scope.
|
|
76
|
+
_EXCLUDED_PATH_SEGMENTS: Final[frozenset[str]] = frozenset(
|
|
77
|
+
{
|
|
78
|
+
"_spec",
|
|
79
|
+
".plans",
|
|
80
|
+
"tests",
|
|
81
|
+
"node_modules",
|
|
82
|
+
".venv",
|
|
83
|
+
"venv",
|
|
84
|
+
".git",
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Filenames that are out-of-scope even when located inside an otherwise
|
|
89
|
+
# in-scope directory. CHANGELOG.md records literal release-history
|
|
90
|
+
# release versions; pyproject.toml is the canonical version source; the
|
|
91
|
+
# vendoring-strategy doc's dependency-pin table mirrors those canonical
|
|
92
|
+
# dependency pins (literal requirement facts, not a displayed version
|
|
93
|
+
# surface that goes stale).
|
|
94
|
+
_EXCLUDED_FILENAMES: Final[frozenset[str]] = frozenset(
|
|
95
|
+
{
|
|
96
|
+
"CHANGELOG.md",
|
|
97
|
+
"pyproject.toml",
|
|
98
|
+
"vendoring-strategy.md",
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
DOCS_PATH_PARTS: Final[tuple[str, ...]] = ("site", "content", "docs")
|
|
103
|
+
DOCS_SUFFIXES: Final[frozenset[str]] = frozenset({".md", ".mdx"})
|
|
104
|
+
# Docs-relative directory segments that exclude a page from the in-scope
|
|
105
|
+
# sweep. The exclusion is locale-aware: a ``blog`` segment anywhere below
|
|
106
|
+
# ``site/content/docs/`` is out of scope, covering both the English-root blog
|
|
107
|
+
# (``site/content/docs/blog/...``) and every locale mirror
|
|
108
|
+
# (``site/content/docs/<locale>/blog/...``). The blog records historical
|
|
109
|
+
# releases by literal version (dated release-announcement posts), exactly as
|
|
110
|
+
# the ``CHANGELOG.md`` exclusion above does.
|
|
111
|
+
_EXCLUDED_DOCS_SUBTREE_SEGMENTS: Final[frozenset[str]] = frozenset({"blog"})
|
|
112
|
+
# Documentation pages carry these region markers in the comment syntax of the
|
|
113
|
+
# host docs framework: the HTML-comment form (``<!-- ... -->``) for Markdown
|
|
114
|
+
# pages and the JSX-comment form (``{/* ... */}``) for MDX pages. Both forms are
|
|
115
|
+
# recognized so the exclusion regions fire regardless of the page's extension.
|
|
116
|
+
_GENERATED_REFERENCE_START: Final[frozenset[str]] = frozenset(
|
|
117
|
+
{
|
|
118
|
+
"<!-- apothem:generated-reference:start -->",
|
|
119
|
+
"{/* apothem:generated-reference:start */}",
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
_GENERATED_REFERENCE_END: Final[frozenset[str]] = frozenset(
|
|
123
|
+
{
|
|
124
|
+
"<!-- apothem:generated-reference:end -->",
|
|
125
|
+
"{/* apothem:generated-reference:end */}",
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
# The changelog page injects the root ``CHANGELOG.md`` body between these
|
|
129
|
+
# markers at build time. That body is literal release-history (the same
|
|
130
|
+
# content the root ``CHANGELOG.md`` exclusion above already covers), not a
|
|
131
|
+
# displayed version surface that goes stale, so its version strings are
|
|
132
|
+
# skipped exactly as the generated-reference block is.
|
|
133
|
+
_CHANGELOG_START: Final[frozenset[str]] = frozenset(
|
|
134
|
+
{
|
|
135
|
+
"<!-- apothem:changelog:start -->",
|
|
136
|
+
"{/* apothem:changelog:start */}",
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
_CHANGELOG_END: Final[frozenset[str]] = frozenset(
|
|
140
|
+
{
|
|
141
|
+
"<!-- apothem:changelog:end -->",
|
|
142
|
+
"{/* apothem:changelog:end */}",
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@dataclass(frozen=True)
|
|
148
|
+
class Finding:
|
|
149
|
+
"""One literal semver embed in an in-scope surface."""
|
|
150
|
+
|
|
151
|
+
path: str
|
|
152
|
+
line: int
|
|
153
|
+
match: str
|
|
154
|
+
context: str
|
|
155
|
+
rule: str = RULE_ANCHOR
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass(frozen=True)
|
|
159
|
+
class GrepResult:
|
|
160
|
+
"""Aggregated walk result for a single dynamism sweep."""
|
|
161
|
+
|
|
162
|
+
grep: str
|
|
163
|
+
root: str
|
|
164
|
+
scanned_count: int
|
|
165
|
+
passed: bool
|
|
166
|
+
findings: list[Finding] = field(default_factory=list)
|
|
167
|
+
|
|
168
|
+
def to_json(self) -> str:
|
|
169
|
+
payload = {
|
|
170
|
+
"grep": self.grep,
|
|
171
|
+
"root": self.root,
|
|
172
|
+
"scanned_count": self.scanned_count,
|
|
173
|
+
"passed": self.passed,
|
|
174
|
+
"findings": [asdict(f) for f in self.findings],
|
|
175
|
+
}
|
|
176
|
+
return json.dumps(payload, indent=2)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _is_in_scope(path: Path, root: Path) -> bool:
|
|
180
|
+
"""Return True iff *path* is a dynamism-bound surface under *root*.
|
|
181
|
+
|
|
182
|
+
In-scope: top-level ``README.md`` and every ``*.md`` / ``*.mdx`` under
|
|
183
|
+
``site/content/docs/``.
|
|
184
|
+
Out-of-scope: everything excluded by ``_EXCLUDED_PATH_SEGMENTS`` or
|
|
185
|
+
``_EXCLUDED_FILENAMES``.
|
|
186
|
+
"""
|
|
187
|
+
if path.name in _EXCLUDED_FILENAMES:
|
|
188
|
+
return False
|
|
189
|
+
try:
|
|
190
|
+
relative = path.relative_to(root)
|
|
191
|
+
except ValueError:
|
|
192
|
+
return False
|
|
193
|
+
parts = relative.parts
|
|
194
|
+
if any(segment in _EXCLUDED_PATH_SEGMENTS for segment in parts):
|
|
195
|
+
return False
|
|
196
|
+
if relative == Path("README.md"):
|
|
197
|
+
return True
|
|
198
|
+
under_docs = (
|
|
199
|
+
parts[: len(DOCS_PATH_PARTS)] == DOCS_PATH_PARTS
|
|
200
|
+
and path.suffix in DOCS_SUFFIXES
|
|
201
|
+
)
|
|
202
|
+
if not under_docs:
|
|
203
|
+
return False
|
|
204
|
+
# Locale-aware blog exclusion: a ``blog`` segment anywhere below
|
|
205
|
+
# ``site/content/docs/`` is out of scope, covering both the English-root
|
|
206
|
+
# blog and every ``site/content/docs/<locale>/blog/`` mirror.
|
|
207
|
+
docs_relative_parts = parts[len(DOCS_PATH_PARTS) :]
|
|
208
|
+
return not any(
|
|
209
|
+
segment in _EXCLUDED_DOCS_SUBTREE_SEGMENTS for segment in docs_relative_parts
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _scan_file(path: Path) -> list[Finding]:
|
|
214
|
+
"""Return every literal semver embed in *path*."""
|
|
215
|
+
findings: list[Finding] = []
|
|
216
|
+
try:
|
|
217
|
+
text = path.read_text(encoding="utf-8")
|
|
218
|
+
except (OSError, UnicodeDecodeError):
|
|
219
|
+
return findings
|
|
220
|
+
inside_generated_reference = False
|
|
221
|
+
inside_changelog = False
|
|
222
|
+
for line_index, line in enumerate(text.splitlines(), start=1):
|
|
223
|
+
if line.strip() in _GENERATED_REFERENCE_START:
|
|
224
|
+
inside_generated_reference = True
|
|
225
|
+
continue
|
|
226
|
+
if line.strip() in _GENERATED_REFERENCE_END:
|
|
227
|
+
inside_generated_reference = False
|
|
228
|
+
continue
|
|
229
|
+
if line.strip() in _CHANGELOG_START:
|
|
230
|
+
inside_changelog = True
|
|
231
|
+
continue
|
|
232
|
+
if line.strip() in _CHANGELOG_END:
|
|
233
|
+
inside_changelog = False
|
|
234
|
+
continue
|
|
235
|
+
if inside_generated_reference or inside_changelog:
|
|
236
|
+
continue
|
|
237
|
+
for match in _SEMVER_RE.finditer(line):
|
|
238
|
+
findings.append(
|
|
239
|
+
Finding(
|
|
240
|
+
path=str(path),
|
|
241
|
+
line=line_index,
|
|
242
|
+
match=match.group(),
|
|
243
|
+
context=line.strip(),
|
|
244
|
+
)
|
|
245
|
+
)
|
|
246
|
+
return findings
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def check(root: Path) -> GrepResult:
|
|
250
|
+
"""Walk *root* for in-scope surfaces; flag every literal semver."""
|
|
251
|
+
findings: list[Finding] = []
|
|
252
|
+
scanned = 0
|
|
253
|
+
candidates = sorted(p for suffix in DOCS_SUFFIXES for p in root.rglob(f"*{suffix}"))
|
|
254
|
+
for candidate in candidates:
|
|
255
|
+
if not candidate.is_file():
|
|
256
|
+
continue
|
|
257
|
+
if not _is_in_scope(candidate, root):
|
|
258
|
+
continue
|
|
259
|
+
scanned += 1
|
|
260
|
+
findings.extend(_scan_file(candidate))
|
|
261
|
+
return GrepResult(
|
|
262
|
+
grep=GREP_NAME,
|
|
263
|
+
root=str(root),
|
|
264
|
+
scanned_count=scanned,
|
|
265
|
+
passed=not findings,
|
|
266
|
+
findings=findings,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def _read_input(argv: list[str]) -> Path:
|
|
271
|
+
if len(argv) >= 2:
|
|
272
|
+
return Path(argv[1])
|
|
273
|
+
return Path.cwd()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def main(root: Path) -> int:
|
|
277
|
+
"""Entry point: scan *root*, print JSON report, return exit code."""
|
|
278
|
+
result = check(root)
|
|
279
|
+
print(result.to_json())
|
|
280
|
+
return EXIT_PASS if result.passed else EXIT_FAIL
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
if __name__ == "__main__":
|
|
284
|
+
sys.exit(main(_read_input(sys.argv)))
|