@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,559 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Flag mechanistic / harness-internal vocabulary in user-facing prose.
|
|
4
|
+
|
|
5
|
+
Why this enforcement exists. The plain-language rule requires user-facing
|
|
6
|
+
surfaces (READMEs, documentation pages, landing pages, install guides)
|
|
7
|
+
to read as natural product prose — never as a leak of harness identity,
|
|
8
|
+
plan-internal taxonomy, or implementation mechanism. Tokens like ``AI``,
|
|
9
|
+
``agent``, ``LLM``, ``attestation``, the process-tooling markers
|
|
10
|
+
``ratified`` and ``cutover-rehearsal``, the registered harness brand names
|
|
11
|
+
(``claude_code``, ``cursor``, ``gemini``, ``copilot``, ``windsurf``,
|
|
12
|
+
``codex``, ``hermes``), and plan-stage tokens (numeric stage labels, stream
|
|
13
|
+
labels, and zero-padded nested-stage labels) are mechanistic. They belong to
|
|
14
|
+
internal rules / commands / agents / plans surfaces; on the user-facing
|
|
15
|
+
surface they break the plain-language floor.
|
|
16
|
+
|
|
17
|
+
The product noun ``harness`` / ``harnesses`` is NOT forbidden — it is
|
|
18
|
+
apothem's central product domain ("host-agnostic AI-harness configuration
|
|
19
|
+
manager"), a domain carve-out per the plain-language rule's §2.
|
|
20
|
+
|
|
21
|
+
Scope. Corpus-level standalone validator. Walks the working tree under
|
|
22
|
+
the supplied root and inspects ONLY in-scope surfaces:
|
|
23
|
+
|
|
24
|
+
- ``README.md`` at the repository root.
|
|
25
|
+
- ``site/content/docs/**/*.{md,mdx}`` — the documentation tree.
|
|
26
|
+
|
|
27
|
+
OUT of scope (skipped wholesale): technical documentation routes
|
|
28
|
+
(``blog/``, ``comparison/``, ``reference/``, the agent-architecture
|
|
29
|
+
concept page, and the instruction-surface convention references),
|
|
30
|
+
generated reference inventory blocks, ``rules/**``,
|
|
31
|
+
``commands/**``, ``agents/**``, ``skills/**``, ``.plans/**``, ``tests/**``,
|
|
32
|
+
``scripts/**``, every ``*.py`` / ``*.sh`` / ``*.ps1`` source file,
|
|
33
|
+
``CLAUDE.md``, ``.github/copilot-instructions.md``. The dev-facing surface
|
|
34
|
+
is permissive by design — only the general operator-facing prose is held
|
|
35
|
+
to the plain-language bar.
|
|
36
|
+
|
|
37
|
+
Detection. Each forbidden token is a word-boundary case-insensitive
|
|
38
|
+
match. Matches inside fenced code blocks (triple-backtick) are excluded:
|
|
39
|
+
docs legitimately quote command names, sample config, and tool output
|
|
40
|
+
inside fences. Inline-code (single-backtick) spans are NOT excluded —
|
|
41
|
+
inline code in user-facing prose is the typical leak surface and the
|
|
42
|
+
matcher catches it intentionally.
|
|
43
|
+
|
|
44
|
+
Exit semantics. Exits 0 when zero findings across every in-scope file;
|
|
45
|
+
exits 2 on any finding. The exit-2 convention matches the conformity-
|
|
46
|
+
gate orchestrator's EXIT_FAIL constant.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from __future__ import annotations
|
|
50
|
+
|
|
51
|
+
import json
|
|
52
|
+
import re
|
|
53
|
+
import sys
|
|
54
|
+
from dataclasses import asdict, dataclass, field
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
from typing import Final
|
|
57
|
+
|
|
58
|
+
GREP_NAME: Final[str] = "plain-language-grep"
|
|
59
|
+
RULE_ANCHOR: Final[str] = "rules/plain-language.md — user-facing prose"
|
|
60
|
+
|
|
61
|
+
EXIT_PASS: Final[int] = 0
|
|
62
|
+
EXIT_FAIL: Final[int] = 2
|
|
63
|
+
|
|
64
|
+
# Forbidden vocabulary on user-facing prose surfaces. Tokens are matched
|
|
65
|
+
# case-insensitively at word boundaries. Multi-word tokens (e.g.,
|
|
66
|
+
# ``claude code``) are matched as literal phrases.
|
|
67
|
+
_FORBIDDEN_TOKENS: Final[tuple[str, ...]] = (
|
|
68
|
+
# Mechanistic generics.
|
|
69
|
+
"AI",
|
|
70
|
+
"agent",
|
|
71
|
+
"agents",
|
|
72
|
+
"LLM",
|
|
73
|
+
"LLMs",
|
|
74
|
+
"attestation",
|
|
75
|
+
"attestations",
|
|
76
|
+
# Process-tooling vocabulary (plan / governance markers that leak the
|
|
77
|
+
# internal process onto the user-facing surface). ``cutover-rehearsal``
|
|
78
|
+
# carries a hyphen; it is ``re.escape``d into the alternation, so the
|
|
79
|
+
# hyphen is matched literally.
|
|
80
|
+
"ratified",
|
|
81
|
+
"cutover-rehearsal",
|
|
82
|
+
# Registered harness identifiers (both snake_case slug and brand form).
|
|
83
|
+
"claude_code",
|
|
84
|
+
"claude-code",
|
|
85
|
+
"cursor",
|
|
86
|
+
"gemini",
|
|
87
|
+
"copilot",
|
|
88
|
+
"windsurf",
|
|
89
|
+
"codex",
|
|
90
|
+
"hermes",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Plan-stage taxonomy tokens. These are regex patterns (not literal
|
|
94
|
+
# words), so they live separately and are joined into the master regex
|
|
95
|
+
# verbatim rather than via ``re.escape``.
|
|
96
|
+
_PLAN_PHASE_PATTERNS: Final[tuple[str, ...]] = (
|
|
97
|
+
r"phase\s+\d+", # numbered stage labels
|
|
98
|
+
r"stream\s+[A-Z]\b", # "stream A", "Stream B"
|
|
99
|
+
r"\b\d{2}[A-Z]\b", # zero-padded nested-stage tokens
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
_LITERAL_GROUP: Final[str] = "|".join(re.escape(t) for t in _FORBIDDEN_TOKENS)
|
|
103
|
+
_PATTERN_GROUP: Final[str] = "|".join(_PLAN_PHASE_PATTERNS)
|
|
104
|
+
|
|
105
|
+
# Combined regex: word-boundary anchored case-insensitive scan.
|
|
106
|
+
_FORBIDDEN_RE: Final[re.Pattern[str]] = re.compile(
|
|
107
|
+
r"(?i)\b(?:" + _LITERAL_GROUP + r"|" + _PATTERN_GROUP + r")\b"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Fenced code block delimiter — matches a line whose first non-whitespace
|
|
111
|
+
# content is ```, so fences indented under list items (valid CommonMark) are
|
|
112
|
+
# recognized too, not only column-0 fences. Opening and closing fences both
|
|
113
|
+
# match; the matcher toggles in_fence state on each occurrence.
|
|
114
|
+
_CODE_FENCE_RE: Final[re.Pattern[str]] = re.compile(r"^[ \t]*```")
|
|
115
|
+
|
|
116
|
+
# In-scope path predicates. The matcher walks the corpus and applies
|
|
117
|
+
# these predicates to every Markdown / MDX file to decide whether to scan it.
|
|
118
|
+
_DOCS_PATH_PARTS: Final[tuple[str, ...]] = ("site", "content", "docs")
|
|
119
|
+
_README_FILENAME: Final[str] = "README.md"
|
|
120
|
+
_MARKDOWN_SUFFIXES: Final[frozenset[str]] = frozenset({".md", ".mdx"})
|
|
121
|
+
_TECHNICAL_DOC_PREFIXES: Final[tuple[str, ...]] = (
|
|
122
|
+
"site/content/docs/blog/",
|
|
123
|
+
"site/content/docs/comparison/",
|
|
124
|
+
"site/content/docs/reference/",
|
|
125
|
+
)
|
|
126
|
+
_TECHNICAL_DOC_FILES: Final[frozenset[str]] = frozenset(
|
|
127
|
+
{
|
|
128
|
+
"site/content/docs/reference/ai-conventions.mdx",
|
|
129
|
+
"site/content/docs/architecture/agents.mdx",
|
|
130
|
+
"site/content/docs/architecture/cohort-packaging-contract.mdx",
|
|
131
|
+
"site/content/docs/architecture/harness-adapter-abstraction.mdx",
|
|
132
|
+
"site/content/docs/architecture/shared-profile-schema.mdx",
|
|
133
|
+
"site/content/docs/concepts/agent-architecture.mdx",
|
|
134
|
+
"site/content/docs/how-to/installer-environment-variables.mdx",
|
|
135
|
+
"site/content/docs/reference/plans-discipline.mdx",
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
_PRODUCT_INDEX_PATH: Final[str] = "site/content/docs/index.mdx"
|
|
139
|
+
# Cohort-locale segments mirrored under ``site/content/docs/<locale>/``. A
|
|
140
|
+
# locale subtree is a translation of the English source, so every EN-path
|
|
141
|
+
# exclusion predicate (technical-doc prefixes / files, harness-page allowlist,
|
|
142
|
+
# product index) applies identically to its locale mirror. The matcher strips
|
|
143
|
+
# the locale segment before exclusion matching so a translated comparison /
|
|
144
|
+
# reference page is not false-flagged for the harness brand names its English
|
|
145
|
+
# source legitimately carries.
|
|
146
|
+
_COHORT_LOCALE_SEGMENTS: Final[frozenset[str]] = frozenset(
|
|
147
|
+
{"zh-cn", "es", "pt-br", "fr", "de", "ja", "ko", "ru", "id", "ar", "hi"}
|
|
148
|
+
)
|
|
149
|
+
# Documentation pages carry these region markers in the comment syntax of the
|
|
150
|
+
# host docs framework: the HTML-comment form (``<!-- ... -->``) for Markdown
|
|
151
|
+
# pages and the JSX-comment form (``{/* ... */}``) for MDX pages. Both forms are
|
|
152
|
+
# recognized so the exclusion regions fire regardless of the page's extension.
|
|
153
|
+
_GENERATED_REFERENCE_START: Final[frozenset[str]] = frozenset(
|
|
154
|
+
{
|
|
155
|
+
"<!-- apothem:generated-reference:start -->",
|
|
156
|
+
"{/* apothem:generated-reference:start */}",
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
_GENERATED_REFERENCE_END: Final[frozenset[str]] = frozenset(
|
|
160
|
+
{
|
|
161
|
+
"<!-- apothem:generated-reference:end -->",
|
|
162
|
+
"{/* apothem:generated-reference:end */}",
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
# The changelog page injects the root ``CHANGELOG.md`` body between these
|
|
166
|
+
# markers at build time. The release history records the harness brand names
|
|
167
|
+
# and product vocabulary as factual release-note content (the same content the
|
|
168
|
+
# root ``CHANGELOG.md`` carries), not user-facing landing prose, so it is
|
|
169
|
+
# skipped exactly as the generated-reference block is.
|
|
170
|
+
_CHANGELOG_START: Final[frozenset[str]] = frozenset(
|
|
171
|
+
{
|
|
172
|
+
"<!-- apothem:changelog:start -->",
|
|
173
|
+
"{/* apothem:changelog:start */}",
|
|
174
|
+
}
|
|
175
|
+
)
|
|
176
|
+
_CHANGELOG_END: Final[frozenset[str]] = frozenset(
|
|
177
|
+
{
|
|
178
|
+
"<!-- apothem:changelog:end -->",
|
|
179
|
+
"{/* apothem:changelog:end */}",
|
|
180
|
+
}
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# Per-harness-page brand allowlist. A page at
|
|
184
|
+
# ``site/content/docs/harnesses/<stem>.mdx``
|
|
185
|
+
# is the canonical product description for that harness; brand-token
|
|
186
|
+
# references to that harness are load-bearing (page title, frontmatter
|
|
187
|
+
# ``description``, prose product identification, inline-code CLI paths,
|
|
188
|
+
# table cells) and cannot relocate inside fenced code blocks without
|
|
189
|
+
# breaking the rendered surface. The matcher exempts the brand tokens
|
|
190
|
+
# in the stem's allowlist when the finding's path resolves to the
|
|
191
|
+
# corresponding harness page. Tokens are lower-cased and matched
|
|
192
|
+
# case-insensitively against the finding's ``match`` field.
|
|
193
|
+
_HARNESS_PAGE_ALLOWED_BRANDS: Final[dict[str, frozenset[str]]] = {
|
|
194
|
+
"antigravity": frozenset({"gemini"}), # Google Antigravity bundles Gemini.
|
|
195
|
+
# claude-code's install propagation lists the canonical sibling
|
|
196
|
+
# directories ``agents/`` ``commands/`` ``rules/`` ``skills/`` etc.;
|
|
197
|
+
# the noun ``agents`` here names the Claude Code harness directory,
|
|
198
|
+
# not the mechanistic ``AI agent`` vocabulary.
|
|
199
|
+
"claude-code": frozenset({"claude-code", "claude_code", "agents"}),
|
|
200
|
+
# CodeBuddy's page enumerates the apothem cohort surface (skills,
|
|
201
|
+
# commands, agents, hooks); the noun ``agents`` names the cohort class,
|
|
202
|
+
# not the mechanistic ``AI agent`` vocabulary.
|
|
203
|
+
"codebuddy": frozenset({"agents"}),
|
|
204
|
+
# OpenAI Codex's canonical config filename is ``AGENTS.md``; the
|
|
205
|
+
# noun on this page describes the file, not the mechanistic agent.
|
|
206
|
+
"codex": frozenset({"codex", "agents"}),
|
|
207
|
+
"cursor": frozenset({"cursor"}),
|
|
208
|
+
"gemini-cli": frozenset({"gemini"}),
|
|
209
|
+
"github-copilot": frozenset({"copilot"}),
|
|
210
|
+
# GLM's vendor is Z.ai; the ``ai`` token in the ``Z.ai`` brand name and
|
|
211
|
+
# the ``api.z.ai`` backend URLs names the vendor, not the mechanistic
|
|
212
|
+
# ``AI`` vocabulary the plain-language rule prohibits.
|
|
213
|
+
"glm": frozenset({"ai"}),
|
|
214
|
+
# ``Hermes Agent`` is the canonical product name (proper noun).
|
|
215
|
+
"hermes": frozenset({"hermes", "agent"}),
|
|
216
|
+
# Kiro's ``Agent Hooks`` is a documented product feature (proper noun).
|
|
217
|
+
"kiro": frozenset({"agent"}),
|
|
218
|
+
"windsurf": frozenset({"windsurf"}),
|
|
219
|
+
# Zed's canonical instruction filename is ``AGENTS.md`` and its product
|
|
220
|
+
# surface is the agent panel; the nouns name the file/feature, not the
|
|
221
|
+
# mechanistic vocabulary.
|
|
222
|
+
"zed": frozenset({"agent", "agents"}),
|
|
223
|
+
}
|
|
224
|
+
_HARNESS_PAGE_PARENT: Final[str] = "site/content/docs/harnesses"
|
|
225
|
+
|
|
226
|
+
# Generic mechanistic nouns that the per-harness-page allowlist legitimately
|
|
227
|
+
# carries on a brand's OWN product page (``Hermes Agent`` proper noun, the
|
|
228
|
+
# ``AGENTS.md`` filename on the Codex / Zed pages, the cohort-directory noun on
|
|
229
|
+
# the Claude Code / CodeBuddy pages) but that MUST NOT be blanket-exempted on
|
|
230
|
+
# the README / product-index surface. On the README a bare ``agent`` / ``agents``
|
|
231
|
+
# in prose is the mechanistic leak the plain-language rule prohibits; only the
|
|
232
|
+
# directory / cohort-enumeration uses of ``agents`` clear, and those clear via
|
|
233
|
+
# the line-scoped ``_is_directory_or_cohort_reference`` carve-out below — never
|
|
234
|
+
# via a blanket token exemption.
|
|
235
|
+
_GENERIC_MECHANISTIC_NOUNS: Final[frozenset[str]] = frozenset({"agent", "agents"})
|
|
236
|
+
|
|
237
|
+
# README brand allowlist. The repository ``README.md`` is the apothem
|
|
238
|
+
# product index: its CLI-usage section MUST enumerate the supported
|
|
239
|
+
# ``--harness <name>`` flag values for the documentation to be useful,
|
|
240
|
+
# and those flag values are the canonical adapter-package identifiers
|
|
241
|
+
# under ``src/apothem/harnesses/``. References to those identifiers
|
|
242
|
+
# at the README surface are load-bearing product domain — not the
|
|
243
|
+
# narrative-vocabulary class the plain-language rule prohibits. The set is
|
|
244
|
+
# the union of every harness-page allowlist (minus the generic mechanistic
|
|
245
|
+
# nouns, which are page-scoped, never README-blanket) plus the kebab-case CLI
|
|
246
|
+
# variants (e.g. ``claude-code``) so adapter identifiers spelled either
|
|
247
|
+
# in their snake_case Python form or their kebab-case CLI form clear the
|
|
248
|
+
# matcher. ``agent`` / ``agents`` are deliberately excluded — the generic
|
|
249
|
+
# noun on the README is held to the line-scoped directory / cohort carve-out,
|
|
250
|
+
# not a blanket pass.
|
|
251
|
+
_README_ALLOWED_BRANDS: Final[frozenset[str]] = (
|
|
252
|
+
frozenset(
|
|
253
|
+
{token for tokens in _HARNESS_PAGE_ALLOWED_BRANDS.values() for token in tokens}
|
|
254
|
+
| {
|
|
255
|
+
"claude-code",
|
|
256
|
+
"claude_code",
|
|
257
|
+
"cursor",
|
|
258
|
+
"codex",
|
|
259
|
+
"gemini-cli",
|
|
260
|
+
"github-copilot",
|
|
261
|
+
"hermes",
|
|
262
|
+
"opencode",
|
|
263
|
+
"qwen-code",
|
|
264
|
+
"qwen_code",
|
|
265
|
+
"windsurf",
|
|
266
|
+
"antigravity",
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
- _GENERIC_MECHANISTIC_NOUNS
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@dataclass(frozen=True)
|
|
274
|
+
class Finding:
|
|
275
|
+
"""One forbidden token in a user-facing prose surface."""
|
|
276
|
+
|
|
277
|
+
path: str
|
|
278
|
+
line: int
|
|
279
|
+
match: str
|
|
280
|
+
context: str
|
|
281
|
+
rule: str = RULE_ANCHOR
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
@dataclass(frozen=True)
|
|
285
|
+
class GrepResult:
|
|
286
|
+
"""Aggregated walk result for a single corpus sweep."""
|
|
287
|
+
|
|
288
|
+
grep: str
|
|
289
|
+
root: str
|
|
290
|
+
scanned_count: int
|
|
291
|
+
passed: bool
|
|
292
|
+
findings: list[Finding] = field(default_factory=list)
|
|
293
|
+
|
|
294
|
+
def to_json(self) -> str:
|
|
295
|
+
payload = {
|
|
296
|
+
"grep": self.grep,
|
|
297
|
+
"root": self.root,
|
|
298
|
+
"scanned_count": self.scanned_count,
|
|
299
|
+
"passed": self.passed,
|
|
300
|
+
"findings": [asdict(f) for f in self.findings],
|
|
301
|
+
}
|
|
302
|
+
return json.dumps(payload, indent=2)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def _is_user_facing(path: Path, root: Path) -> bool:
|
|
306
|
+
"""Return True iff ``path`` is an in-scope user-facing Markdown surface.
|
|
307
|
+
|
|
308
|
+
In scope:
|
|
309
|
+
- ``<root>/README.md``
|
|
310
|
+
- any ``*.md`` / ``*.mdx`` under ``<root>/site/content/docs/``
|
|
311
|
+
|
|
312
|
+
Out of scope: every other path. The matcher is deliberately permissive
|
|
313
|
+
on dev-facing surfaces.
|
|
314
|
+
"""
|
|
315
|
+
if path.suffix not in _MARKDOWN_SUFFIXES:
|
|
316
|
+
return False
|
|
317
|
+
try:
|
|
318
|
+
rel = path.resolve().relative_to(root.resolve())
|
|
319
|
+
except ValueError:
|
|
320
|
+
return False
|
|
321
|
+
parts = rel.parts
|
|
322
|
+
if len(parts) == 1 and parts[0] == _README_FILENAME:
|
|
323
|
+
return True
|
|
324
|
+
normalised = _delocalise_docs_path(rel.as_posix())
|
|
325
|
+
if normalised in _TECHNICAL_DOC_FILES:
|
|
326
|
+
return False
|
|
327
|
+
if any(normalised.startswith(prefix) for prefix in _TECHNICAL_DOC_PREFIXES):
|
|
328
|
+
return False
|
|
329
|
+
return parts[: len(_DOCS_PATH_PARTS)] == _DOCS_PATH_PARTS
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def _delocalise_docs_path(norm: str) -> str:
|
|
333
|
+
"""Strip a cohort-locale segment from a docs path for exclusion matching.
|
|
334
|
+
|
|
335
|
+
``site/content/docs/<locale>/comparison/index.mdx`` normalises to
|
|
336
|
+
``site/content/docs/comparison/index.mdx`` so the EN-path exclusion
|
|
337
|
+
predicates apply identically to every locale mirror. Non-docs paths and
|
|
338
|
+
English-root docs paths pass through unchanged.
|
|
339
|
+
"""
|
|
340
|
+
prefix = "site/content/docs/"
|
|
341
|
+
if not norm.startswith(prefix):
|
|
342
|
+
return norm
|
|
343
|
+
head, slash, tail = norm[len(prefix) :].partition("/")
|
|
344
|
+
if slash and head in _COHORT_LOCALE_SEGMENTS:
|
|
345
|
+
return prefix + tail
|
|
346
|
+
return norm
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def _harness_page_allowlist(rel_path: str) -> frozenset[str]:
|
|
350
|
+
"""Return the allowed-brand token set for a harness-page surface.
|
|
351
|
+
|
|
352
|
+
A page at ``site/content/docs/harnesses/<stem>.mdx`` may freely reference its own
|
|
353
|
+
canonical brand identifier - the page IS the product description.
|
|
354
|
+
Returns the lower-cased token set from
|
|
355
|
+
``_HARNESS_PAGE_ALLOWED_BRANDS[stem]`` when the path matches the
|
|
356
|
+
harness-page parent; ``frozenset()`` otherwise (no exemption).
|
|
357
|
+
"""
|
|
358
|
+
norm = _delocalise_docs_path(rel_path.replace("\\", "/"))
|
|
359
|
+
if norm == _README_FILENAME:
|
|
360
|
+
return _README_ALLOWED_BRANDS
|
|
361
|
+
if norm == _PRODUCT_INDEX_PATH:
|
|
362
|
+
return _README_ALLOWED_BRANDS
|
|
363
|
+
if not norm.startswith(_HARNESS_PAGE_PARENT + "/"):
|
|
364
|
+
return frozenset()
|
|
365
|
+
stem = Path(norm).stem
|
|
366
|
+
return _HARNESS_PAGE_ALLOWED_BRANDS.get(stem, frozenset())
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# Markdown link URL ranges — carve-out class. Canonical filename slugs
|
|
370
|
+
# referenced inside a link URL (``[text](url)``, ````) or a
|
|
371
|
+
# link-reference definition (``[id]: url``) are addressing the on-disk
|
|
372
|
+
# artifact, not asserting the vocabulary in prose. Matches whose offset
|
|
373
|
+
# falls inside one of these URL spans are excluded from the finding set
|
|
374
|
+
# alongside fenced code blocks. The link text itself remains in scope.
|
|
375
|
+
_LINK_URL_RE: Final[re.Pattern[str]] = re.compile(
|
|
376
|
+
r"!?\[[^\]]*\]\(([^)\s]+)(?:\s+\"[^\"]*\")?\)"
|
|
377
|
+
)
|
|
378
|
+
_LINK_REF_RE: Final[re.Pattern[str]] = re.compile(r"^\s*\[[^\]]+\]:\s*(\S+)")
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def _link_url_spans(line: str) -> list[tuple[int, int]]:
|
|
382
|
+
"""Return (start, end) spans of every markdown link / reference URL.
|
|
383
|
+
|
|
384
|
+
Matches:
|
|
385
|
+
- Inline link / image URL: ``[text](url)`` / ````; the
|
|
386
|
+
URL span is the capture group (excludes the parens themselves).
|
|
387
|
+
- Reference definition: ``[id]: url`` at line start (optionally
|
|
388
|
+
indented). The URL span is the capture group.
|
|
389
|
+
"""
|
|
390
|
+
spans: list[tuple[int, int]] = []
|
|
391
|
+
for m in _LINK_URL_RE.finditer(line):
|
|
392
|
+
spans.append(m.span(1))
|
|
393
|
+
ref = _LINK_REF_RE.match(line)
|
|
394
|
+
if ref is not None:
|
|
395
|
+
spans.append(ref.span(1))
|
|
396
|
+
return spans
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
# Sibling cohort-directory names. When the generic noun ``agents`` is
|
|
400
|
+
# enumerated alongside two or more of these on the same line, it names the
|
|
401
|
+
# cohort directory class (``skills, commands, agents, hooks``), not the
|
|
402
|
+
# mechanistic ``AI agent`` vocabulary. Two siblings is the threshold so a
|
|
403
|
+
# single co-occurrence of a common word does not trigger a false carve-out.
|
|
404
|
+
_COHORT_DIRECTORY_SIBLINGS: Final[tuple[str, ...]] = (
|
|
405
|
+
"commands",
|
|
406
|
+
"rules",
|
|
407
|
+
"skills",
|
|
408
|
+
"hooks",
|
|
409
|
+
"templates",
|
|
410
|
+
)
|
|
411
|
+
_COHORT_SIBLING_RE: Final[re.Pattern[str]] = re.compile(
|
|
412
|
+
r"(?i)\b(?:" + "|".join(_COHORT_DIRECTORY_SIBLINGS) + r")\b"
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
# Path-separator characters that, when adjacent to the matched token, mark it
|
|
416
|
+
# as a directory reference (``agents/``, ``~/.agents``, ``.agents``,
|
|
417
|
+
# ``\agents``) rather than a prose noun.
|
|
418
|
+
_PATH_SEPARATORS: Final[frozenset[str]] = frozenset({"/", "\\", "."})
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def _is_directory_or_cohort_reference(line: str, match: re.Match[str]) -> bool:
|
|
422
|
+
"""Return True iff the matched generic noun is a directory / cohort use.
|
|
423
|
+
|
|
424
|
+
The line-scoped carve-out for ``agent`` / ``agents`` on the README and
|
|
425
|
+
product-index surface. Two recognised forms clear:
|
|
426
|
+
|
|
427
|
+
- **Directory reference.** The token is immediately adjacent to a path
|
|
428
|
+
separator on either side — ``agents/``, ``/agents``, ``.agents``,
|
|
429
|
+
``\\agents`` — including the backticked ```agents/``` form
|
|
430
|
+
(the backtick is not the separator; the trailing ``/`` is). This names
|
|
431
|
+
an on-disk directory, not the mechanistic vocabulary.
|
|
432
|
+
- **Cohort-directory enumeration.** The token co-occurs on the same line
|
|
433
|
+
with two or more sibling cohort-directory names
|
|
434
|
+
(``commands`` / ``rules`` / ``skills`` / ``hooks`` / ``templates``),
|
|
435
|
+
e.g. ``skills, commands, agents, hooks``. This names the cohort
|
|
436
|
+
directory class, not the mechanistic vocabulary.
|
|
437
|
+
|
|
438
|
+
Applies only to the generic nouns in ``_GENERIC_MECHANISTIC_NOUNS``; every
|
|
439
|
+
other forbidden token (harness identifiers, ``AI`` / ``LLM`` / process
|
|
440
|
+
markers) is unaffected and never clears via this carve-out.
|
|
441
|
+
"""
|
|
442
|
+
if match.group().lower() not in _GENERIC_MECHANISTIC_NOUNS:
|
|
443
|
+
return False
|
|
444
|
+
start, end = match.start(), match.end()
|
|
445
|
+
before = line[start - 1] if start > 0 else ""
|
|
446
|
+
after = line[end] if end < len(line) else ""
|
|
447
|
+
if before in _PATH_SEPARATORS or after in _PATH_SEPARATORS:
|
|
448
|
+
return True
|
|
449
|
+
siblings = sum(1 for _ in _COHORT_SIBLING_RE.finditer(line))
|
|
450
|
+
return siblings >= 2
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def _scan_file(path: Path, root: Path) -> list[Finding]:
|
|
454
|
+
"""Scan one Markdown file; return findings outside fenced code blocks.
|
|
455
|
+
|
|
456
|
+
Applies the per-harness-page brand allowlist: when ``path`` resolves
|
|
457
|
+
to ``site/content/docs/harnesses/<stem>.mdx`` and the matched token is in the
|
|
458
|
+
stem's allowed-brand set, the match is skipped. Matches whose offset
|
|
459
|
+
falls inside a markdown link URL (``[text](url)``) or link-reference
|
|
460
|
+
definition (``[id]: url``) are also excluded — the URL addresses an
|
|
461
|
+
on-disk artifact, not the vocabulary in prose.
|
|
462
|
+
"""
|
|
463
|
+
try:
|
|
464
|
+
content = path.read_text(encoding="utf-8")
|
|
465
|
+
except (OSError, UnicodeDecodeError):
|
|
466
|
+
return []
|
|
467
|
+
try:
|
|
468
|
+
rel_path = str(path.resolve().relative_to(root.resolve()))
|
|
469
|
+
except ValueError:
|
|
470
|
+
rel_path = str(path)
|
|
471
|
+
allowlist = _harness_page_allowlist(rel_path)
|
|
472
|
+
findings: list[Finding] = []
|
|
473
|
+
inside_fence = False
|
|
474
|
+
inside_generated_reference = False
|
|
475
|
+
inside_changelog = False
|
|
476
|
+
for line_index, line in enumerate(content.splitlines(), start=1):
|
|
477
|
+
if _CODE_FENCE_RE.match(line):
|
|
478
|
+
inside_fence = not inside_fence
|
|
479
|
+
continue
|
|
480
|
+
if line.strip() in _GENERATED_REFERENCE_START:
|
|
481
|
+
inside_generated_reference = True
|
|
482
|
+
continue
|
|
483
|
+
if line.strip() in _GENERATED_REFERENCE_END:
|
|
484
|
+
inside_generated_reference = False
|
|
485
|
+
continue
|
|
486
|
+
if line.strip() in _CHANGELOG_START:
|
|
487
|
+
inside_changelog = True
|
|
488
|
+
continue
|
|
489
|
+
if line.strip() in _CHANGELOG_END:
|
|
490
|
+
inside_changelog = False
|
|
491
|
+
continue
|
|
492
|
+
if inside_fence:
|
|
493
|
+
continue
|
|
494
|
+
if inside_generated_reference or inside_changelog:
|
|
495
|
+
continue
|
|
496
|
+
url_spans = _link_url_spans(line)
|
|
497
|
+
for match in _FORBIDDEN_RE.finditer(line):
|
|
498
|
+
if match.group().lower() in allowlist:
|
|
499
|
+
continue
|
|
500
|
+
if _is_directory_or_cohort_reference(line, match):
|
|
501
|
+
continue
|
|
502
|
+
start = match.start()
|
|
503
|
+
if any(s <= start < e for s, e in url_spans):
|
|
504
|
+
continue
|
|
505
|
+
findings.append(
|
|
506
|
+
Finding(
|
|
507
|
+
path=rel_path,
|
|
508
|
+
line=line_index,
|
|
509
|
+
match=match.group(),
|
|
510
|
+
context=line.strip(),
|
|
511
|
+
)
|
|
512
|
+
)
|
|
513
|
+
return findings
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
def check(root: Path) -> GrepResult:
|
|
517
|
+
"""Walk the corpus under ``root``; flag forbidden tokens in user prose.
|
|
518
|
+
|
|
519
|
+
Pre-conditions: ``root`` is the repository root (or an arbitrary
|
|
520
|
+
subtree to scan).
|
|
521
|
+
Post-conditions: ``result.passed`` is True iff every in-scope file
|
|
522
|
+
contained zero forbidden tokens outside fenced code blocks.
|
|
523
|
+
"""
|
|
524
|
+
findings: list[Finding] = []
|
|
525
|
+
scanned = 0
|
|
526
|
+
candidates = sorted(
|
|
527
|
+
p for suffix in _MARKDOWN_SUFFIXES for p in root.rglob(f"*{suffix}")
|
|
528
|
+
)
|
|
529
|
+
for path in candidates:
|
|
530
|
+
if not path.is_file():
|
|
531
|
+
continue
|
|
532
|
+
if not _is_user_facing(path, root):
|
|
533
|
+
continue
|
|
534
|
+
scanned += 1
|
|
535
|
+
findings.extend(_scan_file(path, root))
|
|
536
|
+
return GrepResult(
|
|
537
|
+
grep=GREP_NAME,
|
|
538
|
+
root=str(root),
|
|
539
|
+
scanned_count=scanned,
|
|
540
|
+
passed=not findings,
|
|
541
|
+
findings=findings,
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def _read_input(argv: list[str]) -> Path:
|
|
546
|
+
if len(argv) >= 2:
|
|
547
|
+
return Path(argv[1])
|
|
548
|
+
return Path.cwd()
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
def _main(argv: list[str]) -> int:
|
|
552
|
+
root = _read_input(argv)
|
|
553
|
+
result = check(root)
|
|
554
|
+
print(result.to_json())
|
|
555
|
+
return EXIT_PASS if result.passed else EXIT_FAIL
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
if __name__ == "__main__":
|
|
559
|
+
sys.exit(_main(sys.argv))
|