@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,272 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Flag brand-mark display/identifier form drift on brand-touched surfaces.
|
|
4
|
+
|
|
5
|
+
Why this enforcement exists. The brand-mark convention sub-mandate (the
|
|
6
|
+
display brand ``Apothem`` PascalCase versus the identifier
|
|
7
|
+
``apothem`` lowercase) carries a per-surface canonical form: human-
|
|
8
|
+
readable display surfaces render PascalCase; machine-resolved identifier
|
|
9
|
+
surfaces honor ecosystem-normalized lowercase (PEP-503, URL conventions,
|
|
10
|
+
package-manager naming). A wordmark spelled lowercase on a display
|
|
11
|
+
surface, or a Python distribution name spelled PascalCase, is drift the
|
|
12
|
+
M9 visual leverage + M14 sibling convergence + M3 ten-dimension
|
|
13
|
+
consistency bars catch at the pre-emission gate.
|
|
14
|
+
|
|
15
|
+
Detection strategy. Per-line scan over the brand-touched glob set. Each
|
|
16
|
+
occurrence of ``\\b(apothem|Apothem)\\b`` is classified against two
|
|
17
|
+
high-confidence pattern sets: an identifier-context set (URL paths,
|
|
18
|
+
package-manager install commands, environment variables, file basenames,
|
|
19
|
+
Python imports, suite folder, repo path) and a display-context set
|
|
20
|
+
(Markdown H1 with brand-name, site-title metadata, frontmatter title:,
|
|
21
|
+
alt-text, OG/Twitter meta-title, SVG title/desc). Drift findings emit
|
|
22
|
+
only when the classification is high-confidence: PascalCase form on an
|
|
23
|
+
identifier-context line, or lowercase form on a display-context line.
|
|
24
|
+
Unclassified occurrences pass; the unclassified occurrences are cataloged in the operator's normalization review pass.
|
|
25
|
+
|
|
26
|
+
Path filter. The matcher early-exits on out-of-scope paths so tooling,
|
|
27
|
+
tests, rules, hooks, plan-suite scratch, and the ecosystem's own
|
|
28
|
+
internal Markdown corpus are not inspected. In-scope paths are the
|
|
29
|
+
brand-touched globs enumerated at ``IN_SCOPE_PREFIXES`` and
|
|
30
|
+
``IN_SCOPE_FILENAMES``.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import re
|
|
36
|
+
import sys
|
|
37
|
+
from dataclasses import dataclass
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
from typing import Final
|
|
40
|
+
|
|
41
|
+
from apothem.conformity._grep_base import GrepResult, run_grep
|
|
42
|
+
|
|
43
|
+
# Brand-mark occurrence regex. Word-boundary anchors prevent partial
|
|
44
|
+
# matches inside identifiers like ``ahmed-g-gad/apothem-internals`` (which
|
|
45
|
+
# remains a single match starting at the canonical token).
|
|
46
|
+
BRAND_RE: Final[re.Pattern[str]] = re.compile(r"\b(apothem|Apothem)\b")
|
|
47
|
+
|
|
48
|
+
# Identifier-context line patterns. When a line matches one of these,
|
|
49
|
+
# the canonical form on that line is lowercase ``apothem``. A
|
|
50
|
+
# PascalCase ``Apothem`` occurrence on such a line is identifier-on-
|
|
51
|
+
# display-surface drift.
|
|
52
|
+
IDENTIFIER_CONTEXT_PATTERNS: Final[tuple[re.Pattern[str], ...]] = tuple(
|
|
53
|
+
re.compile(pat, re.IGNORECASE)
|
|
54
|
+
for pat in (
|
|
55
|
+
# URL paths
|
|
56
|
+
r"github\.com/[\w-]+/apothem",
|
|
57
|
+
r"apothem\.ahmedgad\.com",
|
|
58
|
+
r"pypi\.org/project/apothem",
|
|
59
|
+
# Package-manager install commands
|
|
60
|
+
r"\bpip\s+install\s+\S*apothem",
|
|
61
|
+
r"\bbrew\s+install\s+\S*apothem",
|
|
62
|
+
r"\bscoop\s+install\s+\S*apothem",
|
|
63
|
+
r"\bwinget\s+install\s+\S*apothem",
|
|
64
|
+
r"\bpacman\s+-S\s+\S*apothem",
|
|
65
|
+
r"\b(apt|dnf|yum)\s+install\s+\S*apothem",
|
|
66
|
+
# CLI invocations
|
|
67
|
+
r"\$\s*apothem\b",
|
|
68
|
+
r"\bapothem\s+--",
|
|
69
|
+
# Python module references
|
|
70
|
+
r"\bimport\s+apothem\b",
|
|
71
|
+
r"\bfrom\s+apothem\b",
|
|
72
|
+
# Versioned/typed file basenames
|
|
73
|
+
r"\bapothem-v?\d",
|
|
74
|
+
r"\bapothem[_.]\d",
|
|
75
|
+
r"\bapothem\.(rb|json|ya?ml|toml|spec|whl|tar|deb|rpm)\b",
|
|
76
|
+
# Env-var prefix (upper-snake identifier form)
|
|
77
|
+
r"\bAPOTHEM_\w+",
|
|
78
|
+
# Suite folder path
|
|
79
|
+
r"/.plans/[\w-]*apothem",
|
|
80
|
+
# Repo path under owner
|
|
81
|
+
r"\bahmed-g-gad/[\w-]*apothem",
|
|
82
|
+
# PEP-621 distribution name field
|
|
83
|
+
r'^\s*name\s*=\s*"apothem"',
|
|
84
|
+
# Homebrew formula filename
|
|
85
|
+
r"/Formula/apothem",
|
|
86
|
+
# Scoop manifest filename
|
|
87
|
+
r"/bucket/apothem\.json",
|
|
88
|
+
# Winget package-identifier segment
|
|
89
|
+
r"ahmed-g-gad\.apothem",
|
|
90
|
+
# PKGBUILD pkgname
|
|
91
|
+
r"\bpkgname=apothem",
|
|
92
|
+
# Docker image
|
|
93
|
+
r"\bahmed-g-gad/apothem",
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Display-context line patterns. When a line matches one of these, the
|
|
98
|
+
# canonical form on that line is PascalCase ``Apothem``. A lowercase
|
|
99
|
+
# ``apothem`` occurrence on such a line (outside URL/identifier sub-
|
|
100
|
+
# expressions also on the line) is display-form drift.
|
|
101
|
+
DISPLAY_CONTEXT_PATTERNS: Final[tuple[re.Pattern[str], ...]] = tuple(
|
|
102
|
+
re.compile(pat)
|
|
103
|
+
for pat in (
|
|
104
|
+
# Markdown H1/H2 referencing the brand
|
|
105
|
+
r"^#{1,6}\s+.*(?:Apothem|apothem)",
|
|
106
|
+
# Site metadata fields
|
|
107
|
+
r"^\s*site_name\s*:",
|
|
108
|
+
r"^\s*site_description\s*:",
|
|
109
|
+
# YAML frontmatter title field
|
|
110
|
+
r'^\s*title\s*:\s*["\']?(?:Apothem|apothem)',
|
|
111
|
+
# alt-text attribute
|
|
112
|
+
r'\balt\s*=\s*["\'][^"\']*(?:Apothem|apothem)',
|
|
113
|
+
# SVG accessibility elements
|
|
114
|
+
r"<(?:title|desc|text)[^>]*>(?:Apothem|apothem)",
|
|
115
|
+
# OG / Twitter meta tags
|
|
116
|
+
r"\b(?:og:title|og:site_name|twitter:title|twitter:image:alt)\b",
|
|
117
|
+
# JSON-LD name field
|
|
118
|
+
r'"name"\s*:\s*"(?:Apothem|apothem)"',
|
|
119
|
+
# CLI banner H1 wording
|
|
120
|
+
r"\bApothem\s+v\d",
|
|
121
|
+
# Homebrew formula desc field
|
|
122
|
+
r'^\s*desc\s+"',
|
|
123
|
+
# PEP-621 description field
|
|
124
|
+
r'^\s*description\s*=\s*"',
|
|
125
|
+
# AUR pkgdesc / .deb Description / .rpm Summary
|
|
126
|
+
r"^\s*pkgdesc\s*=",
|
|
127
|
+
r"^\s*Description\s*:",
|
|
128
|
+
r"^\s*Summary\s*:",
|
|
129
|
+
# Winget ShortDescription / Description
|
|
130
|
+
r"^\s*(?:ShortDescription|Description|PackageName)\s*:",
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# In-scope path prefixes (relative to project root). The matcher's
|
|
135
|
+
# classification only fires when the inspected path starts with one of
|
|
136
|
+
# these or matches one of the IN_SCOPE_FILENAMES bare basenames.
|
|
137
|
+
IN_SCOPE_PREFIXES: Final[tuple[str, ...]] = (
|
|
138
|
+
"site/",
|
|
139
|
+
"assets/",
|
|
140
|
+
".github/",
|
|
141
|
+
"bin/",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# In-scope bare filenames (root-level singletons).
|
|
145
|
+
IN_SCOPE_FILENAMES: Final[frozenset[str]] = frozenset(
|
|
146
|
+
{
|
|
147
|
+
"README.md",
|
|
148
|
+
"CHANGELOG.md",
|
|
149
|
+
"SUPPORT.md",
|
|
150
|
+
"SECURITY.md",
|
|
151
|
+
"LICENSE",
|
|
152
|
+
"pyproject.toml",
|
|
153
|
+
"scripts/installer/install.sh",
|
|
154
|
+
"scripts/installer/install.ps1",
|
|
155
|
+
"scripts/installer/update.sh",
|
|
156
|
+
"scripts/installer/update.ps1",
|
|
157
|
+
"scripts/installer/uninstall.sh",
|
|
158
|
+
"scripts/installer/uninstall.ps1",
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
GREP_NAME: Final[str] = "brand-mark-grep"
|
|
163
|
+
RULE_ANCHOR: Final[str] = (
|
|
164
|
+
"rules/plain-language.md (brand-mark display/identifier casing)"
|
|
165
|
+
)
|
|
166
|
+
EXIT_PASS: Final[int] = 0
|
|
167
|
+
EXIT_FAIL: Final[int] = 2
|
|
168
|
+
STDIN_FLAG: Final[str] = "--stdin"
|
|
169
|
+
DISPLAY_FORM: Final[str] = "Apothem"
|
|
170
|
+
IDENTIFIER_FORM: Final[str] = "apothem"
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@dataclass(frozen=True)
|
|
174
|
+
class Finding:
|
|
175
|
+
"""One brand-mark form-drift occurrence."""
|
|
176
|
+
|
|
177
|
+
line: int
|
|
178
|
+
match: str
|
|
179
|
+
drift: str # "display-form-on-identifier-surface" | "identifier-form-on-display-surface"
|
|
180
|
+
context: str
|
|
181
|
+
rule: str = RULE_ANCHOR
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _in_scope(path: Path | None) -> bool:
|
|
185
|
+
"""Decide whether the path is a brand-touched surface.
|
|
186
|
+
|
|
187
|
+
Pre-conditions: `path` is the artifact's emission destination (or
|
|
188
|
+
None when scanning stdin without a target path).
|
|
189
|
+
Post-conditions: returns True iff the path matches an in-scope
|
|
190
|
+
prefix or an in-scope bare filename.
|
|
191
|
+
"""
|
|
192
|
+
if path is None:
|
|
193
|
+
return True # CLI use without a target path; classify by content alone.
|
|
194
|
+
# Normalize to forward-slash for cross-platform glob match.
|
|
195
|
+
rel = path.as_posix()
|
|
196
|
+
if path.name in IN_SCOPE_FILENAMES:
|
|
197
|
+
return True
|
|
198
|
+
for prefix in IN_SCOPE_PREFIXES:
|
|
199
|
+
if rel.startswith(prefix) or f"/{prefix}" in rel:
|
|
200
|
+
return True
|
|
201
|
+
return False
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _classify(line: str, match_text: str) -> str | None:
|
|
205
|
+
"""Return a drift label when the occurrence is high-confidence drift.
|
|
206
|
+
|
|
207
|
+
Returns None when the occurrence is acceptable or unclassifiable.
|
|
208
|
+
"""
|
|
209
|
+
is_identifier_context = any(p.search(line) for p in IDENTIFIER_CONTEXT_PATTERNS)
|
|
210
|
+
is_display_context = any(p.search(line) for p in DISPLAY_CONTEXT_PATTERNS)
|
|
211
|
+
|
|
212
|
+
if is_identifier_context and not is_display_context:
|
|
213
|
+
# Lowercase form is canonical; PascalCase is drift.
|
|
214
|
+
if match_text == DISPLAY_FORM:
|
|
215
|
+
return "display-form-on-identifier-surface"
|
|
216
|
+
return None
|
|
217
|
+
if is_display_context and not is_identifier_context:
|
|
218
|
+
# PascalCase form is canonical; lowercase is drift.
|
|
219
|
+
if match_text == IDENTIFIER_FORM:
|
|
220
|
+
return "identifier-form-on-display-surface"
|
|
221
|
+
return None
|
|
222
|
+
# Mixed or unclassified: do not flag (catalog in normalization walk).
|
|
223
|
+
return None
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def check(content: str, path: Path | None = None) -> GrepResult:
|
|
227
|
+
"""Scan content for per-surface brand-mark form drift.
|
|
228
|
+
|
|
229
|
+
Pre-conditions: `content` is the artifact body about to be emitted;
|
|
230
|
+
`path` is its destination relative to the project root (or None for
|
|
231
|
+
stdin without a target).
|
|
232
|
+
Post-conditions: `result.passed` is True iff zero high-confidence
|
|
233
|
+
drift occurrences are found on in-scope paths.
|
|
234
|
+
"""
|
|
235
|
+
if not _in_scope(path):
|
|
236
|
+
return GrepResult(
|
|
237
|
+
grep=GREP_NAME,
|
|
238
|
+
path=str(path) if path is not None else None,
|
|
239
|
+
passed=True,
|
|
240
|
+
findings=[],
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
findings: list[Finding] = []
|
|
244
|
+
inside_fence = False
|
|
245
|
+
for line_index, line in enumerate(content.splitlines(), start=1):
|
|
246
|
+
if line.startswith("```"):
|
|
247
|
+
inside_fence = not inside_fence
|
|
248
|
+
continue
|
|
249
|
+
if inside_fence:
|
|
250
|
+
continue
|
|
251
|
+
for occurrence in BRAND_RE.finditer(line):
|
|
252
|
+
drift = _classify(line, occurrence.group())
|
|
253
|
+
if drift is None:
|
|
254
|
+
continue
|
|
255
|
+
findings.append(
|
|
256
|
+
Finding(
|
|
257
|
+
line=line_index,
|
|
258
|
+
match=occurrence.group(),
|
|
259
|
+
drift=drift,
|
|
260
|
+
context=line.strip()[:200],
|
|
261
|
+
)
|
|
262
|
+
)
|
|
263
|
+
return GrepResult(
|
|
264
|
+
grep=GREP_NAME,
|
|
265
|
+
path=str(path) if path is not None else None,
|
|
266
|
+
passed=not findings,
|
|
267
|
+
findings=findings,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
if __name__ == "__main__":
|
|
272
|
+
sys.exit(run_grep(check, sys.argv))
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Flag substantial commented-out code blocks left in source.
|
|
4
|
+
|
|
5
|
+
Why this enforcement exists. The code-craft rule M13.1 forbids commented-
|
|
6
|
+
out source code: source control is the canonical archive. Why-not-what
|
|
7
|
+
comments are welcome; disabled logic is not. The pre-emission gate's
|
|
8
|
+
mechanical bar 13 (M13 code craft) catches multi-line runs of comment-prefixed lines that
|
|
9
|
+
contain code-shaped tokens and surfaces each block so the operator
|
|
10
|
+
restores the code or deletes the dead block.
|
|
11
|
+
|
|
12
|
+
Detection: a per-language comment-prefix table identifies the prefix; the
|
|
13
|
+
grep accumulates consecutive prefixed lines whose stripped bodies match a
|
|
14
|
+
code-shape heuristic (keywords, name=value, name(args), arrow operators).
|
|
15
|
+
A run of three or more such lines is a finding; pure prose comments
|
|
16
|
+
(headers, citations, why-not-what explanations) pass clean.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
import sys
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Final
|
|
26
|
+
|
|
27
|
+
from apothem.conformity._grep_base import GrepResult, run_grep
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True)
|
|
31
|
+
class CommentPrefix:
|
|
32
|
+
"""One language's line-comment prefix and the file extensions it covers."""
|
|
33
|
+
|
|
34
|
+
label: str
|
|
35
|
+
prefix: str
|
|
36
|
+
extensions: tuple[str, ...]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Per-language line-comment prefixes. The set covers the languages the
|
|
40
|
+
# host project commonly emits (Python, shell, YAML, TOML use `#`; the
|
|
41
|
+
# C-family languages and JavaScript use `//`). The label is the language
|
|
42
|
+
# name shown in the finding so the operator can route the cleanup.
|
|
43
|
+
COMMENT_PREFIXES: Final[tuple[CommentPrefix, ...]] = (
|
|
44
|
+
CommentPrefix(
|
|
45
|
+
"hash-prefix (Python / shell / YAML / TOML / Ruby)",
|
|
46
|
+
"#",
|
|
47
|
+
(".py", ".sh", ".bash", ".ps1", ".yml", ".yaml", ".toml", ".rb"),
|
|
48
|
+
),
|
|
49
|
+
CommentPrefix(
|
|
50
|
+
"slash-slash (JS / TS / Go / Rust / C / C++ / Java / Swift)",
|
|
51
|
+
"//",
|
|
52
|
+
(
|
|
53
|
+
".js",
|
|
54
|
+
".ts",
|
|
55
|
+
".tsx",
|
|
56
|
+
".jsx",
|
|
57
|
+
".go",
|
|
58
|
+
".rs",
|
|
59
|
+
".c",
|
|
60
|
+
".cpp",
|
|
61
|
+
".h",
|
|
62
|
+
".hpp",
|
|
63
|
+
".java",
|
|
64
|
+
".swift",
|
|
65
|
+
".kt",
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Code-shaped-token signatures. A commented line whose stripped body
|
|
71
|
+
# contains one of these patterns is treated as commented-out code rather
|
|
72
|
+
# than prose. The set favors precision — common prose words don't match.
|
|
73
|
+
CODE_SIGNATURE_RE: Final[re.Pattern[str]] = re.compile(
|
|
74
|
+
r"(?:"
|
|
75
|
+
r"\b(?:def|class|import|from|return|if|elif|else|for|while|try|except|"
|
|
76
|
+
r"finally|with|lambda|async|await|yield|raise|assert)\b"
|
|
77
|
+
r"|\b(?:function|const|let|var|require|export|module|interface|type|"
|
|
78
|
+
r"struct|enum|impl|fn|pub|use|package)\b"
|
|
79
|
+
r"|[A-Za-z_]\w*\s*=\s*[^=]" # `name = value` (not `==`)
|
|
80
|
+
r"|[A-Za-z_]\w*\s*\([^)]*\)" # `name(args)`
|
|
81
|
+
r"|->|=>" # arrow functions / type hints
|
|
82
|
+
r")"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Minimum consecutive commented-code lines that constitute a block. Two-line
|
|
86
|
+
# runs are typically a TODO + a code snippet; three or more is a definitive
|
|
87
|
+
# block per the rule's intent.
|
|
88
|
+
MIN_BLOCK_LINES: Final[int] = 3
|
|
89
|
+
|
|
90
|
+
GREP_NAME: Final[str] = "commented-out-code-grep"
|
|
91
|
+
RULE_ANCHOR: Final[str] = "M13.1 why-not-what comments"
|
|
92
|
+
EXIT_PASS: Final[int] = 0
|
|
93
|
+
EXIT_FAIL: Final[int] = 2
|
|
94
|
+
STDIN_FLAG: Final[str] = "--stdin"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass(frozen=True)
|
|
98
|
+
class Finding:
|
|
99
|
+
"""One commented-out-code block occurrence."""
|
|
100
|
+
|
|
101
|
+
start_line: int
|
|
102
|
+
end_line: int
|
|
103
|
+
language: str
|
|
104
|
+
line_count: int
|
|
105
|
+
rule: str = RULE_ANCHOR
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _select_prefix(path: Path | None) -> CommentPrefix:
|
|
109
|
+
"""Return the comment prefix matching the file extension, or hash by default.
|
|
110
|
+
|
|
111
|
+
Stdin input has no extension — the hash prefix is the conservative default
|
|
112
|
+
since it covers the largest surface in this ecosystem.
|
|
113
|
+
"""
|
|
114
|
+
if path is not None:
|
|
115
|
+
suffix = path.suffix.lower()
|
|
116
|
+
for entry in COMMENT_PREFIXES:
|
|
117
|
+
if suffix in entry.extensions:
|
|
118
|
+
return entry
|
|
119
|
+
return COMMENT_PREFIXES[0]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _is_commented_code(stripped_body: str) -> bool:
|
|
123
|
+
"""Decide whether a commented line's body looks like code rather than prose."""
|
|
124
|
+
return CODE_SIGNATURE_RE.search(stripped_body) is not None
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def check(content: str, path: Path | None = None) -> GrepResult:
|
|
128
|
+
"""Scan content; return a structured result.
|
|
129
|
+
|
|
130
|
+
Pre-conditions: `content` is the source body about to be emitted.
|
|
131
|
+
Post-conditions: `result.passed` is True iff no run of
|
|
132
|
+
`MIN_BLOCK_LINES` or more consecutive commented lines contains
|
|
133
|
+
code-shaped tokens.
|
|
134
|
+
"""
|
|
135
|
+
prefix = _select_prefix(path)
|
|
136
|
+
findings: list[Finding] = []
|
|
137
|
+
run_start: int | None = None
|
|
138
|
+
run_length = 0
|
|
139
|
+
|
|
140
|
+
def flush(end_line: int) -> None:
|
|
141
|
+
if run_start is not None and run_length >= MIN_BLOCK_LINES:
|
|
142
|
+
findings.append(
|
|
143
|
+
Finding(
|
|
144
|
+
start_line=run_start,
|
|
145
|
+
end_line=end_line,
|
|
146
|
+
language=prefix.label,
|
|
147
|
+
line_count=run_length,
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
for line_index, line in enumerate(content.splitlines(), start=1):
|
|
152
|
+
stripped = line.lstrip()
|
|
153
|
+
is_comment = stripped.startswith(prefix.prefix)
|
|
154
|
+
body = stripped[len(prefix.prefix) :].strip() if is_comment else ""
|
|
155
|
+
if not is_comment or not _is_commented_code(body):
|
|
156
|
+
flush(line_index - 1)
|
|
157
|
+
run_start = None
|
|
158
|
+
run_length = 0
|
|
159
|
+
continue
|
|
160
|
+
if run_start is None:
|
|
161
|
+
run_start = line_index
|
|
162
|
+
run_length = 1
|
|
163
|
+
else:
|
|
164
|
+
run_length += 1
|
|
165
|
+
if run_start is not None:
|
|
166
|
+
flush(run_start + run_length - 1)
|
|
167
|
+
return GrepResult(
|
|
168
|
+
grep=GREP_NAME,
|
|
169
|
+
path=str(path) if path is not None else None,
|
|
170
|
+
passed=not findings,
|
|
171
|
+
findings=findings,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
sys.exit(run_grep(check, sys.argv))
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Flag unsupported completion / guarantee claims in cohort prose.
|
|
4
|
+
|
|
5
|
+
Why this enforcement exists. Spec §4.2 (Output Honesty, Validity, and
|
|
6
|
+
Determinism) demands evidence that requirements are truly complete, including
|
|
7
|
+
checks against "done" claims that would require a rerun to prove. A command,
|
|
8
|
+
agent, or skill that promises an absolute, unconditional outcome — "guaranteed
|
|
9
|
+
to pass", "always works", "100% complete", "cannot fail" — asserts a result the
|
|
10
|
+
prose cannot back with evidence; the claim reads as honest completion when it is
|
|
11
|
+
actually an unprovable guarantee. This matcher detects a closed set of such
|
|
12
|
+
absolute-guarantee phrases so the dishonest-completion pattern surfaces before
|
|
13
|
+
emission.
|
|
14
|
+
|
|
15
|
+
What this is NOT. This is a deliberately narrow guard against *absolute,
|
|
16
|
+
unconditional* guarantees, not a ban on the words "done" or "complete".
|
|
17
|
+
Evidence-gated completion language ("complete when every verification passes",
|
|
18
|
+
"not complete until zero findings remain", "declare complete once the suite is
|
|
19
|
+
verified") is correct and is not matched. Distinguishing a merely-unsupported
|
|
20
|
+
"done" from an evidence-gated one requires judgment beyond a mechanical grep;
|
|
21
|
+
that broader class is documented as out of scope per the spec's
|
|
22
|
+
"detected or documented as out of scope" acceptance, and this grep covers the
|
|
23
|
+
mechanically-detectable absolute-guarantee subset.
|
|
24
|
+
|
|
25
|
+
Scope. Only cohort prose (`.md` under commands / agents / skills / rules /
|
|
26
|
+
output-styles / hooks messages) is scanned; code, schemas, and plan-suite
|
|
27
|
+
artifacts are skipped. Files that define this discipline (quoting the phrases as
|
|
28
|
+
anti-pattern examples) are excluded by path, and hits inside fenced code blocks
|
|
29
|
+
are excluded — a fenced block quotes commands or anti-pattern examples rather
|
|
30
|
+
than carrying the artifact's own directive prose (mirroring hedging_grep).
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import re
|
|
36
|
+
import sys
|
|
37
|
+
from dataclasses import dataclass
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
from typing import Final
|
|
40
|
+
|
|
41
|
+
from apothem.conformity._grep_base import GrepResult, run_grep
|
|
42
|
+
|
|
43
|
+
# Closed set of absolute / unconditional completion-or-guarantee claims. Each is
|
|
44
|
+
# unprovable in directive prose: proving it would require a rerun, and even then
|
|
45
|
+
# the universal quantifier ("always", "never", "100%", "cannot") cannot be
|
|
46
|
+
# discharged. The patterns are anchored to the guarantee structure to keep the
|
|
47
|
+
# false-positive rate near zero.
|
|
48
|
+
_CLAIM_PATTERNS: Final[tuple[tuple[str, re.Pattern[str]], ...]] = (
|
|
49
|
+
(
|
|
50
|
+
"guaranteed-outcome",
|
|
51
|
+
re.compile(r"guaranteed to (?:pass|work|succeed|complete)", re.IGNORECASE),
|
|
52
|
+
),
|
|
53
|
+
(
|
|
54
|
+
"absolute-percentage",
|
|
55
|
+
re.compile(
|
|
56
|
+
r"100%\s+(?:complete|guaranteed|certain|reliable|done|airtight)",
|
|
57
|
+
re.IGNORECASE,
|
|
58
|
+
),
|
|
59
|
+
),
|
|
60
|
+
("cannot-fail", re.compile(r"\bcannot (?:fail|possibly fail)\b", re.IGNORECASE)),
|
|
61
|
+
("will-never-fail", re.compile(r"\bwill never (?:fail|break)\b", re.IGNORECASE)),
|
|
62
|
+
(
|
|
63
|
+
"always-succeeds",
|
|
64
|
+
re.compile(r"\balways (?:passes|works|succeeds)\b", re.IGNORECASE),
|
|
65
|
+
),
|
|
66
|
+
("never-fails", re.compile(r"\bnever (?:fails|breaks)\b", re.IGNORECASE)),
|
|
67
|
+
(
|
|
68
|
+
"definitely-works",
|
|
69
|
+
re.compile(r"\bdefinitely (?:works|passes|complete)\b", re.IGNORECASE),
|
|
70
|
+
),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Cohort-prose directories whose `.md` files carry directive / output prose.
|
|
74
|
+
_COHORT_DIRS: Final[tuple[str, ...]] = (
|
|
75
|
+
"commands",
|
|
76
|
+
"agents",
|
|
77
|
+
"skills",
|
|
78
|
+
"rules",
|
|
79
|
+
"output-styles",
|
|
80
|
+
"hooks",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Files that define the completion-honesty discipline and quote the banned
|
|
84
|
+
# phrases as anti-pattern examples; excluded so the definition is not a finding.
|
|
85
|
+
_EXCLUDED_BASENAMES: Final[frozenset[str]] = frozenset(
|
|
86
|
+
{
|
|
87
|
+
"completion_claim_grep.py",
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Fenced code block delimiter (triple backtick at column 0), mirroring
|
|
92
|
+
# hedging_grep.CODE_FENCE_RE. A claim inside a fenced block is a quoted command
|
|
93
|
+
# or anti-pattern example, not the artifact's own prescriptive prose, so it is
|
|
94
|
+
# excluded from the scan.
|
|
95
|
+
_CODE_FENCE_RE: Final[re.Pattern[str]] = re.compile(r"^```")
|
|
96
|
+
|
|
97
|
+
GREP_NAME: Final[str] = "completion-claim-grep"
|
|
98
|
+
RULE_ANCHOR: Final[str] = "rules/session-closure.md (verifiable-close output honesty)"
|
|
99
|
+
EXIT_PASS: Final[int] = 0
|
|
100
|
+
EXIT_FAIL: Final[int] = 2
|
|
101
|
+
STDIN_FLAG: Final[str] = "--stdin"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass(frozen=True)
|
|
105
|
+
class Finding:
|
|
106
|
+
"""One unsupported-completion-claim occurrence."""
|
|
107
|
+
|
|
108
|
+
line: int
|
|
109
|
+
kind: str
|
|
110
|
+
text: str
|
|
111
|
+
rule: str = RULE_ANCHOR
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _in_scope(path: Path | None) -> bool:
|
|
115
|
+
"""Return True when *path* is cohort prose subject to the scan.
|
|
116
|
+
|
|
117
|
+
A None path (stdin) is in scope so direct invocations are checked; a
|
|
118
|
+
concrete path must be a `.md` under a cohort directory and not excluded.
|
|
119
|
+
"""
|
|
120
|
+
if path is None:
|
|
121
|
+
return True
|
|
122
|
+
if path.suffix.lower() != ".md":
|
|
123
|
+
return False
|
|
124
|
+
if path.name in _EXCLUDED_BASENAMES:
|
|
125
|
+
return False
|
|
126
|
+
parts = set(path.parts)
|
|
127
|
+
return any(directory in parts for directory in _COHORT_DIRS)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def check(content: str, path: Path | None = None) -> GrepResult:
|
|
131
|
+
"""Scan *content* for absolute-guarantee completion claims.
|
|
132
|
+
|
|
133
|
+
Pre-conditions: *content* is the artifact body about to be emitted; *path*
|
|
134
|
+
is its destination (used for cohort-scope restriction and exclusion).
|
|
135
|
+
Post-conditions: ``result.passed`` is True when no absolute-guarantee phrase
|
|
136
|
+
from the closed set appears, or when *path* is out of scope.
|
|
137
|
+
"""
|
|
138
|
+
if not _in_scope(path):
|
|
139
|
+
return GrepResult(grep=GREP_NAME, path=_path_str(path), passed=True)
|
|
140
|
+
|
|
141
|
+
findings: list[Finding] = []
|
|
142
|
+
inside_fence = False
|
|
143
|
+
for line_number, line in enumerate(content.splitlines(), start=1):
|
|
144
|
+
if _CODE_FENCE_RE.match(line):
|
|
145
|
+
# Toggle fence state — opening and closing fences both match.
|
|
146
|
+
inside_fence = not inside_fence
|
|
147
|
+
continue
|
|
148
|
+
if inside_fence:
|
|
149
|
+
continue
|
|
150
|
+
for kind, pattern in _CLAIM_PATTERNS:
|
|
151
|
+
match = pattern.search(line)
|
|
152
|
+
if match:
|
|
153
|
+
findings.append(
|
|
154
|
+
Finding(line=line_number, kind=kind, text=match.group(0))
|
|
155
|
+
)
|
|
156
|
+
return GrepResult(
|
|
157
|
+
grep=GREP_NAME,
|
|
158
|
+
path=_path_str(path),
|
|
159
|
+
passed=not findings,
|
|
160
|
+
findings=findings,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _path_str(path: Path | None) -> str | None:
|
|
165
|
+
return str(path) if path is not None else None
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
if __name__ == "__main__":
|
|
169
|
+
sys.exit(run_grep(check, sys.argv))
|