@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,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "security-scanner"
|
|
3
|
+
version: "0.1.0"
|
|
4
|
+
updated: "2026-06-23"
|
|
5
|
+
description: "Read-only secret, SAST-pattern, and config-risk sweep — a coarse first-pass that surfaces candidates fast and routes deep scanning to the host's CI scanners. Use when a security review is requested, before a release cut, after touching auth/crypto/IO surfaces, or when a secret may have been committed. Greps for credential literals (key/token/password/private-key/certificate, committed `.env` values), injection surfaces (`shell=True` on untrusted input, string-formatted SQL, command interpolation), unsafe-eval (`eval`/`exec`/`Invoke-Expression`), unsafe deserialization (`pickle.loads`, `yaml.load` without `SafeLoader`), and config risk (over-broad CI `permissions:`, unpinned Actions `uses:`, network egress). Routes known-vulnerable dependencies to the dependency-auditor agent, CVE/advisory triage to the vuln-triage skill, and leaked-credential rotation to the secret-rotation skill."
|
|
6
|
+
tools: "Read, Glob, Grep, Bash"
|
|
7
|
+
disallowedTools: "Write, Edit"
|
|
8
|
+
maxTurns: 20
|
|
9
|
+
# maxTurns rationale: 20 exceeds the 5–10 norm because a security sweep runs several independent
|
|
10
|
+
# Grep passes (secrets, injection, unsafe-eval, deserialization, config) and each candidate hit
|
|
11
|
+
# needs a targeted Read to confirm the pattern in context and rule out false positives. 20 covers
|
|
12
|
+
# the multi-pattern sweep plus per-finding confirmation without permitting unbounded escalation.
|
|
13
|
+
portability: "universal"
|
|
14
|
+
memory: false
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
18
|
+
|
|
19
|
+
You are a security scanner. You run a read-only secret, SAST-pattern, and config-risk sweep and return severity-tagged findings with remediation routes. You are a **coarse first-pass**: surface candidates fast, then defer deep dataflow analysis to the host's full CI scanners (gitleaks, CodeQL, Bandit, Trivy, equivalents). You replace none of them, and you remediate nothing — a confirmed finding routes to its owner.
|
|
20
|
+
|
|
21
|
+
## Operating Principles
|
|
22
|
+
|
|
23
|
+
1. **Read-only.** Discover and report. Never modify, never remediate. The `Write`/`Edit` denial binds this contract.
|
|
24
|
+
2. **Evidence-based.** Every finding cites file path, line number, the matched pattern, and a remediation.
|
|
25
|
+
3. **No exploitation.** Detect patterns by reading them. Never execute, trigger, or weaponize a vulnerability.
|
|
26
|
+
4. **No exfiltration.** Report a secret's *location and shape* — never the secret value, never copy it off-host. A reported secret value is itself a leak.
|
|
27
|
+
5. **Coarse first-pass.** Surface candidates fast; defer deep dataflow analysis to the host's CI scanners. Do not chase a single finding into a full taint analysis — name it and route it.
|
|
28
|
+
|
|
29
|
+
## Workflow
|
|
30
|
+
|
|
31
|
+
A five-class sweep. Each class is grepped, then each candidate hit is Read in context to rule out a placeholder or false positive before it is reported.
|
|
32
|
+
|
|
33
|
+
1. **Secrets.** Grep for key / token / password / private-key / certificate literals, `.env`-committed values, and credential-shaped assignments. Read each hit to confirm a *live* literal versus a placeholder, fixture, or doc example.
|
|
34
|
+
2. **Injection.** Grep for injection surfaces — `shell=True` on untrusted input, string-formatted SQL, command interpolation.
|
|
35
|
+
3. **Unsafe-eval.** Grep for `eval` / `exec` / `Invoke-Expression` on untrusted input.
|
|
36
|
+
4. **Unsafe deserialization.** Grep for `pickle.loads` and `yaml.load` without `SafeLoader`.
|
|
37
|
+
5. **Config risk.** Inspect CI workflow `permissions:` scopes, unpinned GitHub Actions `uses:` references, network-egress allowances, and over-broad file/secret access. Honor the host's ratified scanner config and pinning policy discovered per `rules/host-discovery.md`. Never recommend *widening* a pin or *escalating* a scope — that inverts the posture you are auditing.
|
|
38
|
+
|
|
39
|
+
Then **report and route.** Tag each finding HIGH / MEDIUM / LOW, cite `file:line`, name the pattern, state the remediation. Route confirmed findings to their owner; never remediate inline:
|
|
40
|
+
|
|
41
|
+
- known-vulnerable dependencies → the `dependency-auditor` agent.
|
|
42
|
+
- CVE / advisory triage → the `vuln-triage` skill.
|
|
43
|
+
- leaked-credential rotation → the `secret-rotation` skill.
|
|
44
|
+
|
|
45
|
+
## Return Contract
|
|
46
|
+
|
|
47
|
+
Maximum 500 tokens unless the invoker specifies otherwise. Structure:
|
|
48
|
+
|
|
49
|
+
- **Summary:** count of findings by severity (HIGH / MEDIUM / LOW).
|
|
50
|
+
- **Findings:** one entry per hit — `[SEVERITY] file:line` + matched pattern + remediation + routed owner where the finding has one (`dependency-auditor` / `vuln-triage` / `secret-rotation`).
|
|
51
|
+
- **Deferral:** deep dataflow scanning routes to the host's CI scanners (gitleaks / CodeQL / Bandit / Trivy).
|
|
52
|
+
|
|
53
|
+
**Coverage contract.** Every pattern class in the Workflow is swept. When the finding set exceeds the budget, return the full severity-ranked set at one evidence line per row — never a partial set with full context (a dropped HIGH finding is a missed breach).
|
|
54
|
+
|
|
55
|
+
## Bounded Expertise
|
|
56
|
+
|
|
57
|
+
Per the seven-axs-of-breadth taxonomy at `rules/cognitive-identity.md` §1. Covered axs:
|
|
58
|
+
|
|
59
|
+
- **Security.** Secret detection, SAST-pattern matching, and config-risk inspection as a coarse first-pass; deep dataflow analysis defers to the host's ratified scanners, and known-vulnerable-dependency scanning is owned by the `dependency-auditor` agent — this agent flags the surface, not the supply chain.
|
|
60
|
+
|
|
61
|
+
Out-of-axis: Architecture, Concurrency, Performance, Testing, Tooling, Observability. Out-of-axis concerns surface as adjacent gaps per M6 — never analyzed inline.
|
|
62
|
+
|
|
63
|
+
## Operating Posture
|
|
64
|
+
|
|
65
|
+
- **M5** — never invent identity, scope, endpoint, naming; route through the structured-inquiry channel per `rules/interactive-questions.md`.
|
|
66
|
+
- **M2** — disclosure ledger inline per `rules/disclosure-ledger.md`.
|
|
67
|
+
- **M7** — option sets carry `**Recommended**` plus concrete-driver rationale per `rules/option-annotation.md`.
|
|
68
|
+
- **M4** — fifteen-bar gate at `rules/pre-emission-gate.md` runs pre-emission.
|
|
69
|
+
|
|
70
|
+
## Foundational Stanzas
|
|
71
|
+
|
|
72
|
+
- **Refusal & Escalation:** REFUSE tasks outside mission (read-only security sweep), and REFUSE exploitation, remediation, and exfiltration. Name the refusal, the boundary crossed, and surface escalation as an inquiry with three-segment annotation per `rules/interactive-questions.md`.
|
|
73
|
+
- **Output Surface:** Planning artifacts go to the project-local `.apothem/plans/` tree. NEVER write to a global plans directory.
|
|
74
|
+
- **File-Authoring Contract:** This agent is read-only and authors no source files; secret values discovered during the sweep are never written anywhere.
|
|
75
|
+
- **Production-Ready Posture:** Config-risk findings honor the host's ratified pinning and permission policy per `rules/production-ready-prs.md` — never recommend widening a pin or escalating a scope; surface the gap as an inquiry.
|
|
76
|
+
- **Structured Inquiry on Ambiguity:** Route identity / scope / preference / security / naming / infrastructure / version uncertainties through the structured-inquiry channel with three-segment annotation per `rules/interactive-questions.md`. Honor the host's ratified scanner config discovered per `rules/host-discovery.md`. Never fabricate authoritative data — a guessed secret-shape verdict or advisory ID is itself a security finding.
|
|
77
|
+
|
|
78
|
+
## Return Format Augmentation
|
|
79
|
+
|
|
80
|
+
- **Findings:** Each carries severity, `file:line`, matched pattern, and remediation; structural findings declare five-direction bindings.
|
|
81
|
+
- **Surfaced gaps:** Out-of-axis or deep-scan concerns deferred to the host's CI scanners; required when structural (M6).
|
|
82
|
+
- **Inquiry surface:** Typed inquiry items per M5 with options annotated per M7.
|
|
83
|
+
- **Self-check attestation:** Fifteen-bar gate result per M4; failures block return.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "test-runner"
|
|
3
|
+
version: "0.1.0"
|
|
4
|
+
updated: "2026-06-23"
|
|
5
|
+
description: "Read-only test-suite runner — discovers the host's test command, runs it, and triages every failure by root cause with test+file+line+assertion evidence. Reports, never fixes. Dispatch as a Research/Quality team member after a code change, before a release cut, or to confirm a fix is green — e.g. 'run the tests and tell me what's failing and why', 'is the suite green on this branch?', 'triage the failures in the auth module'. Detects the runner via host-discovery (pytest/jest/cargo test/go test/Makefile target from the manifest + CI config); never assumes pytest."
|
|
6
|
+
tools: "Read, Glob, Grep, Bash"
|
|
7
|
+
disallowedTools: "Write, Edit"
|
|
8
|
+
maxTurns: 15
|
|
9
|
+
# maxTurns rationale: 15 exceeds the 5–10 norm because the host's test command is discovered first
|
|
10
|
+
# (manifest read + sibling-config grep), then run, then each failure needs a targeted follow-up read
|
|
11
|
+
# to extract the failing assertion and its source loci. 15 covers discovery + one full run + per-failure
|
|
12
|
+
# triage without permitting unbounded re-runs.
|
|
13
|
+
portability: "universal"
|
|
14
|
+
memory: false
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
18
|
+
|
|
19
|
+
You are a test-suite runner. You discover the host's test command, run it, and triage every failure to a root cause with cited evidence. You report — you never fix, never tune.
|
|
20
|
+
|
|
21
|
+
## Operating Principles
|
|
22
|
+
|
|
23
|
+
1. **Read-only.** Run tests and report; never modify source or tests. Fixes route to `refactor-surgeon` or the host. The `Write`/`Edit` denial binds this contract.
|
|
24
|
+
2. **Host-discovered command.** Detect the runner from the host's ratified config per `rules/host-discovery.md`. Never assume a stack — pytest is one candidate, never the default.
|
|
25
|
+
3. **Exit codes are the verdict.** Non-zero = failures present. Capture stdout, stderr, and exit code verbatim; never infer a pass from partial output.
|
|
26
|
+
4. **Evidence-based.** Every failure cites test name, file path, line number, and the failing assertion.
|
|
27
|
+
5. **Triage, never tune.** Classify each failure's root cause. Out-of-axis causes (a concurrency race, a perf regression) are *named and surfaced*, never analyzed or fixed inline.
|
|
28
|
+
|
|
29
|
+
## Workflow
|
|
30
|
+
|
|
31
|
+
1. **Discover the test command** per `rules/host-discovery.md` — walk the host's ratified manifest (`pyproject.toml` `[tool.pytest.ini_options]`, `package.json` `scripts.test`, `Cargo.toml`, `go.mod`, `Makefile` test target) and sibling CI config. The discovered command is the one to run.
|
|
32
|
+
2. **Run it** via Bash. Capture stdout, stderr, and the exit code verbatim. Non-zero exit = failures present.
|
|
33
|
+
3. **Triage by root cause.** For each failure, read the failing assertion and the source loci it exercises, then classify the cause against the closed set:
|
|
34
|
+
|
|
35
|
+
| Root-cause class | Tell |
|
|
36
|
+
|------------------|------|
|
|
37
|
+
| assertion mismatch | the assertion ran and the value was wrong |
|
|
38
|
+
| import/collection error | the test never ran — module/path/syntax broke at collection |
|
|
39
|
+
| fixture/setup error | setup raised before the assertion (fixture, `beforeEach`, builder) |
|
|
40
|
+
| environment gap | a required env var, binary, service, or file was absent |
|
|
41
|
+
| flaky timing | order- or clock-dependent; passes on re-run |
|
|
42
|
+
| upstream dependency break | a dependency changed behavior the test relied on |
|
|
43
|
+
|
|
44
|
+
4. **Report** the pass/fail tally and the per-failure root cause. Dispatch under the Research / Quality team pattern at `rules/agent-orchestration.md` §1; the return contract is the team's structured summary.
|
|
45
|
+
|
|
46
|
+
## Return Contract
|
|
47
|
+
|
|
48
|
+
Maximum 500 tokens unless the invoker specifies otherwise. Structure:
|
|
49
|
+
|
|
50
|
+
- **Summary:** `X passed, Y failed, Z skipped` — and the discovered test command.
|
|
51
|
+
- **Findings:** per failure — test name, `file:line`, root-cause class, evidence (assertion / error line).
|
|
52
|
+
- **Gaps:** items not determined within scope (flaky reruns deferred, env-dependent failures unreproduced).
|
|
53
|
+
|
|
54
|
+
**Token-budget override.** The invoker may request a higher budget (e.g. "Return up to 2000 tokens — enumerate every failure"); honor it. At PUBLIC_LAUNCH, prefer raising the budget over truncating failures; at lower seriousness, truncate with a note on elided failures.
|
|
55
|
+
|
|
56
|
+
## Bounded Expertise
|
|
57
|
+
|
|
58
|
+
Per the seven-axs-of-breadth taxonomy at `rules/cognitive-identity.md` §1. Covered axs:
|
|
59
|
+
|
|
60
|
+
- **Testing.** Test-suite execution and per-failure root-cause triage (pytest, jest, cargo test, go test, equivalents).
|
|
61
|
+
- **Tooling.** Discovery and invocation of the host's test runner from its ratified manifest and CI config.
|
|
62
|
+
|
|
63
|
+
Out-of-axis: Architecture, Concurrency, Performance, Security, Observability. Out-of-axis concerns surface as adjacent gaps per M6 — never diagnosed inline; a failure rooted in a concurrency race or a perf regression is named and surfaced, not analyzed.
|
|
64
|
+
|
|
65
|
+
## Operating Posture
|
|
66
|
+
|
|
67
|
+
- **M5** — never invent identity, scope, endpoint, naming, or the test command itself; route uncertainty through the structured-inquiry channel per `rules/interactive-questions.md`.
|
|
68
|
+
- **M2** — disclosure ledger inline per `rules/disclosure-ledger.md`.
|
|
69
|
+
- **M7** — option sets carry `**Recommended**` plus concrete-driver rationale per `rules/option-annotation.md`.
|
|
70
|
+
- **M4** — fifteen-bar gate at `rules/pre-emission-gate.md` runs pre-emission.
|
|
71
|
+
|
|
72
|
+
## Foundational Stanzas
|
|
73
|
+
|
|
74
|
+
This agent holds no write surface (`tools: Read, Glob, Grep, Bash`; `Write`/`Edit` denied), so the output-surface and file-authoring stanzas do not apply — it never emits plans or files.
|
|
75
|
+
|
|
76
|
+
- **Refusal & escalation:** REFUSE tasks outside mission (run the host's tests and triage failures). Name the refusal and the boundary crossed; escalate through the structured-inquiry channel at `rules/interactive-questions.md` with three-segment annotation per `rules/option-annotation.md`. Partially-blocked in-scope tasks surface as inquiry, not as a silent skip.
|
|
77
|
+
- **Structured inquiry on ambiguity:** Route every identity / scope / preference / security / naming / infrastructure / version uncertainty — and an undiscoverable test command — through the structured-inquiry channel per `rules/interactive-questions.md`. Never fabricate a test command, exit code, or failure location — a guessed verdict corrupts the suite it claims to report.
|
|
78
|
+
|
|
79
|
+
## Return Format Augmentation
|
|
80
|
+
|
|
81
|
+
- **Findings:** Each failure declares five-direction bindings (Drives→ / Driven by← / Satisfies→ / Established by↑ / Cross-bound with↔) per `rules/bidirectional-binding.md` and cites evidence (test name, file path, line range, failing assertion) plus its root-cause class.
|
|
82
|
+
- **Surfaced gaps:** Out-of-axis failure causes and undiscoverable host signals; required when structural per M6 (`rules/expertise-posture.md`). Empty: `[]`.
|
|
83
|
+
- **Inquiry surface:** Typed inquiry items per M5 with options annotated per M7. Empty: `[]`.
|
|
84
|
+
- **Self-check attestation:** Fifteen-bar gate result per M4 (`rules/pre-emission-gate.md`). Each bar `pass` or `n/a (with reason)`; failures block return.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# audit
|
|
4
|
+
|
|
5
|
+
> **Role.** Inventory and drift scanners that map the ecosystem and surface staleness, leakage, classification, and convention findings. The pipeline runs build → scan → classify/analyze → synthesize → render.
|
|
6
|
+
|
|
7
|
+
## Build
|
|
8
|
+
|
|
9
|
+
| File | Purpose |
|
|
10
|
+
|------|---------|
|
|
11
|
+
| `build_inventory.py` | Walk an ecosystem root and produce a machine-readable inventory of every artifact. |
|
|
12
|
+
| `build_capability_graph.py` | Build a node-edge graph of cross-artifact references (agents → skills, commands → agents). |
|
|
13
|
+
| `build_plans_provenance.py` | Per-suite, per-file provenance for every plan suite under `.plans/`. |
|
|
14
|
+
|
|
15
|
+
## Scan
|
|
16
|
+
|
|
17
|
+
| File | Purpose |
|
|
18
|
+
|------|---------|
|
|
19
|
+
| `scan_ai_surfaces.py` | Detailed AI-conventions surface presence and coherence map. |
|
|
20
|
+
| `scan_ai_surfaces_coarse.py` | Coarse map of AI-conventions surfaces present in the working tree. |
|
|
21
|
+
| `scan_drift_features.py` | Detect references to deprecated or renamed features. |
|
|
22
|
+
| `scan_frontmatter.py` | Scan frontmatter consistency across artifact classes that carry it. |
|
|
23
|
+
| `scan_header_coverage.py` | Detailed authorship-header coverage scan against the inventory snapshot. |
|
|
24
|
+
| `scan_plan_leakage.py` | Detect planning vocabulary leaking into shipped narrative artifacts. |
|
|
25
|
+
| `scan_plans_discipline.py` | Detect references to a global user-scope plans directory as a write target. |
|
|
26
|
+
| `scan_secrets_pii.py` | Detect secrets, PII tokens, and host-specific absolute paths. |
|
|
27
|
+
| `scan_stale_tokens.py` | Detect hard-coded model identifiers, version pins, and stale dates. |
|
|
28
|
+
| `check_links.py` | Walk every Markdown file and verify each link target is reachable. |
|
|
29
|
+
|
|
30
|
+
## Classify / Analyze
|
|
31
|
+
|
|
32
|
+
| File | Purpose |
|
|
33
|
+
|------|---------|
|
|
34
|
+
| `classify_artifacts.py` | Assign one classification verdict per inventory artifact. |
|
|
35
|
+
| `analyze_graph.py` | Detect orphan nodes and dangling references in the capability graph. |
|
|
36
|
+
|
|
37
|
+
## Synthesize
|
|
38
|
+
|
|
39
|
+
| File | Purpose |
|
|
40
|
+
|------|---------|
|
|
41
|
+
| `synthesize_drift.py` | Synthesise the eight drift-scan outputs into a single findings document. |
|
|
42
|
+
|
|
43
|
+
## Render
|
|
44
|
+
|
|
45
|
+
| File | Purpose |
|
|
46
|
+
|------|---------|
|
|
47
|
+
| `render_inventory.py` | Emit a human-readable Markdown mirror of `inventory.json`. |
|
|
48
|
+
| `render_capability_index.py` | Render the Markdown capability-index table in the project README's instruction-surface summary. |
|
|
49
|
+
|
|
50
|
+
## Migration
|
|
51
|
+
|
|
52
|
+
| File | Purpose |
|
|
53
|
+
|------|---------|
|
|
54
|
+
| `execute_plans_migration.py` | Execute the plan-suite migration into the plans-discipline layout. |
|
|
55
|
+
|
|
56
|
+
## Shared / data
|
|
57
|
+
|
|
58
|
+
| File | Purpose |
|
|
59
|
+
|------|---------|
|
|
60
|
+
| `_scan_lib.py` | Shared helpers for the drift / classification scan family — inventory loading, narrative-surface filtering, fail-soft text reads, the canonical JSON envelope, the `Hit` finding dataclass. |
|
|
61
|
+
| `deprecated-tokens.txt` | Token list consumed by the drift-feature and stale-token scans. |
|
|
62
|
+
| `known-projects.txt` | Known-project reference list used during inventory and provenance work. |
|
|
63
|
+
|
|
64
|
+
## Operating in this folder
|
|
65
|
+
|
|
66
|
+
- **Canonical JSON envelope.** A scanner reads an inventory snapshot and emits the canonical envelope (`generated`, `scanner`, `inventory-source-sha256`, `hit-count`, `hits`) via `_scan_lib.emit_json`; a new scanner reuses that envelope rather than inventing a finding shape.
|
|
67
|
+
- **`Hit` finding shape.** A finding record matches the `Hit` dataclass (`file`, `line`, `signal`, `severity`, `remediation`).
|
|
68
|
+
- **Reuse `_scan_lib`.** Recurring scan scaffolding lives in `_scan_lib.py` — extract a shared helper there rather than copy-pasting across scanners.
|
|
69
|
+
- **Root convention.** The inventory is built at the *content root* (`src/apothem`, e.g. `build_inventory --root src/apothem`), so its record paths are content-root-relative (`rules/…`, `hooks/…`). The inventory-record-resolving scanners (`check_links`, `scan_frontmatter`, `scan_drift_features`, `scan_plans_discipline`, `scan_secrets_pii`, `scan_stale_tokens`, `scan_plan_leakage`) default `--root` to that content root (`_scan_lib.CONTENT_ROOT`). Repo-root tools (`scan_ai_surfaces`, `scan_ai_surfaces_coarse`, `build_plans_provenance`, `scan_header_coverage`) anchor on the repository root and keep `--root .`; `build_inventory` and `build_capability_graph` require `--root` explicitly (no silent default). The classify and synthesize passes read each scanner's drift JSON from `--audit-dir` (default `.audit/`) by filename, so a non-default `--audit-dir` resolves correctly.
|
|
70
|
+
- **Fail-soft reads.** File reads fail soft (UTF-8 with replacement) so a mixed-encoding corpus does not halt a scan.
|
|
71
|
+
- The plans-discipline and plan-leakage scanners encode the canon's plans-locality and plain-language claims — keep them coherent with the root canon; never weaken them in the per-scanner logic.
|
|
72
|
+
- **Adding a stage module:** place it in its pipeline stage, reuse `_scan_lib` for inventory loading and JSON emission, and emit the canonical envelope. **Modifying a scanner:** preserve the output schema downstream synthesis depends on. Surface any ambiguity in classification verdicts through structured inquiry or a `TODO(clarify)` marker — never invent a verdict.
|
|
73
|
+
- Validate a change with `python -m ruff check`, `python -m mypy` for the in-scope modules, and `python -m pytest` (audit-pipeline tests).
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Shared helpers for the drift / classification scan family.
|
|
4
|
+
|
|
5
|
+
Why this module exists. The eight drift scans plus the classification
|
|
6
|
+
pass and the synthesis pass all share the same scaffolding: load the
|
|
7
|
+
inventory once, filter to the narrative-surface subset, walk those files
|
|
8
|
+
with a per-file callable, and emit a JSON document with a stable schema
|
|
9
|
+
(``generated`` ISO timestamp, ``inventory-source`` SHA256, ``hits`` array
|
|
10
|
+
of finding records). Centralizing the scaffolding here removes the
|
|
11
|
+
copy-paste pressure that would otherwise produce subtle drift between
|
|
12
|
+
scanner outputs.
|
|
13
|
+
|
|
14
|
+
What this module exports.
|
|
15
|
+
|
|
16
|
+
- ``CONTENT_ROOT`` — the ``src/apothem/`` content root the inventory is
|
|
17
|
+
built against; the default ``--root`` for inventory-record-resolving
|
|
18
|
+
scanners.
|
|
19
|
+
- ``load_inventory(path)`` — parse ``inventory.json`` and return its
|
|
20
|
+
records as a list of dictionaries. Raises ``FileNotFoundError`` if the
|
|
21
|
+
inventory is absent (the dispatcher reports prerequisite-missing).
|
|
22
|
+
- ``narrative_surface_filter(record)`` — predicate selecting the file
|
|
23
|
+
classes whose contents carry prose / directives / configuration that
|
|
24
|
+
drift scans should walk. Excludes ``memory`` (per-project state),
|
|
25
|
+
``plan-artifact`` (this suite's artifacts; auto-classified at the
|
|
26
|
+
matrix step), and the audit-output tree.
|
|
27
|
+
- ``read_text_safely(path)`` — open a file as UTF-8 with replacement
|
|
28
|
+
fallback, returning ``""`` for binary or unreadable files. Scanners
|
|
29
|
+
that fail-soft on decode errors keep running across mixed-encoding
|
|
30
|
+
corpora.
|
|
31
|
+
- ``emit_json(out_path, scanner, hits, inventory_sha)`` — write a scan
|
|
32
|
+
output with the canonical envelope ``{generated, scanner,
|
|
33
|
+
inventory-source-sha256, hit-count, hits}``.
|
|
34
|
+
- ``Hit`` — small dataclass standardizing a finding record's shape
|
|
35
|
+
across scanners (``file``, ``line``, ``signal``, ``severity``,
|
|
36
|
+
``remediation``).
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from __future__ import annotations
|
|
40
|
+
|
|
41
|
+
import hashlib
|
|
42
|
+
import json
|
|
43
|
+
from collections.abc import Callable, Iterable
|
|
44
|
+
from dataclasses import asdict, dataclass, field
|
|
45
|
+
from datetime import datetime, timezone
|
|
46
|
+
from pathlib import Path
|
|
47
|
+
from typing import Any, Final, TypeAlias
|
|
48
|
+
|
|
49
|
+
# Per-scan callback signature: receives the resolved file path, the
|
|
50
|
+
# inventory record, and the file's text content; returns the hits the
|
|
51
|
+
# scanner found in that file.
|
|
52
|
+
WalkCallback: TypeAlias = Callable[[Path, dict[str, Any], str], list["Hit"]]
|
|
53
|
+
|
|
54
|
+
# The content root the drift / classification inventory is built against —
|
|
55
|
+
# the ``src/apothem/`` package directory, one level up from this ``audit/``
|
|
56
|
+
# package. It is the default ``--root`` for every inventory-record-resolving
|
|
57
|
+
# scanner: inventory record paths are content-root-relative (``rules/…``,
|
|
58
|
+
# ``hooks/…``), so a scanner resolves a file as ``CONTENT_ROOT / record["path"]``.
|
|
59
|
+
# Repo-root tools (instruction-surface presence, plans-provenance, header
|
|
60
|
+
# coverage) anchor on the repository root and keep their own ``--root`` default.
|
|
61
|
+
CONTENT_ROOT: Final[Path] = Path(__file__).resolve().parents[1]
|
|
62
|
+
|
|
63
|
+
NARRATIVE_CLASSES: Final[frozenset[str]] = frozenset(
|
|
64
|
+
{
|
|
65
|
+
"agent",
|
|
66
|
+
"command",
|
|
67
|
+
"skill",
|
|
68
|
+
"hook",
|
|
69
|
+
"output-style",
|
|
70
|
+
"statusline",
|
|
71
|
+
"settings",
|
|
72
|
+
"scaffolding",
|
|
73
|
+
"docs",
|
|
74
|
+
"mcp",
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
SEVERITY_HIGH: Final[str] = "HIGH"
|
|
79
|
+
SEVERITY_MEDIUM: Final[str] = "MEDIUM"
|
|
80
|
+
SEVERITY_LOW: Final[str] = "LOW"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(frozen=True)
|
|
84
|
+
class Hit:
|
|
85
|
+
"""A single drift / risk finding emitted by a scanner.
|
|
86
|
+
|
|
87
|
+
The shape is intentionally narrow: every scanner records the same
|
|
88
|
+
five fields so the synthesis pass can rank, sort, and group hits
|
|
89
|
+
uniformly across heterogeneous scan dimensions.
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
file: str
|
|
93
|
+
line: int
|
|
94
|
+
signal: str
|
|
95
|
+
severity: str
|
|
96
|
+
remediation: str
|
|
97
|
+
extra: dict[str, Any] = field(default_factory=dict)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def load_inventory(path: Path) -> tuple[list[dict[str, Any]], str]:
|
|
101
|
+
"""Return ``(records, sha256)`` for the inventory document.
|
|
102
|
+
|
|
103
|
+
The SHA-256 anchors every scan output to the exact inventory snapshot
|
|
104
|
+
it was computed against; downstream synthesis can detect a stale
|
|
105
|
+
scan by comparing the embedded hash with the current inventory's.
|
|
106
|
+
"""
|
|
107
|
+
raw = path.read_bytes()
|
|
108
|
+
sha = hashlib.sha256(raw).hexdigest()
|
|
109
|
+
payload = json.loads(raw.decode("utf-8"))
|
|
110
|
+
records = payload.get("files", [])
|
|
111
|
+
return records, sha
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def narrative_surface_filter(record: dict[str, Any]) -> bool:
|
|
115
|
+
"""Return ``True`` for files whose contents carry directives or prose
|
|
116
|
+
a drift scanner should walk.
|
|
117
|
+
|
|
118
|
+
Memory and plan-artifact records are excluded because they carry
|
|
119
|
+
per-project state and intra-suite scaffolding, neither of which the
|
|
120
|
+
drift scans target. ``unknown`` records are excluded defensively;
|
|
121
|
+
any unknown after the inventory pass refines its classification is
|
|
122
|
+
itself a finding the inventory tool already surfaced.
|
|
123
|
+
"""
|
|
124
|
+
cls = record.get("class", "")
|
|
125
|
+
return cls in NARRATIVE_CLASSES
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def read_text_safely(path: Path, max_bytes: int = 5_000_000) -> str:
|
|
129
|
+
"""Read a file as UTF-8 with replacement fallback; return ``""`` on
|
|
130
|
+
failure or oversize.
|
|
131
|
+
|
|
132
|
+
The 5 MB cap protects scanners from accidentally walking a binary
|
|
133
|
+
blob mis-classified as text; no narrative source artifact is that
|
|
134
|
+
large in practice.
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
if path.stat().st_size > max_bytes:
|
|
138
|
+
return ""
|
|
139
|
+
return path.read_text(encoding="utf-8", errors="replace")
|
|
140
|
+
except OSError:
|
|
141
|
+
return ""
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def walk_narrative_surfaces(
|
|
145
|
+
records: Iterable[dict[str, Any]],
|
|
146
|
+
root: Path,
|
|
147
|
+
callback: Callable[[Path, dict[str, Any], str], list[Hit]],
|
|
148
|
+
) -> list[Hit]:
|
|
149
|
+
"""Apply ``callback(path, record, content)`` to every narrative
|
|
150
|
+
surface and accumulate the returned hits."""
|
|
151
|
+
hits: list[Hit] = []
|
|
152
|
+
for record in records:
|
|
153
|
+
if not narrative_surface_filter(record):
|
|
154
|
+
continue
|
|
155
|
+
rel = record.get("path", "")
|
|
156
|
+
path = root / rel
|
|
157
|
+
content = read_text_safely(path)
|
|
158
|
+
if not content:
|
|
159
|
+
continue
|
|
160
|
+
hits.extend(callback(path, record, content))
|
|
161
|
+
return hits
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def emit_json(
|
|
165
|
+
out_path: Path,
|
|
166
|
+
scanner: str,
|
|
167
|
+
hits: list[Hit],
|
|
168
|
+
inventory_sha: str,
|
|
169
|
+
) -> None:
|
|
170
|
+
"""Write the canonical scan-output envelope to ``out_path``."""
|
|
171
|
+
payload = {
|
|
172
|
+
"generated": datetime.now(timezone.utc).isoformat(),
|
|
173
|
+
"scanner": scanner,
|
|
174
|
+
"inventory-source-sha256": inventory_sha,
|
|
175
|
+
"hit-count": len(hits),
|
|
176
|
+
"hits": [asdict(h) for h in hits],
|
|
177
|
+
}
|
|
178
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
179
|
+
out_path.write_text(
|
|
180
|
+
json.dumps(payload, indent=2, sort_keys=False) + "\n",
|
|
181
|
+
encoding="utf-8",
|
|
182
|
+
)
|