@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,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "code-craft-markdown"
|
|
3
|
+
description: "Per-language code-craft for Markdown / prose artifacts — purpose-driven structure, sentence-level justification, precision over politeness, active-voice construction, hedge-elimination per the clean-room generation projection. Honors host's ratified Markdown linter (markdownlint, vale, prose-linter) and frontmatter conventions; passes the host's lint clean."
|
|
4
|
+
pathFilter: "**/*.md, **/*.markdown"
|
|
5
|
+
alwaysApply: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
9
|
+
|
|
10
|
+
# Rule: Code Craft — Markdown
|
|
11
|
+
|
|
12
|
+
## What this rule enforces
|
|
13
|
+
|
|
14
|
+
This rule binds **M13 — Code Craft Conventions** at the **Markdown / prose per-language tier**. Every Markdown artifact the agent produces — README, ADR, RFC, design document, runbook, contributing guide, changelog entry, documentation page, response prose, commit-message body — MUST meet a sentence-level craft floor: **purpose-driven structure** (shape derived from communication purpose, not a generic template); **sentence-level justification** (every sentence advances the purpose; removable sentences MUST NOT exist); **precision over politeness** (exact words; pre-landing hedges removed); **active-voice construction** (concrete subjects, specific verbs); **hedge-elimination** in prescriptive contexts. The rule extends `rules/clean-room-generation.md` §5 (Prose and Documentation) into the per-language code-craft surface.
|
|
15
|
+
|
|
16
|
+
## Pre-conditions
|
|
17
|
+
|
|
18
|
+
Applies whenever a Markdown artifact (any file matching the `pathFilter` globs — `*.md`, `*.markdown`) is authored, modified, or reviewed. Fenced code blocks remain governed by the per-language code-craft rule for the block's language (`python` → `rules/code-craft-python.md`; `bash` → `rules/code-craft-shell.md`); this rule governs the surrounding prose, document structure, link discipline, and frontmatter.
|
|
19
|
+
|
|
20
|
+
## Required behavior
|
|
21
|
+
|
|
22
|
+
### 1. Purpose-Driven Structure
|
|
23
|
+
|
|
24
|
+
Every Markdown artifact has a communication purpose; structure follows purpose:
|
|
25
|
+
|
|
26
|
+
| Purpose class | Structure shape | Why |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| **Tutorial** | Sequential walkthrough; reader proceeds top-to-bottom | The reader's mental model is built incrementally |
|
|
29
|
+
| **How-to guide** | Goal-then-steps; prerequisites, then ordered steps | The reader knows what they want and seeks the recipe |
|
|
30
|
+
| **Reference** | Random-access entries; alphabetical or topical index | The reader looks up a specific item, not a sequence |
|
|
31
|
+
| **Explanation** | Concept-then-elaboration; progressive disclosure | The reader builds understanding from primitives outward |
|
|
32
|
+
| **Architecture document (ADR / RFC / design)** | Context · Decision · Consequences · Alternatives | The reader audits the reasoning behind a structural choice |
|
|
33
|
+
| **Runbook** | Trigger · Diagnosis · Action · Verification · Rollback | The reader is on-call and needs the next step under pressure |
|
|
34
|
+
|
|
35
|
+
The structure is **not** imported from a template "because documents like this usually have them". When a section's content does not advance the purpose, the section is removed. When an unconventional section is required by the purpose, the section is added with a purpose-explanatory header rather than forced into a generic shape.
|
|
36
|
+
|
|
37
|
+
### 2. Sentence-Level Justification
|
|
38
|
+
|
|
39
|
+
Every sentence MUST advance the purpose. Three failure classes are eliminated at authoring time:
|
|
40
|
+
|
|
41
|
+
- **Filler.** "In this section, we will discuss …" / "It is important to note that …" / "As mentioned earlier …" — meta-commentary about the document, not substance. Remove.
|
|
42
|
+
- **Throat-clearing.** "Before diving in …" / "Without further ado …" / "Let's begin by …" — openings that delay substance. Remove, or replace with the substantive opening.
|
|
43
|
+
- **Restatement.** A sentence re-stating the prior one in different words. Compress to one.
|
|
44
|
+
|
|
45
|
+
The test: remove the sentence — does the document still advance the purpose? Yes → it was filler; remove it. No → it is load-bearing; keep it.
|
|
46
|
+
|
|
47
|
+
#### 2.1 Prose-over-lists default; one question per turn
|
|
48
|
+
|
|
49
|
+
Prose is the default carrier; a list earns its place only when the content is **genuinely enumerable** — a set of parallel items, an ordered sequence of steps, a lookup table — where the list structure makes the parallelism or order legible. A conversational answer, an explanation, or a single recommendation stays prose: a bulleted list of one or two items, or a list that fragments a continuous argument into disconnected stubs, is a list imposed where prose carries the meaning better. The reach for a list is justified by the content's structure, not by the habit of bulleting.
|
|
50
|
+
|
|
51
|
+
When prose elicits a decision, ask **at most one question per turn**. Batching several questions into one turn forces the reader to track and answer them in parallel and buries the load-bearing one; surface the single most decision-blocking question, resolve it, then surface the next. (Structured-inquiry invocations route through `rules/interactive-questions.md` and carry their own option-set shape; this is the prose-surface floor for the conversational case.)
|
|
52
|
+
|
|
53
|
+
### 3. Precision Over Politeness
|
|
54
|
+
|
|
55
|
+
Exact words. Specific claims. Numbers with units. Conditions stated:
|
|
56
|
+
|
|
57
|
+
- **Right:** "The function returns null when the key is missing."
|
|
58
|
+
- **Wrong:** "The function may return null in certain cases."
|
|
59
|
+
|
|
60
|
+
Hedge words that soften a binding prescription MUST be removed. The hedging-vocabulary discipline at `rules/definitiveness.md` (M8) applies in full: **maybe · might · could · should probably · usually · generally · typically · mostly · often · perhaps · possibly · somewhat · fairly · roughly · broadly** are eliminated where binding prescription is possible. Where the claim genuinely is conditional, the conditions are enumerated explicitly: "The function returns null when the key is missing OR when the value is `None`."
|
|
61
|
+
|
|
62
|
+
Content-free qualifiers ("very", "quite", "somewhat", "rather", "fairly", "kind of") are noise — remove them; the unqualified claim is stronger and shorter.
|
|
63
|
+
|
|
64
|
+
### 4. Active-Voice Construction
|
|
65
|
+
|
|
66
|
+
Active voice. Concrete subjects. Specific verbs.
|
|
67
|
+
|
|
68
|
+
- **Right:** "The scheduler assigns tasks to workers."
|
|
69
|
+
- **Wrong:** "Tasks are assigned to workers by the scheduler."
|
|
70
|
+
- **Worse:** "Tasks are assigned to workers." (passive without actor — responsibility undiagnosable.)
|
|
71
|
+
|
|
72
|
+
Passive voice is permitted in two cases only: (a) the actor is genuinely unknown or irrelevant ("The configuration is loaded from disk at startup"); (b) the patient is the topical focus and inverting would obscure the topic ("The bug was introduced in commit abc123"). Outside these cases, use active voice.
|
|
73
|
+
|
|
74
|
+
### 5. Frontmatter Discipline
|
|
75
|
+
|
|
76
|
+
When the host's Markdown corpus uses frontmatter (the artifact's first non-empty line is `---`), the frontmatter MUST conform to the host's discovered schema:
|
|
77
|
+
|
|
78
|
+
- **Required fields per artifact class.** The host's per-class contract (rule files require `name` + `description`; skill files require `name` + `description`; documentation pages may require `title` + `summary` + `tags`) is honored per `rules/host-discovery.md`.
|
|
79
|
+
- **Field shape.** Every required field is non-empty (per the PreToolUse Write hook validation at the hooks pipeline). Booleans are `true` / `false` (not `yes` / `no` unless the host's discovered convention uses them). Lists use the host's ratified shape (block `- item` or flow `[item, item]`).
|
|
80
|
+
- **Field order.** Sibling frontmatter ordering is preserved; new fields land at the host-ratified position, not at top or bottom by default.
|
|
81
|
+
|
|
82
|
+
### 6. Link Discipline
|
|
83
|
+
|
|
84
|
+
Every link MUST be **resolvable** at emission time:
|
|
85
|
+
|
|
86
|
+
- **Internal links.** Links to host files resolve to existing files; anchors resolve to existing headings. When documenting placeholder link syntax, spell it `text -> path/to/file.md` or `text -> path/to/file.md#section` (not as a live link).
|
|
87
|
+
- **External links.** Permalinked where possible — commit-pinned over branch-pointed; archived versions where the canonical source may rot.
|
|
88
|
+
- **Cited material.** Quotes and paraphrases carry the source as a link or footnote citation. Folklore claims (no source) are removed or sourced.
|
|
89
|
+
|
|
90
|
+
Stale links are findings per `rules/visual-leverage.md` §4 staleness-check pattern: a link whose target has moved or been removed is stale, and staleness is repaired in the same change-set as the prose modification, never deferred.
|
|
91
|
+
|
|
92
|
+
### 7. Code Block Discipline
|
|
93
|
+
|
|
94
|
+
- **Language tag.** Every fenced block declares its language (` ```python `, ` ```bash `, ` ```yaml `, ` ```json `). An untagged block forgoes syntax highlighting; the missing tag is a finding.
|
|
95
|
+
- **Per-language code-craft.** Block contents honor the per-language sibling rule (Python → `code-craft-python.md`; Shell → `code-craft-shell.md`; other languages → host-discovered convention via `code-craft-conventions.md`).
|
|
96
|
+
- **Runnable examples.** Examples claiming to be runnable MUST run as-shown. Pseudocode is labeled (` ```python title="pseudocode" ` or a comment marker) so the reader is not misled.
|
|
97
|
+
- **Inline-code discipline.** Backticks for symbols, paths, command names, file names; plain prose for natural-language usage. `pathlib.Path` (symbol) is backticked; "the path object" (noun) is not.
|
|
98
|
+
|
|
99
|
+
### 8. Heading Hierarchy
|
|
100
|
+
|
|
101
|
+
Heading levels carry semantic weight:
|
|
102
|
+
|
|
103
|
+
- **One H1 per file.** The H1 is the primary title; subsequent sections use H2 and below.
|
|
104
|
+
- **No skipped levels.** H2 → H3 is allowed; H2 → H4 is not (the missing H3 breaks document outliners).
|
|
105
|
+
- **Headings are anchors.** Every referenced heading becomes an anchor (Markdown auto-generates the anchor from heading text per the host's rules — kebab-case-of-heading is the common shape).
|
|
106
|
+
- **Sentence case or title case.** The host's convention is honored uniformly; mixed casing across siblings is a finding.
|
|
107
|
+
|
|
108
|
+
### 9. Linting & Static Analysis (M13.7)
|
|
109
|
+
|
|
110
|
+
The artifact MUST pass the host's ratified Markdown linter clean:
|
|
111
|
+
|
|
112
|
+
- **markdownlint** (or `markdownlint-cli2` / `markdownlint-cli`) — the host's `.markdownlint.json` / `.markdownlint.yaml` is honored. Common rules: MD013 (line length — host-configured; 80 / 100 / 120 the prevalent values), MD024 (no duplicate headings), MD033 (inline HTML allowed by config), MD041 (first line is a top-level heading).
|
|
113
|
+
- **vale** or another prose-linter — when configured, the host's `.vale.ini` and styles (`Microsoft`, `write-good`, custom dictionaries) apply; the artifact passes the configured severity threshold clean.
|
|
114
|
+
|
|
115
|
+
### 10. Length Discipline
|
|
116
|
+
|
|
117
|
+
Long Markdown artifacts (above 200 lines / 2000 tokens) MUST honor the incremental generation protocol per `rules/large-file-generation.md`. Sections growing beyond the artifact's coherence threshold are split into cross-linked sibling files, never left as monolithic walls of prose.
|
|
118
|
+
|
|
119
|
+
## Disclosure surface
|
|
120
|
+
|
|
121
|
+
Every Markdown artifact emission, restructure, or hedge-elimination is recorded in the disclosure ledger per `rules/disclosure-ledger.md`:
|
|
122
|
+
|
|
123
|
+
- `[Discovery — source: .markdownlint.json | .vale.ini | sibling-md-files; value: <ruleset | style>; honored]` for lint-config and prose-linter discoveries.
|
|
124
|
+
- `[Discovery — source: sibling-frontmatter-schema; value: <field-list>; honored]` for frontmatter-schema discoveries.
|
|
125
|
+
- `[Refinement — improvement: clarity; intercepted: <hedge-form | passive-voice | filler-sentence>; replacement: <revised-form>]` for hedge / passive / filler interceptions.
|
|
126
|
+
- `[Default — applied: <auto-decision>; class: pure-formatting-normalization]` for markdownlint / prettier-md normalizations on existing files where the host has a ratified style.
|
|
127
|
+
|
|
128
|
+
## Failure tells
|
|
129
|
+
|
|
130
|
+
A README that opens with "This document describes …" (filler — the title declares what the document describes). An ADR with a "Background" section running ten paragraphs of throat-clearing before the decision (purpose-drift). A how-to guide structured as a sequential narrative ("First we'll explore the concept, then we'll see how it works …") instead of goal-then-steps (purpose-shape mismatch). Hedging vocabulary in prescriptive prose: "users should generally commit small changes" / "the function might return null in some cases" / "this is typically the safer approach" (M8 violation). Passive voice obscuring the actor: "It was decided that …" / "The bug was fixed" without naming who decided / who fixed (responsibility opaque). Content-free qualifiers in prescription: "very important", "fairly safe", "rather slow" (no information). Untagged fenced code blocks (`` ``` `` followed by code with no language tag — markdownlint MD040 violation). Internal links pointing to moved or removed files (link rot). External links pointing to mutable refs (`main` / `master` / `latest`) where commit-pinned is available (volatile reference). Heading hierarchy with skipped levels (H2 → H4) breaking document outliners. Multiple H1 headings in a single file (one-H1 violation). Frontmatter fields missing the host-ratified required set (`description` non-empty per the hooks pipeline hook validation). A 500-line Markdown artifact authored as a single monolithic write rather than via the incremental generation protocol (CM-23 / `rules/large-file-generation.md` violation).
|
|
131
|
+
|
|
132
|
+
## Bindings (§0.j five-direction)
|
|
133
|
+
|
|
134
|
+
- **Drives →** ● Every Markdown artifact's quality floor across every host project (purpose-driven structure, sentence-level justification, precision over politeness, active-voice construction, hedge-elimination). ● Every documentation page, ADR, RFC, runbook, README, CONTRIBUTING, CHANGELOG entry. ● The frontmatter validation surface at the hooks pipeline PreToolUse Write hook (the hook enforces non-empty `description` on rules / skills / agents / commands). ◐ The link discipline at every cross-rule citation in the ecosystem.
|
|
135
|
+
- **Satisfies →** ● the fifteen-mandate registry row **M13 — Code Craft** at the Markdown per-language tier. ● the rules registry row "Code Craft — Markdown".
|
|
136
|
+
- **Established by ↑** ● the fifteen-mandate registry (ratifies M13). ● The CommonMark and GitHub Flavored Markdown specifications (the upstream syntax standards). ● `markdownlint` rules catalog and `vale` style inventories (the upstream prose-linter rulebooks this rule projects).
|
|
137
|
+
- **Gated by ←** ● The path-filter (`*.md`, `*.markdown`) — this rule activates only on Markdown-language artifact touches. ● the trivial-vs-non-trivial threshold (trivial-scope Markdown edits run an abbreviated check covering link-resolution and frontmatter-presence only).
|
|
138
|
+
- **Cross-bound with ↔** ↔ `rules/code-craft-conventions.md` (universal-delegation stub yields to this rule when the artifact's path matches; the universal floor M13.1–M13.11 is materialized here in prose idioms). ↔ `rules/code-craft-python.md` + `rules/code-craft-shell.md` (sibling per-language code-craft rules — code blocks in Markdown delegate to these per the §7 fenced-block discipline; consistent body shape across the trio). ↔ `rules/clean-room-generation.md` §5 Prose and Documentation (this rule is the per-language projection of §5; sentence-level justification, precision over politeness, active-voice construction are inherited from §5.1–§5.4). ↔ `rules/definitiveness.md` (M8 — hedge-elimination discipline applies in full to Markdown prescriptive prose). ↔ `rules/large-file-generation.md` (CM-23 — long-Markdown incremental-generation protocol). ↔ `rules/visual-leverage.md` (M9 — diagram + prose pairing inside Markdown structural artifacts).
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "code-craft-python"
|
|
3
|
+
description: "Per-language code-craft for Python — strict SOLID compliance, modern type hinting (3.10+ syntax, no Any), Google-style docstrings, specific exception handling, pytest discipline, security guardrails (no hardcoded secrets, no shell injection, no unsafe deserialization), and architectural anti-pattern interception. Path-filtered to Python source files and configuration manifests."
|
|
4
|
+
pathFilter: "**/*.py, **/pyproject.toml, **/setup.py, **/setup.cfg, **/requirements*.txt, **/Pipfile, **/tox.ini, **/pytest.ini, **/conftest.py, **/.flake8, **/mypy.ini, **/ruff.toml, **/.ruff.toml, **/uv.toml, **/uv.lock, **/.python-version, **/pyrightconfig.json"
|
|
5
|
+
alwaysApply: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
9
|
+
|
|
10
|
+
# Rule: Code Craft — Python
|
|
11
|
+
|
|
12
|
+
## What this rule enforces
|
|
13
|
+
|
|
14
|
+
This rule binds **M13 — Code Craft Conventions** at the **Python per-language tier**. Every Python artifact the agent produces — script, hook, helper, library, test, configuration generator, migration script, deployment manifest, snippet — MUST meet a Senior-Architect floor: strict SOLID compliance, modern type hinting (Python 3.10+ syntax with conditional fallbacks per `python_requires`), Google-style docstrings, specific-exception handling, pytest-only test discipline, security-conscious code (no hardcoded secrets, no shell injection, no unsafe deserialization), and proactive anti-pattern interception. Correctness and readability supersede premature optimization. Output is clean, robust, scalable, maintainable, and idiomatically Pythonic.
|
|
15
|
+
|
|
16
|
+
## Pre-conditions
|
|
17
|
+
|
|
18
|
+
Applies whenever a Python artifact matching the `pathFilter` glob list — Python source, lockfiles, lint / format / type-check / test configurations, `python_requires` manifests, virtualenv pinning files — is authored, modified, or reviewed. The §6 seriousness scaling sets the FLOOR per level: any Python file touch activates at least the EXPLORING row even when the surrounding session is EXPLORING globally — never lower. Ecosystem-internal Python under `tools/`, `hooks/`, and `tests/` honors this rule alongside host-project Python.
|
|
19
|
+
|
|
20
|
+
## Required behavior
|
|
21
|
+
|
|
22
|
+
### 1. Strict SOLID Compliance
|
|
23
|
+
|
|
24
|
+
Non-negotiable in every non-trivial Python module:
|
|
25
|
+
|
|
26
|
+
- **SRP.** Every class, function, and module has exactly one reason to change. If a class name requires "and" to describe its purpose, it violates SRP — split it.
|
|
27
|
+
- **OCP.** Open for extension via composition, `Protocol`, and strategy patterns — closed for modification. Use registries, plugin patterns, and dispatch tables over growing `if/elif` chains.
|
|
28
|
+
- **LSP.** Every subclass perfectly substitutable for its parent — no weakened postconditions, no strengthened preconditions, no unexpected exceptions. If overriding tempts you to change the contract, use composition instead.
|
|
29
|
+
- **ISP.** `Protocol` classes with narrow interfaces over monolithic ABCs. A `Readable` protocol with `read()` beats a `FileHandler` ABC with `read()`, `write()`, `delete()`, `rename()`.
|
|
30
|
+
- **DIP.** High-level modules never import low-level modules — both depend on `Protocol` / `ABC` abstractions, with concrete implementations injected at composition root (`main()` or a DI container) and never constructed inside the consumer. Cross-layer injection discipline (which language-agnostic patterns to apply where) lives in `rules/clean-architecture-layers.md` §2.3 — this rule covers Python materialization only (`Protocol` / `ABC` choice, composition-root wiring style, `from __future__ import annotations` for forward references in interface modules).
|
|
31
|
+
|
|
32
|
+
### 2. Implementation & Style
|
|
33
|
+
|
|
34
|
+
#### 2.1 Version Detection
|
|
35
|
+
|
|
36
|
+
Before generating Python code, determine the project's minimum supported version from, in priority order: `python_requires` in `pyproject.toml` / `setup.cfg`, `.python-version`, `tox.ini` envlist, CI matrix. If undetermined, assume 3.10. Below 3.10: use `Optional[X]` not `X | None`, `Union[A, B]` not `A | B`, and omit `match`/`case`. Below 3.11: omit `Self`, and use `asyncio.gather` not `TaskGroup`. The (3.10+) / (3.11+) annotations below are conditional — emit modern syntax only when the detected target supports it.
|
|
37
|
+
|
|
38
|
+
#### 2.2 Formatting & Naming (M13.2)
|
|
39
|
+
|
|
40
|
+
- **PEP 8** baseline. Assume **`ruff`** for linting and formatting (preferred) or `black` (88 chars) + `isort`: (1) stdlib, (2) third-party, (3) local. Absolute imports only.
|
|
41
|
+
- `snake_case` functions / variables / modules, `PascalCase` classes / type aliases, `UPPER_SNAKE_CASE` constants, `_leading_underscore` internal / private.
|
|
42
|
+
- No single-char names except `i / j / k` in loops, `x` in lambdas, `_` for discarded. Names reveal intent: `calculate_portfolio_risk()` not `process_data()`.
|
|
43
|
+
|
|
44
|
+
#### 2.3 Type Hinting
|
|
45
|
+
|
|
46
|
+
Mandatory, strict, modern on ALL signatures, class attributes, and module-level variables:
|
|
47
|
+
|
|
48
|
+
- Modern syntax (3.10+): `list[int]`, `dict[str, T]`, `X | None` — never `List`, `Dict`, `Optional` from `typing`.
|
|
49
|
+
- **Ban `Any`** — use `Protocol`, `TypeVar`, `Generic`, or `@overload` instead. Narrow exceptions: third-party boundary types with incomplete stubs, JSON deserialization results pre-validation, and `**kwargs` forwarding to external APIs. Each use requires a justifying comment (`# Any: <reason>`).
|
|
50
|
+
- Use `TypeAlias` for complex types, `Literal` for constrained strings, `Final` for constants, `ClassVar` for class-level, `Self` (3.11+) for builder returns.
|
|
51
|
+
- `Protocol` over `ABC` for structural subtyping. Return type annotations mandatory including `-> None`.
|
|
52
|
+
|
|
53
|
+
#### 2.4 Documentation (M13.1, M13.11)
|
|
54
|
+
|
|
55
|
+
- **Google Style docstrings** (`Args:`, `Returns:`, `Raises:`) for all public entities. Private: docstring when logic is non-obvious.
|
|
56
|
+
- Inline comments explain **"why"**, never "what." No commented-out code (source control is the canonical archive). Module docstrings describe purpose and public API.
|
|
57
|
+
|
|
58
|
+
#### 2.5 Error & Resource Management (M13.3)
|
|
59
|
+
|
|
60
|
+
- Catch **specific exceptions** — never bare `except:` or generic `except Exception:` (unless re-raising at outermost boundary).
|
|
61
|
+
- `try / except / else / finally` used logically. Custom exception hierarchies rooted in project-level base. Exceptions carry context in message and attributes.
|
|
62
|
+
- Never raise exceptions as a signaling mechanism between layers (Python's EAFP idiom for guard checks is acceptable). Use `contextlib.suppress()` over empty `except` blocks.
|
|
63
|
+
- **Always context managers (`with`)** for I/O and resources. `@contextmanager` or `__enter__` / `__exit__` for custom lifecycle. `ExitStack` for dynamic resource counts. Never rely on GC for cleanup.
|
|
64
|
+
|
|
65
|
+
#### 2.6 Modern Patterns
|
|
66
|
+
|
|
67
|
+
- **`dataclasses` / `attrs`** for data-holding classes — never manual `__init__` / `__repr__` / `__eq__`. Use `field(default_factory=...)` for mutable defaults.
|
|
68
|
+
- **Pydantic** for external data validation. **`Enum`** for fixed constant sets — never magic strings / ints (M13.10).
|
|
69
|
+
- **`pathlib.Path`** over `os.path`. **f-strings** only. **`functools.cache` / `lru_cache`** for expensive pure functions.
|
|
70
|
+
- **`itertools` + generators** for lazy evaluation. **`__slots__`** for memory-dense classes. **`match` / `case`** (3.10+) for complex dispatch.
|
|
71
|
+
- **`asyncio`** for I/O-bound concurrency (M13.9). Never block the event loop with sync I/O. Use `TaskGroup` (3.11+) for structured concurrency. `async with` / `async for` for async resources and iterators.
|
|
72
|
+
- **`logging.getLogger(__name__)`** per module (M13.5). Structured logging via `structlog` for production. Never `print()` for operational output.
|
|
73
|
+
|
|
74
|
+
### 3. Testing Directives (M13.6)
|
|
75
|
+
|
|
76
|
+
- **`pytest` exclusively** — never `unittest.TestCase`. Test files mirror source: `src/domain/user.py` → `tests/domain/test_user.py`.
|
|
77
|
+
- **Arrange-Act-Assert** in every test, separated by blank lines. One behavior per test. Names describe behavior: `test_calculate_risk_raises_on_insufficient_data`.
|
|
78
|
+
- Cover **happy paths, edge cases** (boundary, empty, None, Unicode), and **failure modes** (invalid input, missing deps, timeouts). Every bug fix ships a regression test in the same change-set.
|
|
79
|
+
- **Fixtures** scoped to the narrowest sufficient scope. **`parametrize`** when input varies but the assertion pattern is constant. **`pytest.raises(match=...)`** for exception testing.
|
|
80
|
+
- **`unittest.mock.patch`** at the import site, not the definition. **`tmp_path`** for filesystem. **`monkeypatch`** for env vars. **Factory functions** for complex test data.
|
|
81
|
+
- Test behavior, never implementation details. Never mock what you do not own — wrap it in an adapter and mock the adapter. Never `sleep()` — mock the clock.
|
|
82
|
+
|
|
83
|
+
### 4. Security Directives (M13.8)
|
|
84
|
+
|
|
85
|
+
#### 4.1 Secrets & Configuration
|
|
86
|
+
|
|
87
|
+
- **Zero hardcoded secrets.** Keys, passwords, tokens from env vars or secret managers. `os.environ["KEY"]` (hard fail), never `get("KEY", "default")` for secrets.
|
|
88
|
+
- `.env` in `.gitignore`. Always verify before commit.
|
|
89
|
+
|
|
90
|
+
#### 4.2 Input Validation & Injection Prevention
|
|
91
|
+
|
|
92
|
+
- **Validate all external data** at system boundaries. **SQL**: parameterized queries only. **Commands**: never `shell=True` with untrusted input — use `subprocess.run(["cmd", arg])`.
|
|
93
|
+
- **Paths**: `pathlib.Path.resolve()` + verify within bounds. **Deserialization**: never `pickle` / `yaml.load()` for untrusted data — use `json` / `yaml.safe_load()` / Pydantic.
|
|
94
|
+
- **Templates**: auto-escaping (Jinja2 `autoescape=True`). **Regex**: avoid catastrophic backtracking; timeout user-supplied patterns.
|
|
95
|
+
|
|
96
|
+
#### 4.3 Dependency & Runtime Safety
|
|
97
|
+
|
|
98
|
+
- **Pin deps** in production (`==`). Ranges only in library `pyproject.toml`. **Audit** regularly (`pip-audit`, `safety`). Prefer **`uv`** for environment and dependency management.
|
|
99
|
+
- Never log secrets / PII. Structured logging with sanitized messages. Minimal privilege — never root unless required.
|
|
100
|
+
|
|
101
|
+
### 5. Architectural Guardrails
|
|
102
|
+
|
|
103
|
+
#### 5.1 Quality Audit
|
|
104
|
+
|
|
105
|
+
Audit for missing abstractions, leaky abstractions, god objects, feature envy (methods using another class's data more than their own), primitive obsession (raw `str` / `int` / `dict` where domain types add safety), inappropriate intimacy — triggered when reading, reviewing, or modifying a class / module of 150+ lines, or when a symbol recurs across 3+ files. Refactor immediately when detected; do not defer.
|
|
106
|
+
|
|
107
|
+
#### 5.2 Refactoring & Output
|
|
108
|
+
|
|
109
|
+
- **Concrete, scoped refactorings** — never vague. Atomic: one structural change per refactoring. Preserve all tests. Update all affected type hints, docstrings, imports.
|
|
110
|
+
- **Output**: concise working solution first → brief architectural rationale → surgical changes matching surrounding codebase conventions.
|
|
111
|
+
|
|
112
|
+
#### 5.3 Anti-Pattern Interception
|
|
113
|
+
|
|
114
|
+
Intercept during design: `isinstance` chains → `Protocol` / strategy. Mutable defaults → `field(default_factory=...)`. Global state → injected dependency. Circular imports → redesign boundaries. `import *` → explicit. String constants → `Enum`. `os.path` → `pathlib`. `print()` → `logging`. Sync I/O in async → flag.
|
|
115
|
+
|
|
116
|
+
### 6. Seriousness Scaling
|
|
117
|
+
|
|
118
|
+
| Level | Enforcement |
|
|
119
|
+
| ----- | ----------- |
|
|
120
|
+
| EXPLORING | PEP 8 + type hints + specific exceptions. SOLID awareness only |
|
|
121
|
+
| PERSONAL_USE | Full style. SOLID on public API. Public docstrings. AAA tests. No hardcoded secrets |
|
|
122
|
+
| SHARED | All sections enforced. Design violations are findings. Full test coverage. Security audit |
|
|
123
|
+
| PUBLIC_LAUNCH | Full + `mypy --strict`. 100% public API docs. Dependency audit. Security as quality gate |
|
|
124
|
+
|
|
125
|
+
### 7. Anti-Patterns
|
|
126
|
+
|
|
127
|
+
- **DON'T** use bare `except:` or `except Exception:` (unless re-raising at the outermost boundary) — **BECAUSE** it swallows errors and masks bugs.
|
|
128
|
+
- **DON'T** declare mutable defaults (`def f(items=[])`) — **BECAUSE** the default is shared across calls.
|
|
129
|
+
- **DON'T** use `Any` type hints — **BECAUSE** it disables type checking where you need it most.
|
|
130
|
+
- **DON'T** subclass built-ins (`dict`, `list`) — **BECAUSE** C methods bypass overrides. Use `UserDict` / `UserList`.
|
|
131
|
+
- **DON'T** write monolithic test functions with multiple Act-Assert pairs — **BECAUSE** the first failure masks the rest.
|
|
132
|
+
- **DON'T** suppress with `# type: ignore` without an error code + justifying comment — **BECAUSE** blanket suppression hides real errors.
|
|
133
|
+
- **DON'T** inherit concrete classes for reuse — **BECAUSE** brittle hierarchies. Use composition + `Protocol`.
|
|
134
|
+
|
|
135
|
+
## Disclosure surface
|
|
136
|
+
|
|
137
|
+
Every Python artifact emission, refit, or anti-pattern interception is recorded in the disclosure ledger per `rules/disclosure-ledger.md`:
|
|
138
|
+
|
|
139
|
+
- `[Discovery — source: pyproject.toml | setup.cfg | .python-version | tox.ini; value: <python_requires>; honored]` for every version-detection outcome that shapes type-hint syntax.
|
|
140
|
+
- `[Discovery — source: ruff.toml | .ruff.toml | pyproject.toml [tool.ruff]; value: <ruleset>; honored]` for honored lint-config discoveries.
|
|
141
|
+
- `[Refinement — improvement: maintainability; intercepted: <anti-pattern>; refactor: <description>]` for proactive anti-pattern interceptions during design.
|
|
142
|
+
- `[Default — applied: <auto-decision>; class: pure-formatting-normalization]` for ruff / black formatter normalizations on existing files where the host has a ratified style.
|
|
143
|
+
|
|
144
|
+
## Failure tells
|
|
145
|
+
|
|
146
|
+
`def f(items=[])` (mutable default — shared across calls). `except:` / `except Exception: pass` (silent swallow — M13.3 violation). `Any` type hint without `# Any: <reason>` justifying comment (typecheck disabled where it matters most). `from typing import Optional, Union` in a project with `python_requires = ">=3.10"` (legacy syntax where modern is available). `subprocess.run(cmd, shell=True)` with untrusted input (shell injection — M13.8). `pickle.loads(untrusted_bytes)` (deserialization attack surface). `yaml.load(untrusted)` without `Loader=yaml.SafeLoader` (RCE attack surface). `print()` for operational output (M13.5 — should be `logging.getLogger(__name__).info(...)`). Tests written as `unittest.TestCase` subclasses in a project with `pytest` configured (test-framework drift — M13.6). `# TODO: fix this` without a tracking issue (open marker per `rules/definitiveness.md` M8). `os.path.join(a, b)` in a 3.10+ codebase (legacy API — should be `pathlib.Path(a) / b`). Magic numbers in business logic without named constants (M13.10). Public function with no docstring (M13.11). A test using `time.sleep(3)` to wait for a side effect (timing dependency instead of mocking time).
|
|
147
|
+
|
|
148
|
+
## Bindings (§0.j five-direction)
|
|
149
|
+
|
|
150
|
+
- **Drives →** ● Every Python artifact's quality floor across every host project (SOLID enforcement, type-hint discipline, docstring requirement, pytest convention, security guardrails). ● Every `tools/*.py` and `hooks/*.py` and `tests/*.py` touch under the path-filter. ● Every Python-language manifestation of the Senior Software Architect role declared at `rules/cognitive-identity.md` §1. ◐ The Python-language materialization of clean architecture layer discipline (the §1 DIP discussion cross-references `rules/clean-architecture-layers.md` §2.3).
|
|
151
|
+
- **Satisfies →** ● the fifteen-mandate registry row **M13 — Code Craft** at the Python per-language tier. ● CM-28 (Python Senior Architect — rule-delegated mandate; this rule is the canonical specification CM-28 delegates to). ● the rules registry row "Code Craft — Python".
|
|
152
|
+
- **Established by ↑** ● the fifteen-mandate registry (ratifies M13). ● CM-28. ● `rules/cognitive-identity.md` (Python is the primary language declared at §2). ● PEP 8, PEP 484, PEP 604, PEP 612, PEP 695 (the upstream Python language standards this rule projects).
|
|
153
|
+
- **Gated by ←** ● The path-filter (17 glob patterns covering `*.py`, `pyproject.toml`, `setup.cfg`, `requirements*.txt`, `Pipfile`, `tox.ini`, `pytest.ini`, `conftest.py`, lint configs) — this rule activates only on Python-language artifact touches. ● `rules/cognitive-identity.md` Senior Software Architect role declaration. ● the trivial-vs-non-trivial threshold (trivial-scope Python edits run an abbreviated check covering M13.7 lint / format only).
|
|
154
|
+
- **Cross-bound with ↔** ↔ `rules/code-craft-conventions.md` (universal-delegation stub yields to this rule when the artifact's path matches; the universal floor M13.1–M13.11 is materialized here in Python idioms). ↔ `rules/code-craft-shell.md` + `rules/code-craft-markdown.md` (sibling per-language code-craft rules; consistent body shape across the trio). ↔ `rules/clean-architecture-layers.md` (Python materializes the layer discipline through `Protocol` / `ABC` choice + composition-root patterns; §1 DIP cross-references that rule's §2.3). ↔ `rules/cognitive-identity.md` (the Senior Software Architect role's Python-language manifestation). ↔ `rules/clean-room-generation.md` (Python code emission passes the Writing Protocol §2 + Code Generation §4 before this rule's path-filtered guardrails apply). ↔ `rules/operational-mandates.md` §CM-28 (the inline registry entry that delegates here). ↔ `rules/performance-discipline.md` §1.1 (the per-class performance budgets apply to Python artifacts under this rule's path-filter). ↔ `rules/refactoring-discipline.md` (the per-language quality bar a refactor's deficiency-elevation targets).
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "code-craft-shell"
|
|
3
|
+
description: "Per-language code-craft for shell artifacts — POSIX bash idioms (set -euo pipefail; quoted variables; no eval on untrusted input; trap-based cleanup) and PowerShell idioms (Set-StrictMode -Version Latest; verb-noun cmdlet naming; no Invoke-Expression on untrusted input; structured error records). Honor shellcheck for bash and Invoke-ScriptAnalyzer for PowerShell; pass the host's ratified shell linter clean."
|
|
4
|
+
pathFilter: "**/*.sh, **/*.bash, **/*.ps1, **/*.psm1, **/*.psd1"
|
|
5
|
+
alwaysApply: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
9
|
+
|
|
10
|
+
# Rule: Code Craft — Shell
|
|
11
|
+
|
|
12
|
+
## What this rule enforces
|
|
13
|
+
|
|
14
|
+
This rule binds **M13 — Code Craft Conventions** at the **shell per-language tier**, covering POSIX bash and PowerShell. Every shell artifact the agent produces — script, hook stub, build helper, runner, deployment driver, environment activator, CI-pipeline glue, one-shot administrative command — MUST meet the M13.1–M13.11 floor with shell-specific materialization: strict mode by default, every variable quoted, no shell injection on untrusted input, deterministic error handling with explicit exit codes, named constants over magic numbers, and behavior-shaped tests where the host has a shell-test framework. The artifact MUST pass `shellcheck` (bash / sh) and `Invoke-ScriptAnalyzer` (PowerShell) clean against the host's ratified configuration.
|
|
15
|
+
|
|
16
|
+
## Pre-conditions
|
|
17
|
+
|
|
18
|
+
Applies whenever a shell artifact matching the `pathFilter` glob list — `*.sh`, `*.bash`, `*.ps1`, `*.psm1`, `*.psd1` — is authored, modified, or reviewed. Ecosystem-internal shell stubs under `hooks/lib/bootstrap.sh` and `hooks/lib/bootstrap.ps1` (and siblings) honor this rule alongside host-project shell. The shell-execution sub-budgets at `rules/performance-discipline.md` §1.1 govern the runtime ceiling for hook bootstrap stubs and shell linters; this rule governs their static-form quality.
|
|
19
|
+
|
|
20
|
+
## Required behavior
|
|
21
|
+
|
|
22
|
+
### 1. Strict-Mode Defaults
|
|
23
|
+
|
|
24
|
+
#### 1.1 POSIX bash / sh
|
|
25
|
+
|
|
26
|
+
Every bash script opens with strict-mode declarations as the first non-shebang, non-comment lines:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
#!/usr/bin/env bash
|
|
30
|
+
# Optional: header comment naming purpose / why-not-what / cross-references
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
IFS=$'\n\t'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- **`set -e`** — exit immediately on any command failure (no silent error swallowing).
|
|
36
|
+
- **`set -u`** — unset variable reference is an error (catches typos at runtime).
|
|
37
|
+
- **`set -o pipefail`** — a pipeline's exit status is the last non-zero in the chain (no silent failure of `cmd1 | cmd2` when `cmd1` fails).
|
|
38
|
+
- **`IFS=$'\n\t'`** — restrict word-splitting to newline + tab; eliminates a class of space-bearing-filename bugs.
|
|
39
|
+
|
|
40
|
+
When the host's existing shell scripts use a different strict-mode discipline (e.g., `set -eEuo pipefail` adding the `-E` ERR-trap inheritance), honor the host's discovery per `rules/host-discovery.md`.
|
|
41
|
+
|
|
42
|
+
#### 1.2 PowerShell
|
|
43
|
+
|
|
44
|
+
Every PowerShell script opens with strict-mode declaration:
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
#Requires -Version 7.0
|
|
48
|
+
Set-StrictMode -Version Latest
|
|
49
|
+
$ErrorActionPreference = 'Stop'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- **`Set-StrictMode -Version Latest`** — uninitialized variable reference, missing object property access, function call with too-many positional args all become errors.
|
|
53
|
+
- **`$ErrorActionPreference = 'Stop'`** — non-terminating errors become terminating, eliminating the silent-error class.
|
|
54
|
+
- **`#Requires -Version 7.0`** — declare the minimum PowerShell version (or `5.1` when targeting Windows PowerShell). Match the host's discovered minimum.
|
|
55
|
+
|
|
56
|
+
### 2. Variable Quoting & Word-Splitting
|
|
57
|
+
|
|
58
|
+
#### 2.1 Bash
|
|
59
|
+
|
|
60
|
+
Every variable expansion is double-quoted unless the unquoted form is a deliberate word-splitting use:
|
|
61
|
+
|
|
62
|
+
- **Right form:** `cp -- "$src" "$dst"` (handles spaces, tabs, glob characters in `$src` and `$dst`).
|
|
63
|
+
- **Wrong form:** `cp $src $dst` (silently breaks on a path containing a space; security risk on adversarial inputs).
|
|
64
|
+
- **Argument terminators.** Use `--` before path arguments to disambiguate against unintended option parsing (`rm -- "$file"`).
|
|
65
|
+
- **Array expansion.** `"${array[@]}"` to expand each element as a separate argument; `"${array[*]}"` only when joining is intended.
|
|
66
|
+
|
|
67
|
+
#### 2.2 PowerShell
|
|
68
|
+
|
|
69
|
+
PowerShell handles word-splitting differently — variables are not subject to bash-style word-splitting. The discipline:
|
|
70
|
+
|
|
71
|
+
- **Stop-parsing token.** When invoking native executables that take arguments PowerShell would parse as operators, use `--%` to prevent re-parsing: `git log --% --format=%H`.
|
|
72
|
+
- **Splatting.** Pass argument arrays via splatting (`@args`) rather than string concatenation to preserve quoting.
|
|
73
|
+
- **Path operations.** Use `Join-Path` and `[System.IO.Path]::Combine()` rather than string concatenation for path construction.
|
|
74
|
+
|
|
75
|
+
### 3. Injection Prevention (M13.8)
|
|
76
|
+
|
|
77
|
+
A shell command or PowerShell expression MUST NOT be constructed from untrusted input:
|
|
78
|
+
|
|
79
|
+
#### 3.1 Bash
|
|
80
|
+
|
|
81
|
+
- **No `eval` on untrusted input.** `eval "$user_input"` is RCE. Use `case` / function dispatch instead.
|
|
82
|
+
- **No unquoted command substitution containing untrusted input.** `cmd $(echo "$user_input")` re-splits on word-splitting; prefer arrays.
|
|
83
|
+
- **No `bash -c "$untrusted"`.** Same RCE class. Pass arguments through `argv`, not via interpolation.
|
|
84
|
+
- **`xargs` with `-0` and `-r`** when chaining filename lists; otherwise newline-bearing names break the pipeline.
|
|
85
|
+
|
|
86
|
+
#### 3.2 PowerShell
|
|
87
|
+
|
|
88
|
+
- **No `Invoke-Expression` on untrusted input.** Same RCE class as bash `eval`. Use script blocks (`& { ... }`) with parameterized arguments instead.
|
|
89
|
+
- **No string-formatted SQL / shell commands.** Parameterized cmdlets honor quoting; string-formatted commands do not.
|
|
90
|
+
- **`-LiteralPath` over `-Path`** when the path is data, not a glob pattern (Path expands wildcards; LiteralPath does not).
|
|
91
|
+
|
|
92
|
+
### 4. Error Handling & Exit Codes (M13.3)
|
|
93
|
+
|
|
94
|
+
#### 4.1 Bash
|
|
95
|
+
|
|
96
|
+
- **Explicit exit codes.** `exit 0` for success; `exit 1`–`125` for documented failure modes (avoid 126 / 127 / 128+, reserved by POSIX for shell-internal errors).
|
|
97
|
+
- **`trap` for cleanup.** Resources allocated in the script (temp files, lock files, mounts, child processes) are released by a `trap '...' EXIT INT TERM` clause, not deferred to GC.
|
|
98
|
+
- **Error context on failure.** When a command fails, the failure message names the command, the input, and the exit code: `printf 'error: <command> failed (exit %d) with input %q\n' "$rc" "$input" >&2; exit "$rc"`.
|
|
99
|
+
- **No silent failure.** Every command whose failure is recoverable is wrapped in an explicit conditional; every command whose failure is fatal is allowed to propagate via `set -e`.
|
|
100
|
+
|
|
101
|
+
#### 4.2 PowerShell
|
|
102
|
+
|
|
103
|
+
- **Throw structured errors.** `throw [System.IO.FileNotFoundException]::new("$path")` rather than `throw "file not found"` (typed errors are catchable by type).
|
|
104
|
+
- **Try / catch / finally** over `$LASTEXITCODE` checks for cmdlet errors. Native-exe errors still need `$LASTEXITCODE` inspection.
|
|
105
|
+
- **`exit $exitCode`** at script tail makes the exit code explicit; absence defaults to 0 even after errors in `$ErrorActionPreference = 'Continue'` mode.
|
|
106
|
+
|
|
107
|
+
### 5. Naming & Documentation (M13.2, M13.11)
|
|
108
|
+
|
|
109
|
+
#### 5.1 Bash
|
|
110
|
+
|
|
111
|
+
- **Function names** use snake_case: `cleanup_tempfiles`, `parse_arguments`, `validate_input`.
|
|
112
|
+
- **Variable names** for script-level constants use UPPER_SNAKE_CASE: `readonly LOG_DIR="/var/log/app"`.
|
|
113
|
+
- **Local variables** inside functions use lower_snake_case and the `local` keyword: `local input="$1"; local rc=0`.
|
|
114
|
+
- **Header comment** at the top of the script names: purpose, dependencies (other scripts / binaries the script invokes), invocation example, exit-code catalog.
|
|
115
|
+
|
|
116
|
+
#### 5.2 PowerShell
|
|
117
|
+
|
|
118
|
+
- **Verb-noun cmdlet naming.** Functions follow the approved-verb list (`Get-Verb` lists them): `Get-FooConfig`, `Set-FooConfig`, `New-FooSession`, `Remove-FooSession`, `Test-FooReachability`. Non-approved verbs trigger `Invoke-ScriptAnalyzer` warnings.
|
|
119
|
+
- **Comment-based help.** Every public function carries a `<# .SYNOPSIS / .DESCRIPTION / .PARAMETER / .EXAMPLE / .OUTPUTS #>` block per the host's ratified discipline.
|
|
120
|
+
|
|
121
|
+
### 6. Magic Numbers & Constants (M13.10)
|
|
122
|
+
|
|
123
|
+
Numeric literals in shell logic become named constants:
|
|
124
|
+
|
|
125
|
+
#### 6.1 Bash
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
readonly TIMEOUT_SECONDS=30
|
|
129
|
+
readonly MAX_RETRIES=3
|
|
130
|
+
readonly EXIT_INVALID_INPUT=2
|
|
131
|
+
|
|
132
|
+
if (( retries >= MAX_RETRIES )); then
|
|
133
|
+
exit "$EXIT_INVALID_INPUT"
|
|
134
|
+
fi
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Avoid literal `30`, `3`, `2` in the body — the named constants tell the next reader why these values.
|
|
138
|
+
|
|
139
|
+
#### 6.2 PowerShell
|
|
140
|
+
|
|
141
|
+
```powershell
|
|
142
|
+
$Script:TimeoutSeconds = 30
|
|
143
|
+
$Script:MaxRetries = 3
|
|
144
|
+
$Script:ExitInvalidInput = 2
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 7. Linting & Static Analysis (M13.7)
|
|
148
|
+
|
|
149
|
+
The artifact passes the host's ratified shell linter clean:
|
|
150
|
+
|
|
151
|
+
- **Bash.** `shellcheck script.sh` exits 0. The host's `.shellcheckrc` is honored per M1 host-discovery; sibling scripts' shellcheck-disable directives are followed unless the new script's context warrants different.
|
|
152
|
+
- **PowerShell.** `Invoke-ScriptAnalyzer -Path script.ps1 -Severity Error,Warning` exits 0. The host's `PSScriptAnalyzerSettings.psd1` is honored.
|
|
153
|
+
|
|
154
|
+
The shell-linter performance budgets at `rules/performance-discipline.md` §1.1 govern the runtime ceiling: 5s for `shellcheck` over `hooks/lib/*.sh`, 10s for `Invoke-ScriptAnalyzer` over `hooks/lib/*.ps1`.
|
|
155
|
+
|
|
156
|
+
### 8. Testing (M13.6)
|
|
157
|
+
|
|
158
|
+
Where the host has a ratified shell-test framework:
|
|
159
|
+
|
|
160
|
+
- **bats-core** for bash. Test files at `tests/bash/<unit>.bats`. AAA shape: `setup() { … }` (Arrange) → `@test 'description' { run cmd; ... }` (Act) → `[ "$status" -eq 0 ]; [ "$output" = '...' ]` (Assert).
|
|
161
|
+
- **Pester** for PowerShell. Test files at `tests/powershell/<unit>.Tests.ps1`. AAA shape: `BeforeAll { … }` (Arrange) → `It 'description' { $result = Invoke-Foo … }` (Act) → `$result | Should -Be 'expected'` (Assert).
|
|
162
|
+
|
|
163
|
+
When the host has no shell-test framework configured but the script's behavior warrants verification, surface as an inquiry per `rules/authority-inquiry.md` with bats-core / Pester recommended per the language.
|
|
164
|
+
|
|
165
|
+
### 9. Cross-Platform Convention
|
|
166
|
+
|
|
167
|
+
When a script must run on multiple platforms (Windows + POSIX), prefer:
|
|
168
|
+
|
|
169
|
+
- **Pure POSIX sh** when the script's surface is small and dependency-free (no `[[ ]]`, no arrays, no `$(<file)` substitutions).
|
|
170
|
+
- **Bash with explicit `#!/usr/bin/env bash`** when the script needs bash features and the host has bash on every target platform.
|
|
171
|
+
- **Two parallel scripts** (`script.sh` + `script.ps1`) when the host has POSIX-only and Windows-only paths, with the dispatching wrapper choosing per platform. This is the pattern the ecosystem uses at `hooks/lib/bootstrap.{sh,ps1}` per the canonical-pair discipline declared in the hooks pipeline Paired-Template Review Cadence.
|
|
172
|
+
|
|
173
|
+
## Disclosure surface
|
|
174
|
+
|
|
175
|
+
Every shell artifact emission, refactor, or anti-pattern interception is recorded in the disclosure ledger per `rules/disclosure-ledger.md`:
|
|
176
|
+
|
|
177
|
+
- `[Discovery — source: .shellcheckrc | sibling-shell-scripts; value: <strict-mode-form | linter-config>; honored]` for shellcheck-config and bash-idiom discoveries.
|
|
178
|
+
- `[Discovery — source: PSScriptAnalyzerSettings.psd1 | sibling-ps1-scripts; value: <ruleset>; honored]` for PowerShell linter-config discoveries.
|
|
179
|
+
- `[Refinement — improvement: security; intercepted: <eval | Invoke-Expression | shell-injection-pattern>; replacement: <safe-form>]` for security interceptions.
|
|
180
|
+
- `[Default — applied: <auto-decision>; class: pure-formatting-normalization]` for shellcheck / Invoke-ScriptAnalyzer normalizations on existing files where the host has a ratified style.
|
|
181
|
+
|
|
182
|
+
## Failure tells
|
|
183
|
+
|
|
184
|
+
`#!/bin/sh` followed by bash-only constructs (`[[ ]]`, arrays, `$()` instead of backticks in old-shell contexts — bashism creep). A bash script with no `set -euo pipefail` (silent-error class). A bash script using `set -e` but with `||` chains that swallow the `-e` propagation without explicit handling. Variable expansion without quotes (`cp $src $dst` instead of `cp -- "$src" "$dst"`). `eval "$user_input"` (RCE). `bash -c "$untrusted"` (RCE). A PowerShell script with no `Set-StrictMode` (uninitialized-variable class). A PowerShell script using `Invoke-Expression` on untrusted input (RCE). A PowerShell function named with a non-approved verb (`Process-Foo` instead of `Update-Foo` or `Invoke-Foo`). A bash script that fails `shellcheck` with new findings the host's existing scripts do not have. A PowerShell script that fails `Invoke-ScriptAnalyzer -Severity Error,Warning`. Magic numbers in retry / timeout / buffer-size logic without named constants. A trap-less bash script that allocates a tempfile and exits without cleanup. A PowerShell script that throws a string literal (`throw "error"`) instead of a typed exception. A cross-platform-intended script that uses bash-only constructs without a PowerShell parallel.
|
|
185
|
+
|
|
186
|
+
## Bindings (§0.j five-direction)
|
|
187
|
+
|
|
188
|
+
- **Drives →** ● Every shell artifact's quality floor across every host project (strict-mode defaults, variable quoting, injection prevention, deterministic error handling). ● Every `hooks/lib/bootstrap.sh` and `hooks/lib/bootstrap.ps1` touch under the path-filter (the canonical-pair stubs governed by the hooks pipeline). ● Every CI shell stub, deployment driver, and environment activator. ◐ The shell-execution sub-budgets at `rules/performance-discipline.md` §1.1.
|
|
189
|
+
- **Satisfies →** ● the fifteen-mandate registry row **M13 — Code Craft** at the shell per-language tier. ● the rules registry row "Code Craft — Shell".
|
|
190
|
+
- **Established by ↑** ● the fifteen-mandate registry (ratifies M13). ● POSIX shell standards (IEEE Std 1003.1) and PowerShell language specification (Microsoft Learn). ● `shellcheck` rules catalog (the upstream lint rulebook this rule projects). ● `PSScriptAnalyzer` rules catalog (the upstream PowerShell lint rulebook this rule projects).
|
|
191
|
+
- **Gated by ←** ● The path-filter (`*.sh`, `*.bash`, `*.ps1`, `*.psm1`, `*.psd1`) — this rule activates only on shell-language artifact touches. ● the trivial-vs-non-trivial threshold (trivial-scope shell edits run an abbreviated check covering strict-mode and quoting only).
|
|
192
|
+
- **Cross-bound with ↔** ↔ `rules/code-craft-conventions.md` (universal-delegation stub yields to this rule when the artifact's path matches; the universal floor M13.1–M13.11 is materialized here in shell idioms). ↔ `rules/code-craft-python.md` + `rules/code-craft-markdown.md` (sibling per-language code-craft rules; consistent body shape across the trio). ↔ `rules/performance-discipline.md` §1.1 (per-shell budgets — bootstrap.sh ≤ 500ms, bootstrap.ps1 ≤ 1500ms, find-python.{sh,ps1} ≤ 200ms, shellcheck ≤ 5s, Invoke-ScriptAnalyzer ≤ 10s; this rule is the static-form quality discipline whose runtime is governed there). ↔ `rules/host-discovery.md` (M1 — shellcheck and ScriptAnalyzer config discovery walks). ↔ `rules/clean-room-generation.md` (Code Generation §4 governs initial shell emission before this rule's path-filtered guardrails apply).
|