@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,472 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Session-start bootstrap hook for the apothem ecosystem.
|
|
4
|
+
|
|
5
|
+
Gathers ecosystem context at SessionStart and emits a single-line JSON
|
|
6
|
+
envelope: ``{"hookSpecificOutput":{"hookEventName":"SessionStart",...}}``.
|
|
7
|
+
|
|
8
|
+
The bootstrap produces a plaintext `additionalContext` payload composed
|
|
9
|
+
of up to three sections:
|
|
10
|
+
|
|
11
|
+
* **Session bootstrap** — source, model, and agent-type echoed back from
|
|
12
|
+
the hook's stdin JSON (optional).
|
|
13
|
+
* **Memory summary** — first lines of ``## Project Overview``,
|
|
14
|
+
``**Latest:**`` value, topic file names, and top bullets from
|
|
15
|
+
``## Key Conventions`` in the project's ``MEMORY.md`` index.
|
|
16
|
+
* **Plan summary** — the most recently modified plan suite (if any) and
|
|
17
|
+
key fields pulled from its ``PROGRESS.md``.
|
|
18
|
+
|
|
19
|
+
Any unexpected exception is caught at the outermost boundary; a valid
|
|
20
|
+
failure envelope is emitted and the process exits 0.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import argparse
|
|
26
|
+
import os
|
|
27
|
+
import re
|
|
28
|
+
import sys
|
|
29
|
+
from collections.abc import Iterator
|
|
30
|
+
from dataclasses import dataclass, field
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
from typing import Final
|
|
33
|
+
|
|
34
|
+
_HOOKS_DIR: Final[Path] = Path(__file__).resolve().parent
|
|
35
|
+
_LIB_DIR: Final[Path] = _HOOKS_DIR / "lib"
|
|
36
|
+
_PLAN_SUITES_DIR: Final[str] = os.environ.get("LLM_PLAN_SUITES_DIR", ".plans")
|
|
37
|
+
|
|
38
|
+
# Cap on how many bulleted items (topic files, key conventions) the
|
|
39
|
+
# bootstrap surfaces. Both the display slices in the summary
|
|
40
|
+
# dataclasses and the parser-function defaults below pull from this
|
|
41
|
+
# constant, so the slice acts as a safety belt: if a parser is later
|
|
42
|
+
# called with a wider limit elsewhere, the bootstrap output still
|
|
43
|
+
# stays bounded at this width.
|
|
44
|
+
_BULLET_PREVIEW_LIMIT: Final[int] = 3
|
|
45
|
+
|
|
46
|
+
# Cap on how many numbered items (critical files for the next phase)
|
|
47
|
+
# the bootstrap surfaces. Larger than the bullet cap because the
|
|
48
|
+
# critical-files list is the manifest a fresh session reads first to
|
|
49
|
+
# pick up where the prior session left off; five items keeps that
|
|
50
|
+
# surface useful without bloating the SessionStart envelope.
|
|
51
|
+
_NUMBERED_PREVIEW_LIMIT: Final[int] = 5
|
|
52
|
+
# Insert both paths so ``from emit_hook_context import …`` works whether
|
|
53
|
+
# this script is invoked directly or via ``dispatch.py`` (which adds
|
|
54
|
+
# ``_HOOKS_DIR`` itself). Without the hooks-dir entry, direct invocation
|
|
55
|
+
# raises ``ModuleNotFoundError`` because ``emit_hook_context`` lives in
|
|
56
|
+
# ``hooks/``, not ``hooks/lib/``.
|
|
57
|
+
for _path in (_HOOKS_DIR, _LIB_DIR):
|
|
58
|
+
if str(_path) not in sys.path:
|
|
59
|
+
sys.path.insert(0, str(_path))
|
|
60
|
+
|
|
61
|
+
from emit_hook_context import ( # noqa: E402
|
|
62
|
+
emit_failure_envelope,
|
|
63
|
+
emit_hook_envelope,
|
|
64
|
+
normalize_ascii,
|
|
65
|
+
read_hook_stdin,
|
|
66
|
+
)
|
|
67
|
+
from log import get_logger # noqa: E402
|
|
68
|
+
from resolve_root import Mode, resolve_project_root # noqa: E402
|
|
69
|
+
|
|
70
|
+
_logger = get_logger(__name__)
|
|
71
|
+
|
|
72
|
+
_H2 = re.compile(r"^##\s+(.+?)\s*$")
|
|
73
|
+
_BOLD_FIELD = re.compile(r"^\*\*([^:*]+):\*\*\s*(.*?)\s*$")
|
|
74
|
+
_BULLET = re.compile(r"^\s*-\s+(.+?)\s*$")
|
|
75
|
+
_NUMBERED = re.compile(r"^\s*\d+\.\s+(.+?)\s*$")
|
|
76
|
+
_MARKDOWN_LINK = re.compile(r"\[[^\]]+\]\(([^)]+\.md)\)")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass(frozen=True)
|
|
80
|
+
class SessionMeta:
|
|
81
|
+
"""Metadata echoed from the hook's stdin payload."""
|
|
82
|
+
|
|
83
|
+
source: str = ""
|
|
84
|
+
model: str = ""
|
|
85
|
+
agent_type: str = ""
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def from_payload(cls, payload: dict[str, object] | None) -> SessionMeta:
|
|
89
|
+
"""Extract session-bootstrap fields from a stdin payload."""
|
|
90
|
+
if not payload:
|
|
91
|
+
return cls()
|
|
92
|
+
return cls(
|
|
93
|
+
source=_as_str(payload.get("source")),
|
|
94
|
+
model=_as_str(payload.get("model")),
|
|
95
|
+
agent_type=_as_str(payload.get("agent_type")),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def lines(self) -> list[str]:
|
|
99
|
+
"""Return the bullet-list lines for this metadata block."""
|
|
100
|
+
rows: list[str] = []
|
|
101
|
+
if self.source:
|
|
102
|
+
rows.append(f"- Session source: {self.source}")
|
|
103
|
+
if self.model:
|
|
104
|
+
rows.append(f"- Model: {self.model}")
|
|
105
|
+
if self.agent_type:
|
|
106
|
+
rows.append(f"- Agent: {self.agent_type}")
|
|
107
|
+
return rows
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class MemorySummary:
|
|
112
|
+
"""Structured view of a ``MEMORY.md`` index file."""
|
|
113
|
+
|
|
114
|
+
overview: str = ""
|
|
115
|
+
latest: str = ""
|
|
116
|
+
topic_files: list[str] = field(default_factory=list)
|
|
117
|
+
key_conventions: list[str] = field(default_factory=list)
|
|
118
|
+
|
|
119
|
+
def lines(self) -> list[str]:
|
|
120
|
+
"""Return the bullet-list lines for this memory block."""
|
|
121
|
+
rows: list[str] = []
|
|
122
|
+
if self.overview:
|
|
123
|
+
rows.append(f"- Project overview: {self.overview}")
|
|
124
|
+
if self.latest:
|
|
125
|
+
rows.append(f"- Latest memory entry: {self.latest}")
|
|
126
|
+
if self.topic_files:
|
|
127
|
+
preview = ", ".join(self.topic_files[:_BULLET_PREVIEW_LIMIT])
|
|
128
|
+
rows.append(f"- Topic files: {preview}")
|
|
129
|
+
for convention in self.key_conventions[:_BULLET_PREVIEW_LIMIT]:
|
|
130
|
+
rows.append(f"- Convention: {convention}")
|
|
131
|
+
return rows
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass
|
|
135
|
+
class PlanSummary:
|
|
136
|
+
"""Structured view of an active plan suite."""
|
|
137
|
+
|
|
138
|
+
suite_name: str = ""
|
|
139
|
+
status: str = ""
|
|
140
|
+
phase_in_progress: str = ""
|
|
141
|
+
task_in_progress: str = ""
|
|
142
|
+
next_action: str = ""
|
|
143
|
+
blockers: str = ""
|
|
144
|
+
critical_files: list[str] = field(default_factory=list)
|
|
145
|
+
|
|
146
|
+
def lines(self) -> list[str]:
|
|
147
|
+
"""Return the bullet-list lines for this plan block."""
|
|
148
|
+
rows: list[str] = []
|
|
149
|
+
if self.suite_name:
|
|
150
|
+
rows.append(f"- Active suite: {self.suite_name}")
|
|
151
|
+
if self.status:
|
|
152
|
+
rows.append(f"- Suite status: {self.status}")
|
|
153
|
+
if self.phase_in_progress:
|
|
154
|
+
rows.append(f"- Phase in progress: {self.phase_in_progress}")
|
|
155
|
+
if self.task_in_progress:
|
|
156
|
+
rows.append(f"- Task in progress: {self.task_in_progress}")
|
|
157
|
+
if self.next_action:
|
|
158
|
+
rows.append(f"- Next action: {self.next_action}")
|
|
159
|
+
if self.blockers:
|
|
160
|
+
rows.append(f"- Blockers: {self.blockers}")
|
|
161
|
+
for path in self.critical_files[:_NUMBERED_PREVIEW_LIMIT]:
|
|
162
|
+
rows.append(f"- Critical file: {path}")
|
|
163
|
+
return rows
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _as_str(value: object) -> str:
|
|
167
|
+
"""Return `value` as a string, or empty when not a string."""
|
|
168
|
+
return value if isinstance(value, str) else ""
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _iter_lines(path: Path) -> Iterator[str]:
|
|
172
|
+
"""Yield stripped lines from `path`, or nothing if unreadable."""
|
|
173
|
+
try:
|
|
174
|
+
with path.open(encoding="utf-8", errors="replace") as handle:
|
|
175
|
+
for raw in handle:
|
|
176
|
+
yield raw.rstrip("\r\n")
|
|
177
|
+
except OSError as exc:
|
|
178
|
+
_logger.debug("Unable to read %s: %s", path, exc)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _section_lines(path: Path, heading: str) -> Iterator[str]:
|
|
182
|
+
"""Yield lines that appear under `heading` until the next H2."""
|
|
183
|
+
in_section = False
|
|
184
|
+
for line in _iter_lines(path):
|
|
185
|
+
if not in_section:
|
|
186
|
+
if line.strip() == heading:
|
|
187
|
+
in_section = True
|
|
188
|
+
continue
|
|
189
|
+
if _H2.match(line):
|
|
190
|
+
return
|
|
191
|
+
yield line
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def first_nonblank(path: Path, heading: str) -> str:
|
|
195
|
+
"""Return the first non-blank line under `heading`."""
|
|
196
|
+
for line in _section_lines(path, heading):
|
|
197
|
+
stripped = line.strip()
|
|
198
|
+
if stripped:
|
|
199
|
+
return stripped
|
|
200
|
+
return ""
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def bold_field(path: Path, key: str) -> str:
|
|
204
|
+
"""Return the value of ``**Key:** value`` (first occurrence)."""
|
|
205
|
+
for line in _iter_lines(path):
|
|
206
|
+
match = _BOLD_FIELD.match(line)
|
|
207
|
+
if match and match.group(1).strip() == key:
|
|
208
|
+
return match.group(2).strip()
|
|
209
|
+
return ""
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def heading_value(path: Path, prefix: str) -> str:
|
|
213
|
+
"""Return the tail of the first line starting with `prefix`."""
|
|
214
|
+
for line in _iter_lines(path):
|
|
215
|
+
if line.startswith(prefix):
|
|
216
|
+
return line[len(prefix) :].strip()
|
|
217
|
+
return ""
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def topic_file_names(
|
|
221
|
+
path: Path, heading: str, limit: int = _BULLET_PREVIEW_LIMIT
|
|
222
|
+
) -> list[str]:
|
|
223
|
+
"""Return up to `limit` linked ``.md`` filenames found under `heading`."""
|
|
224
|
+
names: list[str] = []
|
|
225
|
+
for line in _section_lines(path, heading):
|
|
226
|
+
for match in _MARKDOWN_LINK.finditer(line):
|
|
227
|
+
names.append(match.group(1))
|
|
228
|
+
if len(names) >= limit:
|
|
229
|
+
return names
|
|
230
|
+
return names
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def bullets_under(
|
|
234
|
+
path: Path, heading: str, limit: int = _BULLET_PREVIEW_LIMIT
|
|
235
|
+
) -> list[str]:
|
|
236
|
+
"""Return up to `limit` bullet items under `heading`."""
|
|
237
|
+
out: list[str] = []
|
|
238
|
+
for line in _section_lines(path, heading):
|
|
239
|
+
match = _BULLET.match(line)
|
|
240
|
+
if match:
|
|
241
|
+
out.append(match.group(1).strip())
|
|
242
|
+
if len(out) >= limit:
|
|
243
|
+
break
|
|
244
|
+
return out
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def numbered_under(
|
|
248
|
+
path: Path, heading: str, limit: int = _NUMBERED_PREVIEW_LIMIT
|
|
249
|
+
) -> list[str]:
|
|
250
|
+
"""Return up to `limit` numbered-list items under `heading`."""
|
|
251
|
+
out: list[str] = []
|
|
252
|
+
for line in _section_lines(path, heading):
|
|
253
|
+
match = _NUMBERED.match(line)
|
|
254
|
+
if match:
|
|
255
|
+
out.append(match.group(1).strip())
|
|
256
|
+
if len(out) >= limit:
|
|
257
|
+
break
|
|
258
|
+
return out
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def project_slug(root: Path) -> str:
|
|
262
|
+
"""Convert an absolute path to the canonical project-directory slug.
|
|
263
|
+
|
|
264
|
+
The slug deliberately preserves consecutive ``-`` runs that arise from
|
|
265
|
+
adjacent separators (e.g., ``\\.`` becomes ``--``). This matches the
|
|
266
|
+
on-disk folder names already created by Claude Code under
|
|
267
|
+
``<root>/projects/`` — collapsing runs would break lookup of existing
|
|
268
|
+
memory directories. The ``find_memory_index`` substring fallback
|
|
269
|
+
(below) covers any drift.
|
|
270
|
+
"""
|
|
271
|
+
text = str(root).rstrip("/\\").lower()
|
|
272
|
+
for ch in (":", "\\", "/", "."):
|
|
273
|
+
text = text.replace(ch, "-")
|
|
274
|
+
return text
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def find_memory_index(root: Path) -> Path | None:
|
|
278
|
+
"""Locate ``MEMORY.md`` for this project under ``<root>/projects``."""
|
|
279
|
+
projects_root = root / "projects"
|
|
280
|
+
if not projects_root.is_dir():
|
|
281
|
+
return None
|
|
282
|
+
|
|
283
|
+
direct = projects_root / project_slug(root) / "memory" / "MEMORY.md"
|
|
284
|
+
if direct.is_file():
|
|
285
|
+
return direct
|
|
286
|
+
|
|
287
|
+
leaf = root.name.lower().lstrip(".")
|
|
288
|
+
candidates = sorted(projects_root.glob("*/memory/MEMORY.md"), reverse=True)
|
|
289
|
+
for candidate in candidates:
|
|
290
|
+
parent_name = candidate.parent.parent.name.lower()
|
|
291
|
+
if leaf in parent_name:
|
|
292
|
+
return candidate
|
|
293
|
+
return None
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def read_memory_summary(memory_path: Path) -> MemorySummary:
|
|
297
|
+
"""Parse a ``MEMORY.md`` index into a `MemorySummary`."""
|
|
298
|
+
return MemorySummary(
|
|
299
|
+
overview=first_nonblank(memory_path, "## Project Overview"),
|
|
300
|
+
latest=bold_field(memory_path, "Latest"),
|
|
301
|
+
topic_files=topic_file_names(memory_path, "## Topic Files"),
|
|
302
|
+
key_conventions=bullets_under(memory_path, "## Key Conventions"),
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def find_active_suite(plans_root: Path) -> Path | None:
|
|
307
|
+
"""Return the most recently updated plan suite, or None."""
|
|
308
|
+
if not plans_root.is_dir():
|
|
309
|
+
return None
|
|
310
|
+
best: tuple[float, Path] | None = None
|
|
311
|
+
for entry in plans_root.iterdir():
|
|
312
|
+
if not entry.is_dir():
|
|
313
|
+
continue
|
|
314
|
+
progress = entry / "PROGRESS.md"
|
|
315
|
+
notes = entry / "PLAN-NOTES.md"
|
|
316
|
+
if not (progress.is_file() and notes.is_file()):
|
|
317
|
+
continue
|
|
318
|
+
mtime = progress.stat().st_mtime
|
|
319
|
+
if best is None or mtime > best[0]:
|
|
320
|
+
best = (mtime, entry)
|
|
321
|
+
return best[1] if best else None
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def read_plan_summary(suite_dir: Path) -> PlanSummary:
|
|
325
|
+
"""Parse a plan suite's ``PROGRESS.md`` into a `PlanSummary`."""
|
|
326
|
+
progress = suite_dir / "PROGRESS.md"
|
|
327
|
+
return PlanSummary(
|
|
328
|
+
suite_name=suite_dir.name,
|
|
329
|
+
status=heading_value(progress, "## Status:"),
|
|
330
|
+
phase_in_progress=bold_field(progress, "Phase in progress"),
|
|
331
|
+
task_in_progress=bold_field(progress, "Task in progress"),
|
|
332
|
+
next_action=bold_field(progress, "Next action"),
|
|
333
|
+
blockers=bold_field(progress, "Blockers"),
|
|
334
|
+
critical_files=numbered_under(progress, "### Critical Files for Next Phase"),
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def read_conformity_posture(root: Path) -> list[str]:
|
|
339
|
+
"""Read the conformity-posture context message, returning its lines.
|
|
340
|
+
|
|
341
|
+
The conformity posture lives at ``hooks/messages/sessionstart.md``
|
|
342
|
+
and surfaces a standing reminder block (working-trace pickup point,
|
|
343
|
+
unresolved-inquiry enumeration, host-discovery freshness, gate
|
|
344
|
+
awareness, trivial threshold). The bootstrap degrades gracefully
|
|
345
|
+
into a three-block envelope when the file is absent or unreadable;
|
|
346
|
+
a missing posture file does not break SessionStart.
|
|
347
|
+
"""
|
|
348
|
+
|
|
349
|
+
path = root / "hooks" / "messages" / "sessionstart.md"
|
|
350
|
+
if not path.is_file():
|
|
351
|
+
return []
|
|
352
|
+
try:
|
|
353
|
+
text = path.read_text(encoding="utf-8")
|
|
354
|
+
except OSError:
|
|
355
|
+
return []
|
|
356
|
+
return text.splitlines()
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def plugin_alone_pointer() -> list[str]:
|
|
360
|
+
"""Return a lean rules-pointer block when running plugin-alone, else [].
|
|
361
|
+
|
|
362
|
+
When the SessionStart hook fires from the Claude Code plugin installed
|
|
363
|
+
*alone* (via the marketplace, with no separate apothem engine install),
|
|
364
|
+
Claude Code exports ``CLAUDE_PLUGIN_ROOT`` to the spawned hook process and
|
|
365
|
+
the bundled behavioral rules sit under that root but cannot load as
|
|
366
|
+
always-on plugin context. The engine install, by contrast, projects the
|
|
367
|
+
rules through the harness root and leaves ``CLAUDE_PLUGIN_ROOT`` unset — so
|
|
368
|
+
this block is emitted only for the plugin-alone posture and never regresses
|
|
369
|
+
the engine-install session-start summary.
|
|
370
|
+
|
|
371
|
+
The block is a short POINTER, never the full rule bodies (which are large):
|
|
372
|
+
it names where the bundled rules live and states that the mechanical
|
|
373
|
+
conformity hooks remain active. It locates the bundled ``rules/`` directory
|
|
374
|
+
under the plugin root (``rules/`` in the assembled bundle, or
|
|
375
|
+
``src/apothem/rules/`` when the repository root is the plugin root) and
|
|
376
|
+
cites whichever exists, falling back to the assembled location.
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
The pointer block's lines, or an empty list when not plugin-alone.
|
|
380
|
+
"""
|
|
381
|
+
plugin_root = os.environ.get("CLAUDE_PLUGIN_ROOT")
|
|
382
|
+
if not plugin_root:
|
|
383
|
+
return []
|
|
384
|
+
base = Path(plugin_root)
|
|
385
|
+
for rel in ("rules", "src/apothem/rules"):
|
|
386
|
+
if (base / rel).is_dir():
|
|
387
|
+
rules_ref = f"${{CLAUDE_PLUGIN_ROOT}}/{rel}/"
|
|
388
|
+
break
|
|
389
|
+
else:
|
|
390
|
+
rules_ref = "${CLAUDE_PLUGIN_ROOT}/rules/"
|
|
391
|
+
return [
|
|
392
|
+
"Apothem plugin posture:",
|
|
393
|
+
(
|
|
394
|
+
"- Apothem is installed as a Claude Code plugin alone (no engine "
|
|
395
|
+
"install). Its behavioral rules are bundled at "
|
|
396
|
+
f"{rules_ref} — consult them as governing guidance for this "
|
|
397
|
+
"session; they are not auto-loaded as always-on context plugin-alone."
|
|
398
|
+
),
|
|
399
|
+
(
|
|
400
|
+
"- The mechanical conformity hooks (write/edit/bash guards, "
|
|
401
|
+
"authorship-header and plans-locality checks, session and "
|
|
402
|
+
"compaction handlers) remain active and fire on tool use."
|
|
403
|
+
),
|
|
404
|
+
]
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def build_context(root: Path, payload: dict[str, object] | None) -> str:
|
|
408
|
+
"""Assemble the full additionalContext string."""
|
|
409
|
+
blocks: list[list[str]] = []
|
|
410
|
+
|
|
411
|
+
pointer = plugin_alone_pointer()
|
|
412
|
+
if pointer:
|
|
413
|
+
blocks.append(pointer)
|
|
414
|
+
|
|
415
|
+
meta = SessionMeta.from_payload(payload)
|
|
416
|
+
meta_lines = meta.lines()
|
|
417
|
+
if meta_lines:
|
|
418
|
+
blocks.append(["Session bootstrap:", *meta_lines])
|
|
419
|
+
|
|
420
|
+
memory_index = find_memory_index(root)
|
|
421
|
+
if memory_index is not None:
|
|
422
|
+
summary = read_memory_summary(memory_index)
|
|
423
|
+
memory_lines = summary.lines()
|
|
424
|
+
if memory_lines:
|
|
425
|
+
blocks.append(["Memory summary:", *memory_lines])
|
|
426
|
+
|
|
427
|
+
active_suite = find_active_suite(root / _PLAN_SUITES_DIR)
|
|
428
|
+
if active_suite is not None:
|
|
429
|
+
plan_lines = read_plan_summary(active_suite).lines()
|
|
430
|
+
blocks.append(["Plan summary:", *plan_lines])
|
|
431
|
+
else:
|
|
432
|
+
blocks.append(
|
|
433
|
+
[
|
|
434
|
+
"Plan summary:",
|
|
435
|
+
"- No active plan suite detected. Ready for ad-hoc work.",
|
|
436
|
+
]
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
posture_lines = read_conformity_posture(root)
|
|
440
|
+
if posture_lines:
|
|
441
|
+
blocks.append(["Conformity posture:", *posture_lines])
|
|
442
|
+
|
|
443
|
+
flat = [line for block in blocks for line in block]
|
|
444
|
+
return normalize_ascii("\n".join(flat))
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
448
|
+
"""Parse CLI arguments."""
|
|
449
|
+
parser = argparse.ArgumentParser(prog="session_start_bootstrap")
|
|
450
|
+
parser.add_argument("--quiet", "-q", action="store_true")
|
|
451
|
+
return parser.parse_args(argv)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def main(argv: list[str] | None = None) -> None:
|
|
455
|
+
"""Entry point. Emits a hook envelope (success or failure) and returns."""
|
|
456
|
+
args = parse_args(argv)
|
|
457
|
+
try:
|
|
458
|
+
root = resolve_project_root(Mode.HOOKS, script_path=Path(__file__))
|
|
459
|
+
if root is None:
|
|
460
|
+
root = Path(__file__).resolve().parent.parent
|
|
461
|
+
payload = read_hook_stdin()
|
|
462
|
+
context = build_context(root, payload)
|
|
463
|
+
emit_hook_envelope("SessionStart", context, args.quiet)
|
|
464
|
+
except Exception as exc:
|
|
465
|
+
# Outermost boundary. Emit a failure envelope so the harness
|
|
466
|
+
# always sees a structurally valid SessionStart response, never
|
|
467
|
+
# a traceback.
|
|
468
|
+
emit_failure_envelope("SessionStart", str(exc))
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
if __name__ == "__main__":
|
|
472
|
+
main()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# lib
|
|
4
|
+
|
|
5
|
+
> **Role.** Shared internal helpers reused across the `apothem` subpackages — frontmatter probing, materializer building blocks, parallel sweep, and structured reporting.
|
|
6
|
+
|
|
7
|
+
## Files
|
|
8
|
+
|
|
9
|
+
| File | Purpose |
|
|
10
|
+
|------|---------|
|
|
11
|
+
| `frontmatter.py` | YAML frontmatter field probing and value extraction for ecosystem files. |
|
|
12
|
+
| `harness_materializer.py` | Shared building blocks for the per-harness materializers. |
|
|
13
|
+
| `harness_protocol.py` | The `HarnessAdapter` structural Protocol every concrete adapter satisfies — defined in the foundation layer so the registry references the contract without importing its consumers; re-exported by `apothem.harnesses` as the public import path. |
|
|
14
|
+
| `harness_registry.py` | Harness identity, adapter entry-point, target, docs, capability, package-data, and test-fixture registry — authoritative at runtime (filesystem-convention `discover_adapters` is a conformance parity check, not the runtime resolver). |
|
|
15
|
+
| `plugin_tree.py` | Plugin source-tree assembler and manifest generator — materializes the canonical `.claude-plugin` distribution bundle (engine plus catalog) that runs as a self-contained tree with vendored dependencies. |
|
|
16
|
+
| `plugin_bootstrap.py` | Self-contained engine-import bootstrap for the bundled plugin tree — resolves `import apothem` against the bundled engine copy under `<plugin_root>/lib/apothem`. |
|
|
17
|
+
| `plan_tiers.py` | Three-tier scalability classification (small / medium / large) for the `/plan-<stage>` planning pipeline — governs a plan suite's validation cadence, indexing, and decomposition as it scales. |
|
|
18
|
+
| `profile.py` | Canonical shared-profile model, normalization, and diagnostics. |
|
|
19
|
+
| `propagation.py` | Propagation-manifest loader for harness adapters — parses the per-harness install rules from `propagation-manifest.yaml`. |
|
|
20
|
+
| `parallel_sweep.py` | Parallel file-sweep utilities backed by `ProcessPoolExecutor`. |
|
|
21
|
+
| `reporter.py` | Structured pass/fail/warn reporting for the validation tools. |
|
|
22
|
+
| `data_home.py` | Per-harness data-home resolution for the memory and contexts surfaces — derives an isolated `.apothem/<harness>/{memory,contexts,learning}` tree so each target's data is non-overlapping. |
|
|
23
|
+
| `memory.py` | Agnostic, operator-portable durable knowledge store — `MemoryRecord` value type, schema validation, and a canonical-serialized `MemoryStore` with byte-equivalent export/import. |
|
|
24
|
+
| `contexts.py` | Injectable, enable/disable-able context fragments — `ContextFragment` value type, schema validation, and a `ContextStore` with an activation switch. |
|
|
25
|
+
| `learning.py` | Opt-in (default-off) continuous-learning loop — signal capture gated on the profile flag, confidence-scored pattern extraction, and promotion of above-threshold patterns to catalog-skill artifacts. |
|
|
26
|
+
| `auditor.py` | Unified conformance / security auditor — configuration-file scanning, closed-catalog secret detection, and rule-based conformance over a parsed config, emitting advisory `Finding`s that validate against `advisory-finding.schema.json`. Standalone via `python -m apothem.lib.auditor`; the hosted layer consumes `pr_audit`. |
|
|
27
|
+
| `clean_slate.py` | Opt-in clean-slate removal routine — closed removal target set, unsafe-root guard, timestamped backup taken before any removal, per-target confirmation, dry-run preview, and a non-interactive override. |
|
|
28
|
+
| `__init__.py` | Package marker. |
|
|
29
|
+
|
|
30
|
+
## Operating in this folder
|
|
31
|
+
|
|
32
|
+
- **High blast radius.** A defect here propagates into every adapter, the CLI, and the conformity tooling — changes are high-blast-radius; favor narrow, well-tested edits.
|
|
33
|
+
- **The harness registry is the single source of truth** for harness identity, entry points, targets, capabilities, package-data globs, and test fixtures. When the registry changes, the coupled surfaces it indexes (profile schema, manifest, golden fixtures, compatibility matrix, `pyproject.toml`, tests) must move in the same change-set or the suite breaks.
|
|
34
|
+
- **Profile ↔ schema sync.** Keep the profile model and its schema in sync; a profile-shape change without the matching schema update is a defect.
|
|
35
|
+
- **Strict typing.** Public surfaces here are part of the `mypy --strict` scope — keep type annotations exact (`list[T]` / `dict[K, V]` / `X | None`, `typing.Protocol` for structural typing, `typing.cast()` to narrow `Any`); never widen a public signature to escape a strict failure.
|
|
36
|
+
- **Agnostic, operator-portable data stores.** Memory records and context fragments serialize to a byte-equivalent canonical form, and the learning loop is **default-off**, gated on its profile flag. Do not bias any store toward a particular harness or model, and do not flip the learning loop on by default. Reference harnesses only by catalog slug; privilege none.
|
|
37
|
+
- **Adding or changing a module:** update the module table above in the same change-set, and confirm the public API stays `mypy --strict`-clean. Validate with `python -m ruff check` and `python -m ruff format`, `python -m mypy src/apothem/cli/ src/apothem/harnesses/` (plus this package where it falls in strict scope), `python -m pytest`, and `python -m apothem.conformity.gate --all .`.
|
|
38
|
+
|
|
39
|
+
## Related
|
|
40
|
+
|
|
41
|
+
- [`harnesses/`](../harnesses/) — adapters loaded and tested against `harness_registry.py`.
|
|
42
|
+
- [`conformity/`](../conformity/) and [`audit/`](../audit/) — consumers of `frontmatter.py`, `parallel_sweep.py`, and `reporter.py`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""apothem.lib package initializer.
|
|
4
|
+
|
|
5
|
+
Makes src/apothem/lib/ importable as a package so its shared internal helper
|
|
6
|
+
modules can be addressed by their fully-qualified names from sibling packages
|
|
7
|
+
and from external consumers. The package collects domain models and building
|
|
8
|
+
blocks reused across the apothem subpackages — profile, harness registry,
|
|
9
|
+
materializers, propagation, plugin-tree assembly, plan-tier classification,
|
|
10
|
+
frontmatter probing, parallel sweep, and structured reporting. These live in
|
|
11
|
+
the lib layer so harness adapters and tooling consume them without importing
|
|
12
|
+
the presentation-layer cli package. See README.md for the full module index.
|
|
13
|
+
"""
|