@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,188 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Detect references to a global user-scope plans directory as a write target.
|
|
4
|
+
|
|
5
|
+
Why this scan exists. The harness-agnostic plans discipline forbids any
|
|
6
|
+
agent from writing plan artifacts to a global user-config root in any
|
|
7
|
+
host project — plans belong under ``<project-root>/.plans/``. For the
|
|
8
|
+
Claude Code harness specifically, the user-config root carries an
|
|
9
|
+
unfortunate recursion: the apothem plan-suite itself lives under
|
|
10
|
+
``~/.claude/.plans/`` during authoring, while the discipline being
|
|
11
|
+
installed forbids any agent from writing to that path in any host
|
|
12
|
+
project. The recursion is resolved by gitignoring the suite folder
|
|
13
|
+
once the migration is complete; before that, every directive that
|
|
14
|
+
points an agent at ``~/.claude/.plans/...`` (or any other harness's
|
|
15
|
+
global plans path) as a WRITE target is a discipline violation that
|
|
16
|
+
the refit phases need to remove. Read-references inside the discipline
|
|
17
|
+
documentation (rules, site docs, plan-suite specs) are exempt because they
|
|
18
|
+
describe the discipline itself.
|
|
19
|
+
|
|
20
|
+
What this scan covers per finding. Lines mentioning
|
|
21
|
+
``~/.claude/.plans/``, ``$CLAUDE_PROJECT_DIR/.plans/``, or equivalent
|
|
22
|
+
global-plans path variants in a directive context. The scan flags
|
|
23
|
+
write-intent verbs adjacent to the path (``write to``, ``create at``,
|
|
24
|
+
``store under``, ``save to``, ``emit at``, ``land at``) as HIGH
|
|
25
|
+
severity; bare references without write intent are flagged at MEDIUM
|
|
26
|
+
because the operator may be using the path as a documentation pointer.
|
|
27
|
+
|
|
28
|
+
What this scan excludes. Lines inside fenced code blocks (which
|
|
29
|
+
document, rather than direct, the path). Files explicitly classified
|
|
30
|
+
as discipline documentation (``src/apothem/rules/persistent-conventions-vigilance``,
|
|
31
|
+
``site/content/docs/reference/plans-discipline.mdx``, the plan-suite specs themselves) are
|
|
32
|
+
walked but their hits carry an ``is-discipline-doc`` flag in the extra
|
|
33
|
+
field so the synthesis pass can rank them lower.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import argparse
|
|
39
|
+
import re
|
|
40
|
+
import sys
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
from typing import Any, Final
|
|
43
|
+
|
|
44
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
45
|
+
|
|
46
|
+
from _scan_lib import (
|
|
47
|
+
CONTENT_ROOT,
|
|
48
|
+
NARRATIVE_CLASSES,
|
|
49
|
+
SEVERITY_HIGH,
|
|
50
|
+
SEVERITY_MEDIUM,
|
|
51
|
+
Hit,
|
|
52
|
+
emit_json,
|
|
53
|
+
load_inventory,
|
|
54
|
+
read_text_safely,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Path patterns that indicate a reference to the user-scope plans dir.
|
|
58
|
+
_PLANS_PATH_RE: Final[re.Pattern[str]] = re.compile(
|
|
59
|
+
r"(?:~/\.claude/\.plans/|\$HOME/\.claude/\.plans/|\$CLAUDE_PROJECT_DIR/\.plans/"
|
|
60
|
+
r"|%USERPROFILE%[\\/]\.claude[\\/]\.plans[\\/])",
|
|
61
|
+
re.IGNORECASE,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Verbs that indicate a write-intent directive — adjacency raises the
|
|
65
|
+
# severity classification.
|
|
66
|
+
_WRITE_INTENT_RE: Final[re.Pattern[str]] = re.compile(
|
|
67
|
+
r"\b(?:write|writes|writing|create|creates|creating|store|stores|"
|
|
68
|
+
r"storing|save|saves|saving|emit|emits|emitting|land|lands|"
|
|
69
|
+
r"landing|generate|generates|generating|persist|persists|persisting|"
|
|
70
|
+
r"output|outputs|outputting|append|appends|appending|materialize|"
|
|
71
|
+
r"materializes|materializing|materialize|materializes|materializing"
|
|
72
|
+
r")\b",
|
|
73
|
+
re.IGNORECASE,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Files whose entire purpose is to document the plans-discipline; their
|
|
77
|
+
# references are read-targets, not write-targets, but the scan still
|
|
78
|
+
# flags them so the synthesis pass can decide. Paths are content-root-
|
|
79
|
+
# relative to match the inventory's record paths (the inventory is built
|
|
80
|
+
# with the content root as --root, so its paths carry bare top-level
|
|
81
|
+
# prefixes — `rules/...`, not `src/apothem/rules/...`). Surfaces outside
|
|
82
|
+
# the content root (`site/`, the repo-root `CLAUDE.md`) are not in the
|
|
83
|
+
# inventory and so never reach this scan; they are retained here only as
|
|
84
|
+
# an intent record for the day the scan scope widens.
|
|
85
|
+
_DISCIPLINE_DOC_PATHS: Final[frozenset[str]] = frozenset(
|
|
86
|
+
{
|
|
87
|
+
"rules/persistent-conventions-vigilance.md",
|
|
88
|
+
"site/content/docs/reference/plans-discipline.mdx",
|
|
89
|
+
"CLAUDE.md",
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _is_discipline_doc(rel: str) -> bool:
|
|
95
|
+
return rel in _DISCIPLINE_DOC_PATHS or rel.startswith(".plans/")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _scan_file(rel: str, content: str) -> list[Hit]:
|
|
99
|
+
"""Walk a single narrative artifact for plans-discipline hits."""
|
|
100
|
+
hits: list[Hit] = []
|
|
101
|
+
in_fence = False
|
|
102
|
+
is_doc = _is_discipline_doc(rel)
|
|
103
|
+
for lineno, line in enumerate(content.splitlines(), start=1):
|
|
104
|
+
if line.lstrip().startswith("```"):
|
|
105
|
+
in_fence = not in_fence
|
|
106
|
+
continue
|
|
107
|
+
if in_fence:
|
|
108
|
+
continue
|
|
109
|
+
if not _PLANS_PATH_RE.search(line):
|
|
110
|
+
continue
|
|
111
|
+
write_intent = bool(_WRITE_INTENT_RE.search(line))
|
|
112
|
+
severity = SEVERITY_HIGH if write_intent else SEVERITY_MEDIUM
|
|
113
|
+
kind = "plans-write-target" if write_intent else "plans-path-reference"
|
|
114
|
+
hits.append(
|
|
115
|
+
Hit(
|
|
116
|
+
file=rel,
|
|
117
|
+
line=lineno,
|
|
118
|
+
signal=f"{kind}: {line.strip()[:120]}",
|
|
119
|
+
severity=severity,
|
|
120
|
+
remediation=(
|
|
121
|
+
"Replace the user-scope plans path with a"
|
|
122
|
+
" host-project-relative path (e.g.,"
|
|
123
|
+
" '<project>/.plans/'); the discipline forbids the"
|
|
124
|
+
" ecosystem from emitting plan artifacts under the"
|
|
125
|
+
" user-config root."
|
|
126
|
+
),
|
|
127
|
+
extra={"is-discipline-doc": is_doc},
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
return hits
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _scan_record(record: dict[str, Any], root: Path) -> list[Hit]:
|
|
134
|
+
"""Run the plans-discipline scan against one inventory record."""
|
|
135
|
+
cls = record.get("class", "")
|
|
136
|
+
if cls not in NARRATIVE_CLASSES:
|
|
137
|
+
return []
|
|
138
|
+
rel = record["path"]
|
|
139
|
+
path = root / rel
|
|
140
|
+
content = read_text_safely(path)
|
|
141
|
+
if not content:
|
|
142
|
+
return []
|
|
143
|
+
return _scan_file(rel, content)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def main(argv: list[str] | None = None) -> int:
|
|
147
|
+
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
148
|
+
parser.add_argument(
|
|
149
|
+
"--inventory",
|
|
150
|
+
type=Path,
|
|
151
|
+
default=Path(".audit/inventory.json"),
|
|
152
|
+
)
|
|
153
|
+
parser.add_argument("--root", type=Path, default=CONTENT_ROOT)
|
|
154
|
+
parser.add_argument(
|
|
155
|
+
"--output",
|
|
156
|
+
type=Path,
|
|
157
|
+
default=Path(".audit/drift-plans-discipline.json"),
|
|
158
|
+
)
|
|
159
|
+
args = parser.parse_args(argv)
|
|
160
|
+
|
|
161
|
+
if not args.inventory.exists():
|
|
162
|
+
print(
|
|
163
|
+
f"error: inventory not found at {args.inventory}",
|
|
164
|
+
file=sys.stderr,
|
|
165
|
+
)
|
|
166
|
+
return 1
|
|
167
|
+
|
|
168
|
+
records, sha = load_inventory(args.inventory)
|
|
169
|
+
hits: list[Hit] = []
|
|
170
|
+
for record in records:
|
|
171
|
+
hits.extend(_scan_record(record, args.root))
|
|
172
|
+
emit_json(args.output, "scan_plans_discipline", hits, sha)
|
|
173
|
+
by_signal: dict[str, int] = {}
|
|
174
|
+
for h in hits:
|
|
175
|
+
kind = h.signal.split(":", 1)[0]
|
|
176
|
+
by_signal[kind] = by_signal.get(kind, 0) + 1
|
|
177
|
+
summary = ", ".join(f"{k}={v}" for k, v in sorted(by_signal.items()))
|
|
178
|
+
discipline_doc_share = sum(1 for h in hits if h.extra.get("is-discipline-doc"))
|
|
179
|
+
print(
|
|
180
|
+
f"scan_plans_discipline: {len(hits)} hit(s) "
|
|
181
|
+
f"[{summary or 'none'}]; discipline-doc context: "
|
|
182
|
+
f"{discipline_doc_share}"
|
|
183
|
+
)
|
|
184
|
+
return 0
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if __name__ == "__main__":
|
|
188
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Detect secrets, PII tokens, and host-specific absolute paths.
|
|
4
|
+
|
|
5
|
+
Why this scan exists. Three risks live in the same scan because they
|
|
6
|
+
share the same enforcement surface (a pre-commit / pre-emission gate)
|
|
7
|
+
and the same scope (every text file in the working tree, not just the
|
|
8
|
+
narrative subset). A leaked secret is a credential breach. A PII token
|
|
9
|
+
embedded in narrative violates the canonical-banner allow-list and may
|
|
10
|
+
expose contact data outside the operator's intent. An absolute path
|
|
11
|
+
naming the operator's home directory or username binds the artifact to
|
|
12
|
+
a single machine and breaks portability across operator hosts.
|
|
13
|
+
|
|
14
|
+
What this scan covers per finding.
|
|
15
|
+
|
|
16
|
+
- **Secret patterns.** API keys (AWS / GitHub / Stripe / Slack / generic
|
|
17
|
+
PEM blocks / OpenAI / Anthropic). Pattern set is curated per
|
|
18
|
+
upstream-vendor token shapes; any literal occurrence is HIGH severity.
|
|
19
|
+
- **PII tokens.** Email addresses, full-name candidates flagged via
|
|
20
|
+
``\\b[A-Z][a-z]+ [A-Z][a-z]+\\b`` (heuristic; high false-positive),
|
|
21
|
+
phone-like sequences. Banner-allowed contacts (canonical email,
|
|
22
|
+
website, GitHub handle) are exempt via the byte-exact banner-line
|
|
23
|
+
match.
|
|
24
|
+
- **Absolute home paths.** ``/Users/<name>/`` (macOS), ``/home/<name>/``
|
|
25
|
+
(Linux), ``C:\\\\Users\\\\<name>\\\\`` (Windows). The operator's actual
|
|
26
|
+
username is detected by reading the canonical banner once at scan
|
|
27
|
+
start and used as the comparison anchor; non-operator usernames in
|
|
28
|
+
test fixtures are also flagged separately because they bind the
|
|
29
|
+
artifact to that specific test scenario.
|
|
30
|
+
|
|
31
|
+
What this scan excludes. Memory and plan-artifact records are walked
|
|
32
|
+
for absolute-path detection (a plan-artifact referencing the operator's
|
|
33
|
+
home leaks the operator's username if the plan is shared) but excluded
|
|
34
|
+
from secret scanning (per-project memory may legitimately reference
|
|
35
|
+
host-specific tokens that never leave the project's own boundary).
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
import argparse
|
|
41
|
+
import re
|
|
42
|
+
import sys
|
|
43
|
+
from pathlib import Path
|
|
44
|
+
from typing import Any, Final
|
|
45
|
+
|
|
46
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
47
|
+
|
|
48
|
+
from _scan_lib import (
|
|
49
|
+
CONTENT_ROOT,
|
|
50
|
+
NARRATIVE_CLASSES,
|
|
51
|
+
SEVERITY_HIGH,
|
|
52
|
+
SEVERITY_LOW,
|
|
53
|
+
SEVERITY_MEDIUM,
|
|
54
|
+
Hit,
|
|
55
|
+
emit_json,
|
|
56
|
+
load_inventory,
|
|
57
|
+
read_text_safely,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Banner contacts that are explicitly allow-listed for PII detection.
|
|
61
|
+
# The byte-exact banner content is treated as the canonical disclosure
|
|
62
|
+
# surface; matching tokens elsewhere outside the banner are still
|
|
63
|
+
# flagged as candidates for review.
|
|
64
|
+
BANNER_EMAIL: Final[str] = "me@ahmedgad.com"
|
|
65
|
+
BANNER_WEBSITE: Final[str] = "ahmedgad.com"
|
|
66
|
+
BANNER_GITHUB_HANDLE: Final[str] = "ahmed-g-gad"
|
|
67
|
+
BANNER_NAME: Final[str] = "Ahmed G. Gad"
|
|
68
|
+
BANNER_USERNAME: Final[str] = "Gad"
|
|
69
|
+
|
|
70
|
+
# Secret-pattern catalog. Each entry is a (label, regex) pair. The
|
|
71
|
+
# regexes are intentionally narrow to limit false positives; broader
|
|
72
|
+
# scanning is the gitleaks pre-commit hook's job at the hook-install
|
|
73
|
+
# pass.
|
|
74
|
+
_SECRET_PATTERNS: Final[list[tuple[str, re.Pattern[str]]]] = [
|
|
75
|
+
("aws-access-key-id", re.compile(r"\bAKIA[0-9A-Z]{16}\b")),
|
|
76
|
+
("aws-secret-access-key", re.compile(r"\b[A-Za-z0-9/+=]{40}\b(?=.{0,80}aws)")),
|
|
77
|
+
("github-pat", re.compile(r"\bgh[pousr]_[A-Za-z0-9_]{36,}\b")),
|
|
78
|
+
("anthropic-api-key", re.compile(r"\bsk-ant-[A-Za-z0-9-_]{30,}\b")),
|
|
79
|
+
("openai-api-key", re.compile(r"\bsk-[A-Za-z0-9]{32,}\b")),
|
|
80
|
+
("slack-token", re.compile(r"\bxox[baprs]-[A-Za-z0-9-]{10,}\b")),
|
|
81
|
+
("stripe-key", re.compile(r"\b(?:sk|pk)_(?:test|live)_[0-9a-zA-Z]{24,}\b")),
|
|
82
|
+
(
|
|
83
|
+
"private-key-block",
|
|
84
|
+
re.compile(r"-----BEGIN (?:RSA|EC|OPENSSH|DSA|PRIVATE) KEY-----"),
|
|
85
|
+
),
|
|
86
|
+
(
|
|
87
|
+
"generic-bearer-token",
|
|
88
|
+
re.compile(
|
|
89
|
+
r"\b(?:bearer|token|api[_-]?key|secret)\s*[:=]\s*[\"']?[A-Za-z0-9_-]{24,}[\"']?",
|
|
90
|
+
re.IGNORECASE,
|
|
91
|
+
),
|
|
92
|
+
),
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
# Absolute-path patterns. The operator's actual username is interpolated
|
|
96
|
+
# at scan time so non-operator usernames in test fixtures show up as a
|
|
97
|
+
# distinct (lower-severity) class.
|
|
98
|
+
_PATH_USERS_RE: Final[re.Pattern[str]] = re.compile(
|
|
99
|
+
r"(?<![\w/])(?:/Users/|/home/|[A-Z]:[\\/]Users[\\/])(?P<user>[A-Za-z0-9._-]+)[/\\]"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Email pattern matching anywhere; the BANNER_EMAIL is allow-listed.
|
|
103
|
+
_EMAIL_RE: Final[re.Pattern[str]] = re.compile(
|
|
104
|
+
r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _scan_secrets(rel: str, content: str) -> list[Hit]:
|
|
109
|
+
"""Walk content for secret-pattern matches."""
|
|
110
|
+
hits: list[Hit] = []
|
|
111
|
+
for lineno, line in enumerate(content.splitlines(), start=1):
|
|
112
|
+
for label, pattern in _SECRET_PATTERNS:
|
|
113
|
+
if pattern.search(line):
|
|
114
|
+
hits.append(
|
|
115
|
+
Hit(
|
|
116
|
+
file=rel,
|
|
117
|
+
line=lineno,
|
|
118
|
+
signal=f"secret-candidate: {label}",
|
|
119
|
+
severity=SEVERITY_HIGH,
|
|
120
|
+
remediation=(
|
|
121
|
+
"Treat as a credential leak: rotate the secret"
|
|
122
|
+
" upstream, remove the literal from the working"
|
|
123
|
+
" tree, and verify git-history removal before"
|
|
124
|
+
" any push to a remote."
|
|
125
|
+
),
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
break # one finding per line is enough
|
|
129
|
+
return hits
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _scan_pii(rel: str, content: str) -> list[Hit]:
|
|
133
|
+
"""Walk content for non-banner email occurrences."""
|
|
134
|
+
hits: list[Hit] = []
|
|
135
|
+
for lineno, line in enumerate(content.splitlines(), start=1):
|
|
136
|
+
for match in _EMAIL_RE.finditer(line):
|
|
137
|
+
email = match.group(0)
|
|
138
|
+
if email == BANNER_EMAIL:
|
|
139
|
+
continue
|
|
140
|
+
hits.append(
|
|
141
|
+
Hit(
|
|
142
|
+
file=rel,
|
|
143
|
+
line=lineno,
|
|
144
|
+
signal=f"non-banner-email: {email}",
|
|
145
|
+
severity=SEVERITY_MEDIUM,
|
|
146
|
+
remediation=(
|
|
147
|
+
"Replace with a vendor-neutral placeholder"
|
|
148
|
+
" (example.com), the canonical banner email, or"
|
|
149
|
+
" remove the contact data if not load-bearing."
|
|
150
|
+
),
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
return hits
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _scan_paths(rel: str, content: str) -> list[Hit]:
|
|
157
|
+
"""Walk content for absolute home-directory paths."""
|
|
158
|
+
hits: list[Hit] = []
|
|
159
|
+
for lineno, line in enumerate(content.splitlines(), start=1):
|
|
160
|
+
for match in _PATH_USERS_RE.finditer(line):
|
|
161
|
+
user = match.group("user")
|
|
162
|
+
severity = SEVERITY_MEDIUM if user == BANNER_USERNAME else SEVERITY_LOW
|
|
163
|
+
sig_kind = (
|
|
164
|
+
"operator-home-path"
|
|
165
|
+
if user == BANNER_USERNAME
|
|
166
|
+
else "non-operator-home-path"
|
|
167
|
+
)
|
|
168
|
+
hits.append(
|
|
169
|
+
Hit(
|
|
170
|
+
file=rel,
|
|
171
|
+
line=lineno,
|
|
172
|
+
signal=f"{sig_kind}: {match.group(0)}",
|
|
173
|
+
severity=severity,
|
|
174
|
+
remediation=(
|
|
175
|
+
"Replace the absolute path with a portable form"
|
|
176
|
+
" (~/, $HOME, %USERPROFILE%, or the host-discovered"
|
|
177
|
+
" environment variable that names the home root)."
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
return hits
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _scan_record(record: dict[str, Any], root: Path) -> list[Hit]:
|
|
185
|
+
"""Run all three scans against one inventory record.
|
|
186
|
+
|
|
187
|
+
All three scans (secrets, PII, paths) are restricted to narrative
|
|
188
|
+
classes. Memory JSONL session logs and plan-artifact files bind
|
|
189
|
+
per-machine state by design — flagging them as portability concerns
|
|
190
|
+
would generate noise that obscures the real findings in narrative
|
|
191
|
+
artifacts that DO get shared across hosts.
|
|
192
|
+
"""
|
|
193
|
+
cls = record.get("class", "")
|
|
194
|
+
if cls not in NARRATIVE_CLASSES:
|
|
195
|
+
return []
|
|
196
|
+
rel = record["path"]
|
|
197
|
+
path = root / rel
|
|
198
|
+
content = read_text_safely(path)
|
|
199
|
+
if not content:
|
|
200
|
+
return []
|
|
201
|
+
hits: list[Hit] = []
|
|
202
|
+
hits.extend(_scan_secrets(rel, content))
|
|
203
|
+
hits.extend(_scan_pii(rel, content))
|
|
204
|
+
hits.extend(_scan_paths(rel, content))
|
|
205
|
+
return hits
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def main(argv: list[str] | None = None) -> int:
|
|
209
|
+
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
210
|
+
parser.add_argument(
|
|
211
|
+
"--inventory",
|
|
212
|
+
type=Path,
|
|
213
|
+
default=Path(".audit/inventory.json"),
|
|
214
|
+
)
|
|
215
|
+
parser.add_argument("--root", type=Path, default=CONTENT_ROOT)
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
"--output",
|
|
218
|
+
type=Path,
|
|
219
|
+
default=Path(".audit/drift-secrets-pii.json"),
|
|
220
|
+
)
|
|
221
|
+
args = parser.parse_args(argv)
|
|
222
|
+
|
|
223
|
+
if not args.inventory.exists():
|
|
224
|
+
print(
|
|
225
|
+
f"error: inventory not found at {args.inventory}",
|
|
226
|
+
file=sys.stderr,
|
|
227
|
+
)
|
|
228
|
+
return 1
|
|
229
|
+
|
|
230
|
+
records, sha = load_inventory(args.inventory)
|
|
231
|
+
hits: list[Hit] = []
|
|
232
|
+
for record in records:
|
|
233
|
+
hits.extend(_scan_record(record, args.root))
|
|
234
|
+
emit_json(args.output, "scan_secrets_pii", hits, sha)
|
|
235
|
+
by_signal: dict[str, int] = {}
|
|
236
|
+
for h in hits:
|
|
237
|
+
kind = h.signal.split(":", 1)[0]
|
|
238
|
+
by_signal[kind] = by_signal.get(kind, 0) + 1
|
|
239
|
+
summary = ", ".join(f"{k}={v}" for k, v in sorted(by_signal.items()))
|
|
240
|
+
print(f"scan_secrets_pii: {len(hits)} hit(s) [{summary or 'none'}]")
|
|
241
|
+
return 0
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
raise SystemExit(main())
|