@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,283 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Enforce concurrency + per-job timeout discipline on GitHub workflows.
|
|
4
|
+
|
|
5
|
+
Why this validator exists. The workflow reliability contract requires
|
|
6
|
+
every push- or pull_request-triggered workflow to declare a top-level
|
|
7
|
+
``concurrency:`` block (to coalesce redundant runs on the same ref)
|
|
8
|
+
AND every job declares a
|
|
9
|
+
``timeout-minutes:`` ceiling (to prevent runaway jobs from monopolising
|
|
10
|
+
the runner pool). Deployment-class workflows (release / publish /
|
|
11
|
+
deploy) reverse the cancellation polarity: mid-deploy cancellation
|
|
12
|
+
risks partial-state hazards, so ``cancel-in-progress: false`` is
|
|
13
|
+
mandatory.
|
|
14
|
+
|
|
15
|
+
Detection. Walk ``<root>/.github/workflows/*.yml``. For each workflow:
|
|
16
|
+
|
|
17
|
+
1. Inspect ``on:`` for ``push`` or ``pull_request`` triggers; skip
|
|
18
|
+
workflows without either (manual / scheduled workflows are out of
|
|
19
|
+
scope for concurrency discipline).
|
|
20
|
+
2. Require a top-level ``concurrency:`` mapping with a ``group:`` key
|
|
21
|
+
and a ``cancel-in-progress:`` flag.
|
|
22
|
+
3. For deployment workflows (filename matches ``*release*`` /
|
|
23
|
+
``*publish*`` / ``*deploy*``) require ``cancel-in-progress: false``;
|
|
24
|
+
for all others require ``cancel-in-progress: true``.
|
|
25
|
+
4. For every job in ``jobs:``, require ``timeout-minutes:`` with
|
|
26
|
+
``N <= 30`` (short jobs) or ``N <= 90`` (full-matrix jobs — detected
|
|
27
|
+
heuristically via the presence of a ``strategy.matrix`` block).
|
|
28
|
+
|
|
29
|
+
Drift classes. ``missing-concurrency-block``,
|
|
30
|
+
``missing-cancel-in-progress-flag``, ``cancel-in-progress-wrong-value``,
|
|
31
|
+
``missing-job-timeout``, ``job-timeout-exceeds-ceiling``.
|
|
32
|
+
|
|
33
|
+
Tolerance. When ``<root>/.github/workflows/`` does not exist, exit 0 with
|
|
34
|
+
``not-yet-materialised: true`` — the workflows tree has not been
|
|
35
|
+
authored yet and the discipline does not yet apply.
|
|
36
|
+
|
|
37
|
+
Exit semantics. Exits 0 when every inspected workflow is conformant;
|
|
38
|
+
exits 2 with a JSON enumeration of per-workflow + per-job drift when
|
|
39
|
+
any drift is detected.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from __future__ import annotations
|
|
43
|
+
|
|
44
|
+
import json
|
|
45
|
+
import sys
|
|
46
|
+
from dataclasses import asdict, dataclass, field
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
from typing import Any, Final
|
|
49
|
+
|
|
50
|
+
import yaml
|
|
51
|
+
|
|
52
|
+
GREP_NAME: Final[str] = "workflow-concurrency-grep"
|
|
53
|
+
RULE_ANCHOR: Final[str] = "workflow concurrency + per-job timeouts"
|
|
54
|
+
|
|
55
|
+
EXIT_PASS: Final[int] = 0
|
|
56
|
+
EXIT_FAIL: Final[int] = 2
|
|
57
|
+
|
|
58
|
+
SHORT_JOB_CEILING_MINUTES: Final[int] = 30
|
|
59
|
+
FULL_MATRIX_JOB_CEILING_MINUTES: Final[int] = 90
|
|
60
|
+
|
|
61
|
+
DEPLOYMENT_NAME_MARKERS: Final[tuple[str, ...]] = ("release", "publish", "deploy")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True)
|
|
65
|
+
class Finding:
|
|
66
|
+
"""One concurrency / timeout drift instance inside a workflow."""
|
|
67
|
+
|
|
68
|
+
workflow: str
|
|
69
|
+
job: str | None
|
|
70
|
+
drift_class: str
|
|
71
|
+
detail: str
|
|
72
|
+
rule: str = RULE_ANCHOR
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(frozen=True)
|
|
76
|
+
class GrepResult:
|
|
77
|
+
grep: str
|
|
78
|
+
root: str
|
|
79
|
+
not_yet_materialised: bool
|
|
80
|
+
workflow_count: int
|
|
81
|
+
passed: bool
|
|
82
|
+
findings: list[Finding] = field(default_factory=list)
|
|
83
|
+
|
|
84
|
+
def to_json(self) -> str:
|
|
85
|
+
payload: dict[str, Any] = {
|
|
86
|
+
"grep": self.grep,
|
|
87
|
+
"root": self.root,
|
|
88
|
+
"not-yet-materialised": self.not_yet_materialised,
|
|
89
|
+
"workflow-count": self.workflow_count,
|
|
90
|
+
"passed": self.passed,
|
|
91
|
+
"findings": [asdict(f) for f in self.findings],
|
|
92
|
+
}
|
|
93
|
+
return json.dumps(payload, indent=2)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _is_deployment_workflow(path: Path) -> bool:
|
|
97
|
+
"""Detect deployment-class workflows by filename marker."""
|
|
98
|
+
stem = path.stem.lower()
|
|
99
|
+
return any(marker in stem for marker in DEPLOYMENT_NAME_MARKERS)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _has_push_or_pr_trigger(on_block: object) -> bool:
|
|
103
|
+
"""Return True iff ``on:`` declares a push or pull_request trigger.
|
|
104
|
+
|
|
105
|
+
The ``on:`` key admits multiple shapes — a string (``on: push``), a
|
|
106
|
+
list (``on: [push, pull_request]``), or a mapping (``on: {push: {...}}``).
|
|
107
|
+
"""
|
|
108
|
+
if isinstance(on_block, str):
|
|
109
|
+
return on_block in ("push", "pull_request")
|
|
110
|
+
if isinstance(on_block, list):
|
|
111
|
+
return any(t in ("push", "pull_request") for t in on_block)
|
|
112
|
+
if isinstance(on_block, dict):
|
|
113
|
+
return "push" in on_block or "pull_request" in on_block
|
|
114
|
+
return False
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _job_is_full_matrix(job: dict[str, Any]) -> bool:
|
|
118
|
+
"""Heuristic: a job carrying ``strategy.matrix`` is a full-matrix job."""
|
|
119
|
+
strategy = job.get("strategy")
|
|
120
|
+
if not isinstance(strategy, dict):
|
|
121
|
+
return False
|
|
122
|
+
return "matrix" in strategy
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _check_workflow(path: Path) -> list[Finding]:
|
|
126
|
+
"""Inspect one workflow file; return its drift findings."""
|
|
127
|
+
findings: list[Finding] = []
|
|
128
|
+
workflow_name = path.name
|
|
129
|
+
try:
|
|
130
|
+
doc = yaml.safe_load(path.read_text(encoding="utf-8"))
|
|
131
|
+
except yaml.YAMLError as exc:
|
|
132
|
+
findings.append(
|
|
133
|
+
Finding(
|
|
134
|
+
workflow=workflow_name,
|
|
135
|
+
job=None,
|
|
136
|
+
drift_class="yaml-parse-error",
|
|
137
|
+
detail=f"failed to parse workflow: {exc}",
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
return findings
|
|
141
|
+
if not isinstance(doc, dict):
|
|
142
|
+
return findings
|
|
143
|
+
# PyYAML coerces the bare key `on` to boolean True (the YAML 1.1
|
|
144
|
+
# legacy-bool surface). Inspect both forms.
|
|
145
|
+
on_block = doc.get("on") if "on" in doc else doc.get(True)
|
|
146
|
+
if not _has_push_or_pr_trigger(on_block):
|
|
147
|
+
return findings
|
|
148
|
+
is_deploy = _is_deployment_workflow(path)
|
|
149
|
+
concurrency = doc.get("concurrency")
|
|
150
|
+
if concurrency is None:
|
|
151
|
+
findings.append(
|
|
152
|
+
Finding(
|
|
153
|
+
workflow=workflow_name,
|
|
154
|
+
job=None,
|
|
155
|
+
drift_class="missing-concurrency-block",
|
|
156
|
+
detail="top-level concurrency: block absent",
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
elif isinstance(concurrency, dict):
|
|
160
|
+
if "cancel-in-progress" not in concurrency:
|
|
161
|
+
findings.append(
|
|
162
|
+
Finding(
|
|
163
|
+
workflow=workflow_name,
|
|
164
|
+
job=None,
|
|
165
|
+
drift_class="missing-cancel-in-progress-flag",
|
|
166
|
+
detail="concurrency block lacks cancel-in-progress key",
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
else:
|
|
170
|
+
cip = concurrency["cancel-in-progress"]
|
|
171
|
+
expected = not is_deploy
|
|
172
|
+
if cip is not expected:
|
|
173
|
+
findings.append(
|
|
174
|
+
Finding(
|
|
175
|
+
workflow=workflow_name,
|
|
176
|
+
job=None,
|
|
177
|
+
drift_class="cancel-in-progress-wrong-value",
|
|
178
|
+
detail=(
|
|
179
|
+
f"deployment workflow requires cancel-in-progress: false (got {cip!r})"
|
|
180
|
+
if is_deploy
|
|
181
|
+
else f"non-deployment workflow requires cancel-in-progress: true (got {cip!r})"
|
|
182
|
+
),
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
jobs = doc.get("jobs")
|
|
186
|
+
if not isinstance(jobs, dict):
|
|
187
|
+
return findings
|
|
188
|
+
for job_name, job in jobs.items():
|
|
189
|
+
if not isinstance(job, dict):
|
|
190
|
+
continue
|
|
191
|
+
# Reusable-workflow callers declare `uses:` at job level with no
|
|
192
|
+
# inline `steps:` sequence. The called reusable workflow owns its
|
|
193
|
+
# timeout-minutes ceiling, so the caller cannot declare one. This
|
|
194
|
+
# mirrors the harden-runner reusable-workflow exemption.
|
|
195
|
+
if "uses" in job and "steps" not in job:
|
|
196
|
+
continue
|
|
197
|
+
timeout = job.get("timeout-minutes")
|
|
198
|
+
if timeout is None:
|
|
199
|
+
findings.append(
|
|
200
|
+
Finding(
|
|
201
|
+
workflow=workflow_name,
|
|
202
|
+
job=str(job_name),
|
|
203
|
+
drift_class="missing-job-timeout",
|
|
204
|
+
detail="job declares no timeout-minutes ceiling",
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
continue
|
|
208
|
+
if not isinstance(timeout, int):
|
|
209
|
+
findings.append(
|
|
210
|
+
Finding(
|
|
211
|
+
workflow=workflow_name,
|
|
212
|
+
job=str(job_name),
|
|
213
|
+
drift_class="missing-job-timeout",
|
|
214
|
+
detail=f"timeout-minutes is not an integer: {timeout!r}",
|
|
215
|
+
)
|
|
216
|
+
)
|
|
217
|
+
continue
|
|
218
|
+
ceiling = (
|
|
219
|
+
FULL_MATRIX_JOB_CEILING_MINUTES
|
|
220
|
+
if _job_is_full_matrix(job)
|
|
221
|
+
else SHORT_JOB_CEILING_MINUTES
|
|
222
|
+
)
|
|
223
|
+
if timeout > ceiling:
|
|
224
|
+
findings.append(
|
|
225
|
+
Finding(
|
|
226
|
+
workflow=workflow_name,
|
|
227
|
+
job=str(job_name),
|
|
228
|
+
drift_class="job-timeout-exceeds-ceiling",
|
|
229
|
+
detail=f"timeout-minutes={timeout} exceeds ceiling={ceiling}",
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
return findings
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def check(root: Path) -> GrepResult:
|
|
236
|
+
"""Walk ``<root>/.github/workflows/*.yml``; return aggregated result.
|
|
237
|
+
|
|
238
|
+
Pre-conditions: ``root`` is a directory path.
|
|
239
|
+
Post-conditions: ``result.passed`` is True iff every push-/PR-
|
|
240
|
+
triggered workflow declares conformant concurrency + per-job
|
|
241
|
+
timeouts, OR the workflows directory does not yet exist.
|
|
242
|
+
"""
|
|
243
|
+
workflows_dir = root / ".github" / "workflows"
|
|
244
|
+
if not workflows_dir.is_dir():
|
|
245
|
+
return GrepResult(
|
|
246
|
+
grep=GREP_NAME,
|
|
247
|
+
root=str(root),
|
|
248
|
+
not_yet_materialised=True,
|
|
249
|
+
workflow_count=0,
|
|
250
|
+
passed=True,
|
|
251
|
+
findings=[],
|
|
252
|
+
)
|
|
253
|
+
workflow_files = sorted(
|
|
254
|
+
list(workflows_dir.glob("*.yml")) + list(workflows_dir.glob("*.yaml"))
|
|
255
|
+
)
|
|
256
|
+
findings: list[Finding] = []
|
|
257
|
+
for path in workflow_files:
|
|
258
|
+
findings.extend(_check_workflow(path))
|
|
259
|
+
return GrepResult(
|
|
260
|
+
grep=GREP_NAME,
|
|
261
|
+
root=str(root),
|
|
262
|
+
not_yet_materialised=False,
|
|
263
|
+
workflow_count=len(workflow_files),
|
|
264
|
+
passed=not findings,
|
|
265
|
+
findings=findings,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _read_input(argv: list[str]) -> Path:
|
|
270
|
+
if len(argv) >= 2:
|
|
271
|
+
return Path(argv[1])
|
|
272
|
+
return Path.cwd()
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _main(argv: list[str]) -> int:
|
|
276
|
+
root = _read_input(argv)
|
|
277
|
+
result = check(root)
|
|
278
|
+
print(result.to_json())
|
|
279
|
+
return EXIT_PASS if result.passed else EXIT_FAIL
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
if __name__ == "__main__":
|
|
283
|
+
sys.exit(_main(sys.argv))
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# harnesses
|
|
4
|
+
|
|
5
|
+
> **Role.** Per-harness adapter subpackages. Each adapter translates the shared `apothem` corpus into one AI tool's native configuration on disk. Harness identity, entry-point paths, target declarations, docs coverage, package-data expectations, and capability support live in `apothem.lib.harness_registry`; `pyproject.toml` mirrors the same entry-point set.
|
|
6
|
+
|
|
7
|
+
## The `HarnessAdapter` protocol
|
|
8
|
+
|
|
9
|
+
`HarnessAdapter` is defined in the foundation layer at [`lib/harness_protocol.py`](../lib/harness_protocol.py) and re-exported by `__init__.py`, so `from apothem.harnesses import HarnessAdapter` stays the public import path every concrete adapter satisfies. The lifecycle contract is intentionally small; registry metadata carries the public identity, docs, capability, package-data, and target-path obligations:
|
|
10
|
+
|
|
11
|
+
| Member | Contract |
|
|
12
|
+
|--------|----------|
|
|
13
|
+
| `name` | Canonical kebab-case harness identifier (e.g. `'claude-code'`). |
|
|
14
|
+
| `output_path` | Absolute path to the target configuration file. |
|
|
15
|
+
| `install(profile)` | Materialize the harness configuration from the shared profile dict and return a structured materialization run when the adapter writes through the shared driver. |
|
|
16
|
+
| `update(profile)` | Re-materialize the harness configuration from an updated profile dict and return the same structured run surface. |
|
|
17
|
+
| `uninstall()` | Remove the harness configuration file if present. |
|
|
18
|
+
| `is_installed()` | Return `True` if the harness configuration file exists on disk. |
|
|
19
|
+
| `verify()` | Return `True` if the installed harness configuration is valid. |
|
|
20
|
+
|
|
21
|
+
## Adapter subpackage shape
|
|
22
|
+
|
|
23
|
+
Each harness subpackage carries the same core module set: `__init__.py` (the adapter class), `install.py`, `uninstall.py`, `update.py`, and `verify.py`. Adapters that render a native configuration file also carry `materializer.py`. Template-propagation and conversion behavior is declared in `lib/propagation-manifest.yaml`.
|
|
24
|
+
|
|
25
|
+
## The seventeen harnesses
|
|
26
|
+
|
|
27
|
+
| Harness | Native config target | Shape |
|
|
28
|
+
|---------|----------------------|-------|
|
|
29
|
+
| `claude_code` | `~/.claude/settings.json`, `~/.claude/{agents,rules,skills,statuslines,output-styles}/`, plus `~/.claude/apothem/{templates,hooks}/` | Native Claude Code adapter; command prompts are wrapped as skills. |
|
|
30
|
+
| `antigravity` | `~/.gemini/GEMINI.md` plus `~/.gemini/antigravity-cli/plugins/apothem/` | Antigravity CLI plugin adapter (no materializer). |
|
|
31
|
+
| `codex` | `~/.codex/AGENTS.md`, `~/.codex/hooks.json`, `~/.codex/hooks/`, `~/.codex/agents/*.toml`, `~/.agents/skills/`, `~/.config/apothem/{rules,templates}/` | Native Codex adapter; does not write `config.toml`. |
|
|
32
|
+
| `cursor` | `<project>/.cursor/rules/apothem-rules.mdc` | Project-scope manifest adapter. |
|
|
33
|
+
| `gemini_cli` | `<project>/GEMINI.md` plus `<project>/.gemini/{commands,skills,agents,apothem}/` | Project-scope manifest adapter with TOML command conversion. |
|
|
34
|
+
| `github_copilot` | `<project>/.github/copilot-instructions.md` | Project-scope manifest adapter. |
|
|
35
|
+
| `hermes` | `~/.hermes/config.yaml` plus `~/.hermes/apothem/` | Materializer (native MCP via `auxiliary.mcp`); support cohorts under `~/.hermes/apothem/`. |
|
|
36
|
+
| `kimi_code` | `<project>/AGENTS.md` plus `<project>/.kimi-code/apothem/` | Project-scope manifest adapter; native agent memory. |
|
|
37
|
+
| `open_claw` | `~/.openclaw/openclaw.json` plus `~/.openclaw/apothem/` | Support cohorts under `~/.openclaw/apothem/`; no config keys authored (name-allowlist skills, CLI MCP). |
|
|
38
|
+
| `opencode` | `~/.config/opencode/opencode.json`, `commands/`, `skills/`, `agents/`, `apothem/` | Materializer plus native commands, skills, and agents. |
|
|
39
|
+
| `qwen_code` | `~/.qwen/settings.json`, `~/.qwen/QWEN.md`, `commands/`, `skills/`, `agents/`, `apothem/` | Materializer plus native hooks, commands, skills, agents, context anchor, and support cohorts. |
|
|
40
|
+
| `windsurf` | `<project>/.devin/rules/apothem-rules.md` | Project-scope manifest adapter (Devin Desktop preferred surface; `.windsurf/rules/` fallback). |
|
|
41
|
+
| `codebuddy` | `<project>/.codebuddy/rules/apothem-rules.md` | Project-scope manifest adapter. |
|
|
42
|
+
| `kiro` | `<project>/.kiro/steering/apothem-rules.md` | Project-scope manifest adapter. |
|
|
43
|
+
| `trae` | `<project>/.trae/rules/apothem-rules.md` | Project-scope manifest adapter. |
|
|
44
|
+
| `zed` | `<project>/.rules` | Project-scope manifest adapter; flat project-root file. |
|
|
45
|
+
| `glm` | `<project>/.apothem/providers/glm.toml` | Project-scope provider adapter (GLM / Z.ai model backend; TOML config only). |
|
|
46
|
+
|
|
47
|
+
## Conventions
|
|
48
|
+
|
|
49
|
+
- Adapters consume their propagation contract from `lib/propagation-manifest.yaml` when they copy or convert shared cohorts.
|
|
50
|
+
- Registry rows are the source of truth for the exact seventeen public IDs, package keys, adapter entry points, docs pages, test fixtures, package-data keys, target declarations, and capability states.
|
|
51
|
+
- The `~/.gemini/` user-scope home namespace belongs to the `antigravity` adapter; the `gemini_cli` adapter is project-scope and writes only under the operator-supplied `--project <path>` root, so the two never collide on the shared Gemini home.
|
|
52
|
+
- Project-scope adapters (`cursor`, `gemini_cli`, `github_copilot`, `codebuddy`, `kiro`, `trae`, `windsurf`, `zed`) opt in via `requires_project = True`; `output_path` is a display-only sentinel and the concrete target resolves per-invocation through `resolve_output_path(project)`. The CLI rejects any lifecycle invocation that omits `--project <path>`, and `is_installed` / `verify` return `False` when no project is supplied.
|
|
53
|
+
- The shared install driver validates every manifest source and target before writing, reports created/updated/unchanged/skipped/warning/error outcomes, supports dry-run, and projects unsupported or discovery-pending registry capability cells as warnings.
|
|
54
|
+
- Existing matching targets are backed up before replacement. Shared discovery directories are merged child-by-child so unrelated operator-authored entries survive Apothem updates, and unchanged generated content is left untouched.
|
|
55
|
+
- The `claude_code` adapter deliberately does **not** manage the operator-owned memory file at the harness root; governance reaches that harness through the propagated `rules/` tree and the `SessionStart` hook, never by rewriting the operator's memory.
|
|
56
|
+
- The `codex` adapter resolves the harness home through the `CODEX_HOME` environment variable, defaulting to the user-scope root when the variable is unset.
|
|
57
|
+
|
|
58
|
+
## Related
|
|
59
|
+
|
|
60
|
+
- [`lib/harness_materializer.py`](../lib/harness_materializer.py) — shared building blocks for the single-file materializers.
|
|
61
|
+
- [`lib/harness_protocol.py`](../lib/harness_protocol.py) — the `HarnessAdapter` Protocol contract, defined in the foundation layer and re-exported here.
|
|
62
|
+
- [`lib/harness_registry.py`](../lib/harness_registry.py) — central exact-seventeen registry and adapter contract metadata.
|
|
63
|
+
- [`lib/propagation-manifest.yaml`](../lib/propagation-manifest.yaml) — the propagation contract consumed by manifest-driven adapters.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Apothem harness adapter protocol — public re-export.
|
|
4
|
+
|
|
5
|
+
Every concrete adapter must implement :class:`HarnessAdapter`. The protocol
|
|
6
|
+
is defined in the foundation layer at :mod:`apothem.lib.harness_protocol` and
|
|
7
|
+
re-exported here, so ``from apothem.harnesses import HarnessAdapter`` stays the
|
|
8
|
+
stable public import path for adapters, tests, and documentation — the
|
|
9
|
+
foundation declares the contract, this consumer package re-exposes it. The
|
|
10
|
+
adapters are declared in :mod:`apothem.lib.harness_registry`; the
|
|
11
|
+
``pyproject.toml`` entry-point group mirrors that registry exactly.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from apothem.lib.harness_protocol import HarnessAdapter as HarnessAdapter
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# _shared
|
|
4
|
+
|
|
5
|
+
> **Role.** The cross-adapter shared-infrastructure package. Logic recurring across three or more harness adapters is hoisted here so each adapter holds only its harness-specific identity and scope. The underscore prefix keeps this package out of the `apothem.harnesses` entry-point namespace — it is shared machinery, not a registrable adapter.
|
|
6
|
+
|
|
7
|
+
## What lives here
|
|
8
|
+
|
|
9
|
+
`install_driver.py` is the shared propagation driver every adapter's `install.py` delegates to. It carries the install recipe once: load a harness's rules from `lib/propagation-manifest.yaml`, sweep stale top-level paths from earlier layouts, then apply each install entry in declaration order. The driver supplies:
|
|
10
|
+
|
|
11
|
+
- The structured materialization-result surface (`MaterializationResult` / `MaterializationRun`) with deterministic per-outcome counts.
|
|
12
|
+
- The safe-write primitives: path validation against an allowed root, backup-before-replace, atomic swap, no-op detection.
|
|
13
|
+
- The directory-replace and stale-sweep primitives.
|
|
14
|
+
- The operator-owned merge path: sentinel-block merge for Markdown anchors, key-preserving merge for JSON.
|
|
15
|
+
- The destructive-authorization gate.
|
|
16
|
+
- The per-mode entry appliers (`write_text`, `replace_tree`, `merge_tree_entries`, `command_skills`, and the per-harness agent/command converters).
|
|
17
|
+
|
|
18
|
+
Scope is expressed by which root the caller supplies — a user-scope harness root or a project-scope project root.
|
|
19
|
+
|
|
20
|
+
## Conventions
|
|
21
|
+
|
|
22
|
+
- Writes go through the safe-write primitives — never bypass them with a raw `Path.write_*`.
|
|
23
|
+
- Targets whose ownership class is vendor-reserved or immutable are refused outright; operator-owned non-additive overwrites route through the authorization gate with a unified diff.
|
|
24
|
+
- The hoist threshold is structural similarity across **three or more** adapters, not mere topical overlap; genuinely per-harness logic stays in the adapter subpackage.
|
|
25
|
+
- The package name stays underscore-prefixed; nothing here registers as an adapter or joins the `apothem.harnesses` entry-point group.
|
|
26
|
+
- This package is in `mypy --strict` scope.
|
|
27
|
+
|
|
28
|
+
## Operating in this folder
|
|
29
|
+
|
|
30
|
+
Add or change a primitive here only when the behavior is shared by three or more adapters; a one-adapter need belongs in that adapter's own module. Preserve the structured result/run surface — callers depend on the outcome vocabulary (`created` / `updated` / `unchanged` / `skipped` / `warning` / `error`) and the dry-run contract — so extend it additively rather than redefining existing outcomes. Validate with `python -m ruff check`, `python -m mypy src/apothem/harnesses/`, the conformity gate (`python -m apothem.conformity.gate --all .`), and `python -m pytest` (the adapter round-trip integration suite exercises this driver through every adapter).
|
|
31
|
+
|
|
32
|
+
## Related
|
|
33
|
+
|
|
34
|
+
- [`../../lib/propagation-manifest.yaml`](../../lib/propagation-manifest.yaml) — the propagation contract the driver loads.
|
|
35
|
+
- [`../../lib/harness_materializer.py`](../../lib/harness_materializer.py) — managed-block merge building blocks.
|
|
36
|
+
- [`../../lib/frontmatter.py`](../../lib/frontmatter.py) — agent/command field extraction used by the converters.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Shared install infrastructure for harness adapters.
|
|
4
|
+
|
|
5
|
+
Holds the common propagation-driver logic every harness adapter's
|
|
6
|
+
``install.py`` delegates to: manifest-rule loading, source/target path
|
|
7
|
+
resolution, the copytree ignore-filter builder, the directory-replace
|
|
8
|
+
primitive, the stale-sweep primitive, and the install/plan orchestrators.
|
|
9
|
+
The underscore-prefixed package name keeps it out of the
|
|
10
|
+
``apothem.harnesses`` entry-point namespace — it is shared infrastructure,
|
|
11
|
+
not a registrable adapter.
|
|
12
|
+
"""
|