@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,495 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
"""Uninstall, verify, fidelity, and the pure build_plan entrypoint."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import shutil
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Literal
|
|
12
|
+
|
|
13
|
+
import yaml
|
|
14
|
+
|
|
15
|
+
from apothem.harnesses._shared import install_driver
|
|
16
|
+
from apothem.lib import install_ledger
|
|
17
|
+
from apothem.lib.data_home import resolve_shared_data_home
|
|
18
|
+
from apothem.lib.harness_materializer import (
|
|
19
|
+
extract_managed_block,
|
|
20
|
+
)
|
|
21
|
+
from apothem.lib.harness_registry import SUPPORTED_HARNESS_IDS
|
|
22
|
+
from apothem.lib.install_ledger import LedgerRecord
|
|
23
|
+
from apothem.lib.propagation import (
|
|
24
|
+
InstallEntry,
|
|
25
|
+
resolve_target,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
from .install_driver_backup import _replace_path, backup_existing
|
|
29
|
+
from .install_driver_merge import render_content_tokens
|
|
30
|
+
from .install_driver_pathsafety import (
|
|
31
|
+
_allowed_write_root,
|
|
32
|
+
_root_for,
|
|
33
|
+
_validate_target_path,
|
|
34
|
+
)
|
|
35
|
+
from .install_driver_planvalidation import (
|
|
36
|
+
_generated_targets_for_entry,
|
|
37
|
+
_projected_profile_body,
|
|
38
|
+
)
|
|
39
|
+
from .install_driver_removal import _surgical_remove_from_target
|
|
40
|
+
from .install_driver_types import (
|
|
41
|
+
MaterializationResult,
|
|
42
|
+
_handle_rm_error,
|
|
43
|
+
_path_text,
|
|
44
|
+
_result,
|
|
45
|
+
resolve_source,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _native_config_parses(target: Path) -> bool:
|
|
50
|
+
"""Return True unless *target* is a structurally invalid JSON/YAML file.
|
|
51
|
+
|
|
52
|
+
Only ``.json``/``.yaml``/``.yml`` targets are parsed; other suffixes (e.g.
|
|
53
|
+
Markdown anchors) pass trivially. A present-but-corrupt config reads as
|
|
54
|
+
not-installed.
|
|
55
|
+
"""
|
|
56
|
+
suffix = target.suffix.lower()
|
|
57
|
+
if suffix not in {".json", ".yaml", ".yml"}:
|
|
58
|
+
return True
|
|
59
|
+
try:
|
|
60
|
+
text = target.read_text(encoding="utf-8")
|
|
61
|
+
except OSError:
|
|
62
|
+
return False
|
|
63
|
+
try:
|
|
64
|
+
if suffix == ".json":
|
|
65
|
+
json.loads(text)
|
|
66
|
+
else:
|
|
67
|
+
yaml.safe_load(text)
|
|
68
|
+
except (json.JSONDecodeError, yaml.YAMLError):
|
|
69
|
+
return False
|
|
70
|
+
return True
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def verify_install(
|
|
74
|
+
harness_name: str,
|
|
75
|
+
*,
|
|
76
|
+
harness_root: Path | None = None,
|
|
77
|
+
project_root: Path | None = None,
|
|
78
|
+
native_config: Path | None = None,
|
|
79
|
+
) -> bool:
|
|
80
|
+
"""Return True when every manifest install-list target is present + valid.
|
|
81
|
+
|
|
82
|
+
Walks the harness's manifest install list and resolves each target against
|
|
83
|
+
the supplied root: ``write_text``/``sentinel_merge`` targets must be
|
|
84
|
+
non-empty regular files, ``replace_tree`` targets must be directories, and
|
|
85
|
+
every other mode (tree merges, cohort conversions) must exist. JSON/YAML
|
|
86
|
+
config targets are additionally parsed — a corrupt config reads as
|
|
87
|
+
not-installed. *native_config* (the adapter's dynamically-rendered config
|
|
88
|
+
file, which is not a manifest entry) is checked the same way when supplied.
|
|
89
|
+
Returns False on the first unsatisfied target.
|
|
90
|
+
"""
|
|
91
|
+
rules = install_driver.load_rules(harness_name)
|
|
92
|
+
if native_config is not None:
|
|
93
|
+
if not native_config.is_file() or native_config.stat().st_size <= 0:
|
|
94
|
+
return False
|
|
95
|
+
if not _native_config_parses(native_config):
|
|
96
|
+
return False
|
|
97
|
+
for entry in rules.install:
|
|
98
|
+
target = resolve_target(
|
|
99
|
+
entry.target, harness_root=harness_root, project_root=project_root
|
|
100
|
+
)
|
|
101
|
+
if entry.mode in {"write_text", "sentinel_merge"}:
|
|
102
|
+
if not target.is_file() or target.stat().st_size <= 0:
|
|
103
|
+
return False
|
|
104
|
+
if not _native_config_parses(target):
|
|
105
|
+
return False
|
|
106
|
+
elif entry.mode == "replace_tree":
|
|
107
|
+
if not target.is_dir():
|
|
108
|
+
return False
|
|
109
|
+
elif not target.exists():
|
|
110
|
+
return False
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass(frozen=True)
|
|
115
|
+
class FidelityResult:
|
|
116
|
+
"""The drift verdict for one profile-derived anchor on disk."""
|
|
117
|
+
|
|
118
|
+
target: str
|
|
119
|
+
status: Literal["faithful", "drifted", "missing"]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _profile_anchor_targets(
|
|
123
|
+
harness_name: str,
|
|
124
|
+
*,
|
|
125
|
+
harness_root: Path | None,
|
|
126
|
+
project_root: Path | None,
|
|
127
|
+
) -> list[Path]:
|
|
128
|
+
"""Return the on-disk anchors that carry the projected profile managed block.
|
|
129
|
+
|
|
130
|
+
Every ``sentinel_merge`` manifest target (anchor adapters fold the projected
|
|
131
|
+
body into these), plus the two bolt-on profile anchors written outside the
|
|
132
|
+
manifest when present: claude_code's ``CLAUDE.md`` and the single-file-config
|
|
133
|
+
adapters' ``apothem/rules/00-apothem-profile.md``.
|
|
134
|
+
"""
|
|
135
|
+
rules = install_driver.load_rules(harness_name)
|
|
136
|
+
root = _root_for(harness_root, project_root)
|
|
137
|
+
targets: list[Path] = [
|
|
138
|
+
resolve_target(
|
|
139
|
+
entry.target, harness_root=harness_root, project_root=project_root
|
|
140
|
+
)
|
|
141
|
+
for entry in rules.install
|
|
142
|
+
if entry.mode == "sentinel_merge"
|
|
143
|
+
]
|
|
144
|
+
for relative in ("CLAUDE.md", "apothem/rules/00-apothem-profile.md"):
|
|
145
|
+
bolt_on = root / relative
|
|
146
|
+
if bolt_on.is_file():
|
|
147
|
+
targets.append(bolt_on)
|
|
148
|
+
return targets
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def check_fidelity(
|
|
152
|
+
harness_name: str,
|
|
153
|
+
*,
|
|
154
|
+
harness_root: Path | None = None,
|
|
155
|
+
project_root: Path | None = None,
|
|
156
|
+
profile: dict[str, Any],
|
|
157
|
+
) -> list[FidelityResult]:
|
|
158
|
+
"""Classify each profile-derived anchor as faithful / drifted / missing.
|
|
159
|
+
|
|
160
|
+
Re-projects *profile* through the same seam ``run_install`` uses and requires
|
|
161
|
+
the freshly-projected managed-block body to appear verbatim inside the
|
|
162
|
+
on-disk anchor's managed block. An anchor whose projected content was edited
|
|
163
|
+
on disk (so the freshly-projected body is no longer a substring) reads as
|
|
164
|
+
``drifted``; an absent anchor or one with no managed block reads as
|
|
165
|
+
``missing``; an exact carry reads as ``faithful``. This is what makes the CLI
|
|
166
|
+
``verify`` answer "is the profile faithfully installed?" rather than merely
|
|
167
|
+
"does a file exist".
|
|
168
|
+
"""
|
|
169
|
+
expected = _projected_profile_body(harness_name, profile) or ""
|
|
170
|
+
results: list[FidelityResult] = []
|
|
171
|
+
for target in _profile_anchor_targets(
|
|
172
|
+
harness_name, harness_root=harness_root, project_root=project_root
|
|
173
|
+
):
|
|
174
|
+
if not target.is_file():
|
|
175
|
+
results.append(FidelityResult(_path_text(target), "missing"))
|
|
176
|
+
continue
|
|
177
|
+
try:
|
|
178
|
+
text = target.read_text(encoding="utf-8")
|
|
179
|
+
except OSError:
|
|
180
|
+
results.append(FidelityResult(_path_text(target), "missing"))
|
|
181
|
+
continue
|
|
182
|
+
block = extract_managed_block(text)
|
|
183
|
+
if block is None:
|
|
184
|
+
results.append(FidelityResult(_path_text(target), "missing"))
|
|
185
|
+
elif expected and expected in block:
|
|
186
|
+
results.append(FidelityResult(_path_text(target), "faithful"))
|
|
187
|
+
else:
|
|
188
|
+
results.append(FidelityResult(_path_text(target), "drifted"))
|
|
189
|
+
return results
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def fidelity_is_faithful(results: list[FidelityResult]) -> bool:
|
|
193
|
+
"""Reduce per-anchor fidelity results to a single bool (all faithful)."""
|
|
194
|
+
return bool(results) and all(result.status == "faithful" for result in results)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _rendered_template_text(
|
|
198
|
+
entry: InstallEntry,
|
|
199
|
+
*,
|
|
200
|
+
harness_root: Path | None,
|
|
201
|
+
project_root: Path | None,
|
|
202
|
+
) -> str:
|
|
203
|
+
"""Return the rendered Apothem template text for a ``write_text`` entry.
|
|
204
|
+
|
|
205
|
+
Reads the manifest source and substitutes ``${HARNESS_ROOT}`` /
|
|
206
|
+
``${PROJECT_ROOT}`` tokens exactly as the install pass did, so the
|
|
207
|
+
surgical uninstall can recognize Apothem's on-disk contribution
|
|
208
|
+
byte-for-byte. Returns ``""`` when the source is absent (nothing for the
|
|
209
|
+
structured stripper to match — operator content is then preserved).
|
|
210
|
+
"""
|
|
211
|
+
src = resolve_source(entry.source)
|
|
212
|
+
if not src.is_file():
|
|
213
|
+
return ""
|
|
214
|
+
try:
|
|
215
|
+
raw = src.read_text(encoding="utf-8")
|
|
216
|
+
except OSError: # pragma: no cover - defensive
|
|
217
|
+
return ""
|
|
218
|
+
return render_content_tokens(
|
|
219
|
+
raw, harness_root=harness_root, project_root=project_root
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _shared_home_root_for(root: Path) -> Path:
|
|
224
|
+
"""Return the shared working-directory root anchored at *root*.
|
|
225
|
+
|
|
226
|
+
Uninstall carries no profile, so the workspace scope defaults to
|
|
227
|
+
project-local and the directory name to ``.apothem`` — the base is *root*
|
|
228
|
+
and the shared root is ``<root>/.apothem``. This mirrors the resolution the
|
|
229
|
+
install pass uses on the no-profile path, so an install and its later
|
|
230
|
+
uninstall agree on the home's location.
|
|
231
|
+
"""
|
|
232
|
+
return resolve_shared_data_home(base=root).root
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _other_harness_shares_home(*, current_harness: str, shared_root: Path) -> bool:
|
|
236
|
+
"""Report whether another installed harness still shares *shared_root*.
|
|
237
|
+
|
|
238
|
+
The shared data home is collapsed across harnesses, so removing it on the
|
|
239
|
+
first uninstall would destroy data the remaining harnesses depend on. This
|
|
240
|
+
consults the install ledger across every package key (except
|
|
241
|
+
*current_harness*) and returns ``True`` when any other harness's latest
|
|
242
|
+
record at its install root resolves to the SAME ``shared_root`` AND that
|
|
243
|
+
latest record is an ``install`` (not yet uninstalled or rolled back).
|
|
244
|
+
|
|
245
|
+
A harness is "still installed at its root" when its most recent ledger
|
|
246
|
+
record of any kind for that root is an ``install``. Because the current
|
|
247
|
+
uninstall's own ``uninstall`` marker is appended only AFTER this guard runs
|
|
248
|
+
(see :func:`run_uninstall`), *current_harness* is excluded explicitly so it
|
|
249
|
+
never counts itself as a co-occupant.
|
|
250
|
+
|
|
251
|
+
The check is fail-safe: any error reading the ledger raises out to the
|
|
252
|
+
caller, which treats it as "cannot prove last-harness" and retains the
|
|
253
|
+
shared home rather than risk a destructive removal on an uncertain count.
|
|
254
|
+
"""
|
|
255
|
+
for package_key in SUPPORTED_HARNESS_IDS:
|
|
256
|
+
if package_key == current_harness:
|
|
257
|
+
continue
|
|
258
|
+
# Find this harness's MOST RECENT record whose install root resolves to
|
|
259
|
+
# the same shared home. Records are append-ordered, so the last match in
|
|
260
|
+
# iteration order is the latest. Its kind tells the live state: an
|
|
261
|
+
# `install` means still installed; an `uninstall`/`rollback` means gone.
|
|
262
|
+
latest_kind: str | None = None
|
|
263
|
+
for record in install_ledger.read_records(package_key):
|
|
264
|
+
if _shared_home_root_for(Path(record.root)) == shared_root:
|
|
265
|
+
latest_kind = record.kind
|
|
266
|
+
if latest_kind == "install":
|
|
267
|
+
return True
|
|
268
|
+
return False
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _remove_data_home(
|
|
272
|
+
harness_name: str, *, root: Path, allowed_root: Path
|
|
273
|
+
) -> MaterializationResult | None:
|
|
274
|
+
"""Back up and remove the shared data home only when it is last-referenced.
|
|
275
|
+
|
|
276
|
+
The data home is the Apothem-owned ``<root>/.apothem/`` subtree shared
|
|
277
|
+
across every harness rooted at *root*, holding the operator's memory
|
|
278
|
+
records, context fragments, and learning signals (see
|
|
279
|
+
:func:`apothem.lib.data_home.resolve_shared_data_home`). Because it is
|
|
280
|
+
SHARED, removing it on the first harness uninstall would destroy data the
|
|
281
|
+
other still-installed harnesses depend on. The removal is therefore
|
|
282
|
+
conditional:
|
|
283
|
+
|
|
284
|
+
* If another installed harness still shares this home, the home is RETAINED
|
|
285
|
+
and an informational ``unchanged`` result is returned.
|
|
286
|
+
* If this is the last harness referencing the home, only the data stores
|
|
287
|
+
(``memory/``, ``contexts/``, ``learning/``) are backed up and removed.
|
|
288
|
+
``plans/`` is NEVER auto-removed — it is operator planning state, not
|
|
289
|
+
Apothem-materialized config — and the ``.apothem`` root itself is left
|
|
290
|
+
in place so any operator ``plans/`` survives. Each removed child is copied
|
|
291
|
+
into the Apothem backup root first, so the data stays recoverable.
|
|
292
|
+
|
|
293
|
+
Returns ``None`` when no data store exists (nothing to remove) or the home
|
|
294
|
+
path falls outside the allowed write root.
|
|
295
|
+
"""
|
|
296
|
+
home = _shared_home_root_for(root)
|
|
297
|
+
if not home.exists():
|
|
298
|
+
return None
|
|
299
|
+
if (
|
|
300
|
+
_validate_target_path(
|
|
301
|
+
home, allowed_root=allowed_root, operation="remove_data_home"
|
|
302
|
+
)
|
|
303
|
+
is not None
|
|
304
|
+
):
|
|
305
|
+
return None
|
|
306
|
+
|
|
307
|
+
# Last-harness guard: retain the shared home while another harness still
|
|
308
|
+
# references it. An uncertain ledger read raises and is caught here, falling
|
|
309
|
+
# back to RETAIN — the safe default that never risks shared-data loss.
|
|
310
|
+
try:
|
|
311
|
+
retain = _other_harness_shares_home(
|
|
312
|
+
current_harness=harness_name, shared_root=home
|
|
313
|
+
)
|
|
314
|
+
except Exception: # pragma: no cover - defensive: ledger read is robust
|
|
315
|
+
retain = True
|
|
316
|
+
if retain:
|
|
317
|
+
return _result(
|
|
318
|
+
"unchanged",
|
|
319
|
+
"remove_data_home",
|
|
320
|
+
home,
|
|
321
|
+
"shared data home retained — another harness is still installed",
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
spec = resolve_shared_data_home(base=root)
|
|
325
|
+
backups: list[Path] = []
|
|
326
|
+
removed_any = False
|
|
327
|
+
# plans/ is intentionally excluded — operator planning state is never
|
|
328
|
+
# auto-removed by uninstall.
|
|
329
|
+
for child in (spec.memory, spec.contexts, spec.learning):
|
|
330
|
+
if not child.exists():
|
|
331
|
+
continue
|
|
332
|
+
backup = backup_existing(
|
|
333
|
+
child,
|
|
334
|
+
install_root=root,
|
|
335
|
+
harness_name=harness_name,
|
|
336
|
+
allowed_root=allowed_root,
|
|
337
|
+
)
|
|
338
|
+
if backup is not None:
|
|
339
|
+
backups.append(backup)
|
|
340
|
+
shutil.rmtree(child, onerror=_handle_rm_error)
|
|
341
|
+
removed_any = True
|
|
342
|
+
if not removed_any:
|
|
343
|
+
return None
|
|
344
|
+
return _result(
|
|
345
|
+
"updated",
|
|
346
|
+
"remove_data_home",
|
|
347
|
+
home,
|
|
348
|
+
"removed shared data stores (memory, contexts, learning); plans retained",
|
|
349
|
+
backup_path=backups[0] if backups else None,
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def run_uninstall(
|
|
354
|
+
harness_name: str,
|
|
355
|
+
*,
|
|
356
|
+
harness_root: Path | None = None,
|
|
357
|
+
project_root: Path | None = None,
|
|
358
|
+
) -> None:
|
|
359
|
+
"""Remove Apothem-generated targets declared for *harness_name*.
|
|
360
|
+
|
|
361
|
+
``write_text`` / ``sentinel_merge`` operator-owned targets are cleaned
|
|
362
|
+
surgically: only Apothem's contribution is stripped (the sentinel-delimited
|
|
363
|
+
managed block for Markdown anchors; Apothem's keys / hook handlers for JSON
|
|
364
|
+
and YAML configs), operator prose and operator-authored keys survive, and a
|
|
365
|
+
file reduced to Apothem-only content is deleted rather than left as a stub.
|
|
366
|
+
The pre-mutation file is copied into the Apothem backup root first — no
|
|
367
|
+
whole-file ``.bak`` sibling is left in the operator's directory. Directory
|
|
368
|
+
discovery surfaces are cleaned child-by-child so unrelated operator-authored
|
|
369
|
+
commands, skills, agents, and rules remain in place; existing generated
|
|
370
|
+
entries are backed up before removal.
|
|
371
|
+
|
|
372
|
+
The pass is ledger-driven: the latest install record for this harness+root
|
|
373
|
+
is the source of truth for which single-file targets were actually written,
|
|
374
|
+
so manifest drift after install cannot strand or over-remove them (a target
|
|
375
|
+
added to the manifest later is untouched; a recorded target removed from the
|
|
376
|
+
manifest is still cleaned). Tree/discovery surfaces stay manifest+source
|
|
377
|
+
driven. The per-harness data home (memory / contexts / learning) is backed up
|
|
378
|
+
and removed, and an uninstall marker is appended to the ledger. With no ledger
|
|
379
|
+
record (a pre-ledger install), the pass falls back to the full manifest.
|
|
380
|
+
"""
|
|
381
|
+
rules = install_driver.load_rules(harness_name)
|
|
382
|
+
root = _root_for(harness_root, project_root)
|
|
383
|
+
allowed_root = _allowed_write_root(harness_root, project_root)
|
|
384
|
+
|
|
385
|
+
# Ledger-driven: the latest install record is the source of truth for what
|
|
386
|
+
# this harness+root actually wrote. ``recorded_paths`` is None when no record
|
|
387
|
+
# exists (legacy / pre-ledger install) — fall back to removing every manifest
|
|
388
|
+
# target. With a record, a single-file manifest target is removed only if it
|
|
389
|
+
# was recorded, so an entry added to the manifest after install is not touched.
|
|
390
|
+
record = install_ledger.latest_record(harness_name, root=root)
|
|
391
|
+
recorded_paths: set[str] | None = (
|
|
392
|
+
{target.path for target in record.targets} if record is not None else None
|
|
393
|
+
)
|
|
394
|
+
handled: set[str] = set()
|
|
395
|
+
|
|
396
|
+
for entry in rules.install:
|
|
397
|
+
if entry.mode in {"write_text", "sentinel_merge"}:
|
|
398
|
+
target = resolve_target(
|
|
399
|
+
entry.target,
|
|
400
|
+
harness_root=harness_root,
|
|
401
|
+
project_root=project_root,
|
|
402
|
+
)
|
|
403
|
+
if recorded_paths is not None and _path_text(target) not in recorded_paths:
|
|
404
|
+
continue
|
|
405
|
+
template_text = _rendered_template_text(
|
|
406
|
+
entry, harness_root=harness_root, project_root=project_root
|
|
407
|
+
)
|
|
408
|
+
_surgical_remove_from_target(
|
|
409
|
+
target,
|
|
410
|
+
template_text,
|
|
411
|
+
mode=entry.mode,
|
|
412
|
+
install_root=root,
|
|
413
|
+
harness_name=harness_name,
|
|
414
|
+
allowed_root=allowed_root,
|
|
415
|
+
)
|
|
416
|
+
handled.add(_path_text(target))
|
|
417
|
+
continue
|
|
418
|
+
# Tree/discovery surfaces are reversed child-by-child against the apothem
|
|
419
|
+
# source enumeration so operator-authored siblings survive — a path list
|
|
420
|
+
# cannot express that, so these stay manifest+source-driven.
|
|
421
|
+
for target in _generated_targets_for_entry(
|
|
422
|
+
entry,
|
|
423
|
+
harness_root=harness_root,
|
|
424
|
+
project_root=project_root,
|
|
425
|
+
exclude=rules.exclude,
|
|
426
|
+
):
|
|
427
|
+
_replace_path(
|
|
428
|
+
target,
|
|
429
|
+
install_root=root,
|
|
430
|
+
harness_name=harness_name,
|
|
431
|
+
allowed_root=allowed_root,
|
|
432
|
+
)
|
|
433
|
+
handled.add(_path_text(target))
|
|
434
|
+
|
|
435
|
+
# Recorded sentinel anchors not covered by a current manifest entry: the
|
|
436
|
+
# bolt-on profile anchors (claude-code ``CLAUDE.md``, the single-file adapters'
|
|
437
|
+
# profile rule) and any sentinel entry removed from the manifest after install.
|
|
438
|
+
# The managed block self-delimits, so it strips without the template.
|
|
439
|
+
if record is not None:
|
|
440
|
+
for recorded in record.targets:
|
|
441
|
+
if recorded.path in handled or recorded.mode != "sentinel_merge":
|
|
442
|
+
continue
|
|
443
|
+
_surgical_remove_from_target(
|
|
444
|
+
Path(recorded.path),
|
|
445
|
+
"",
|
|
446
|
+
mode="sentinel_merge",
|
|
447
|
+
install_root=root,
|
|
448
|
+
harness_name=harness_name,
|
|
449
|
+
allowed_root=allowed_root,
|
|
450
|
+
)
|
|
451
|
+
handled.add(recorded.path)
|
|
452
|
+
|
|
453
|
+
# Back up and remove the per-harness data home (memory / contexts / learning).
|
|
454
|
+
_remove_data_home(harness_name, root=root, allowed_root=allowed_root)
|
|
455
|
+
|
|
456
|
+
# Append an uninstall marker referencing the install pass it reversed.
|
|
457
|
+
install_ledger.append_record(
|
|
458
|
+
LedgerRecord.create(
|
|
459
|
+
harness=harness_name,
|
|
460
|
+
root=root,
|
|
461
|
+
kind="uninstall",
|
|
462
|
+
install_id=record.install_id if record is not None else None,
|
|
463
|
+
)
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def build_plan(
|
|
468
|
+
harness_name: str,
|
|
469
|
+
*,
|
|
470
|
+
harness_root: Path | None = None,
|
|
471
|
+
project_root: Path | None = None,
|
|
472
|
+
) -> list[dict[str, str]]:
|
|
473
|
+
"""Return *harness_name*'s propagation plan without writing anything.
|
|
474
|
+
|
|
475
|
+
Each entry carries ``source`` (resolved on-disk path), ``target``
|
|
476
|
+
(resolved against the supplied root), and ``mode``. When the relevant
|
|
477
|
+
root is ``None`` the corresponding placeholder stays literal in the
|
|
478
|
+
target string so the operator sees the unresolved template form instead
|
|
479
|
+
of a misleading absolute path.
|
|
480
|
+
"""
|
|
481
|
+
rules = install_driver.load_rules(harness_name)
|
|
482
|
+
return [
|
|
483
|
+
{
|
|
484
|
+
"source": str(resolve_source(entry.source)),
|
|
485
|
+
"target": str(
|
|
486
|
+
resolve_target(
|
|
487
|
+
entry.target,
|
|
488
|
+
harness_root=harness_root,
|
|
489
|
+
project_root=project_root,
|
|
490
|
+
)
|
|
491
|
+
),
|
|
492
|
+
"mode": entry.mode,
|
|
493
|
+
}
|
|
494
|
+
for entry in rules.install
|
|
495
|
+
]
|