claude-dev-env 2.9.0 → 2.10.0
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/CLAUDE.md +1 -1
- package/_shared/pr-loop/CLAUDE.md +1 -1
- package/_shared/pr-loop/audit-contract.md +17 -6
- package/_shared/pr-loop/audit-reply-template.md +4 -4
- package/_shared/pr-loop/code-rules-gate.md +3 -5
- package/_shared/pr-loop/fix-protocol.md +2 -3
- package/_shared/pr-loop/gh-payloads.md +1 -1
- package/_shared/pr-loop/scripts/CLAUDE.md +1 -1
- package/_shared/pr-loop/scripts/README.md +1 -1
- package/_shared/pr-loop/scripts/code_rules_gate.py +2 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_running.py +16 -1
- package/_shared/pr-loop/scripts/code_rules_gate_parts/git_blob_readers.py +11 -5
- package/_shared/pr-loop/scripts/preflight.py +9 -4
- package/_shared/pr-loop/scripts/reviews_disabled.py +50 -22
- package/_shared/pr-loop/scripts/tests/conftest.py +20 -0
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +6 -6
- package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +50 -6
- package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +1 -1
- package/_shared/pr-loop/state-schema.md +5 -14
- package/agents/CLAUDE.md +2 -2
- package/agents/clean-coder.md +58 -548
- package/agents/code-quality-agent.md +10 -2
- package/agents/code-verifier.md +1 -1
- package/agents/test_agent_frontmatter.py +32 -40
- package/audit-rubrics/CLAUDE.md +2 -1
- package/audit-rubrics/audit-categories.json +704 -0
- package/audit-rubrics/prompts/category-i-concurrency.md +1 -1
- package/bin/CLAUDE.md +16 -5
- package/bin/ever-shipped-skills.mjs +2 -0
- package/bin/install-plan.mjs +402 -0
- package/bin/install-transaction.mjs +455 -0
- package/bin/install.mjs +593 -147
- package/bin/install.plan.test.mjs +194 -0
- package/bin/install.profile-root.test.mjs +154 -0
- package/bin/install.profiles.test.mjs +253 -0
- package/bin/install.settings-defaults.test.mjs +200 -0
- package/bin/install.transaction.test.mjs +400 -0
- package/bin/install.uninstall-transaction.test.mjs +418 -0
- package/bin/merge_managed_permissions.mjs +130 -0
- package/bin/resolve-install-root.mjs +181 -0
- package/bin/select-install-targets.mjs +401 -0
- package/commands/CLAUDE.md +0 -2
- package/docs/references/CLAUDE.md +1 -0
- package/docs/references/advisor-tool.md +1 -1
- package/docs/references/prose-style-enforcement.md +25 -0
- package/hooks/blocking/CLAUDE.md +6 -6
- package/hooks/blocking/_path_setup.py +9 -5
- package/hooks/blocking/code_rules_docstrings.py +124 -30
- package/hooks/blocking/code_rules_enforcer.py +161 -16
- package/hooks/blocking/code_rules_shared.py +40 -23
- package/hooks/blocking/config/CLAUDE.md +3 -5
- package/hooks/blocking/config/prose_style_enforcement_constants.py +38 -0
- package/hooks/blocking/config/test_prose_style_enforcement_constants.py +45 -0
- package/hooks/blocking/eli11_reply_enforcer.py +70 -113
- package/hooks/blocking/hedging_language_blocker.py +103 -20
- package/hooks/blocking/hook_prose_detector_consistency.py +6 -0
- package/hooks/blocking/intent_only_ending_blocker.py +6 -0
- package/hooks/blocking/plain_language_blocker.py +139 -20
- package/hooks/blocking/pre_tool_use_dispatcher.py +102 -20
- package/hooks/blocking/state_description_blocker.py +7 -1
- package/hooks/blocking/tdd_enforcer.py +8 -0
- package/hooks/blocking/test__path_setup.py +28 -0
- package/hooks/blocking/test_code_rules_enforcer_agent_home_tooling.py +99 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +232 -10
- package/hooks/blocking/test_code_rules_enforcer_ephemeral.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_join_separator_magic.py +41 -0
- package/hooks/blocking/test_code_rules_enforcer_string_magic.py +98 -0
- package/hooks/blocking/test_eli11_reply_enforcer.py +98 -165
- package/hooks/blocking/test_hedging_language_blocker.py +120 -1
- package/hooks/blocking/test_hook_prose_detector_consistency.py +28 -8
- package/hooks/blocking/test_intent_only_ending_blocker.py +27 -2
- package/hooks/blocking/test_package_inventory_stale_blocker.py +11 -4
- package/hooks/blocking/test_plain_language_blocker.py +129 -19
- package/hooks/blocking/test_plain_language_blocker_allowlist.py +70 -26
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +99 -26
- package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +87 -50
- package/hooks/blocking/test_state_description_blocker.py +45 -2
- package/hooks/blocking/test_stop_dispatcher.py +11 -7
- package/hooks/blocking/test_volatile_path_in_post_blocker.py +12 -12
- package/hooks/blocking/volatile_path_in_post_blocker.py +2 -2
- package/hooks/hooks.json +15 -0
- package/hooks/hooks_constants/CLAUDE.md +14 -3
- package/hooks/hooks_constants/ask_user_question_shape.py +281 -0
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +2 -1
- package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +5 -12
- package/hooks/hooks_constants/hedging_uncertainty_constants.py +42 -0
- package/hooks/hooks_constants/issue_tracker_session_starter_constants.py +23 -0
- package/hooks/hooks_constants/orchestrator_auto_starter_constants.py +23 -0
- package/hooks/hooks_constants/piped_pytest_blocker_constants.py +4 -1
- package/hooks/hooks_constants/plain_language_blocker_constants.py +4 -1
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +6 -0
- package/hooks/hooks_constants/project_paths_reader.py +31 -4
- package/hooks/hooks_constants/prose_matcher_precision_constants.py +40 -0
- package/hooks/hooks_constants/pytest_invocation.py +354 -0
- package/hooks/hooks_constants/session_start_injector.py +163 -0
- package/hooks/hooks_constants/session_start_injector_constants.py +46 -0
- package/hooks/hooks_constants/shell_command_pipeline.py +397 -0
- package/hooks/hooks_constants/shell_command_segments.py +5 -0
- package/hooks/hooks_constants/test_ask_user_question_shape.py +167 -0
- package/hooks/hooks_constants/test_project_paths_reader.py +29 -0
- package/hooks/hooks_constants/test_prose_metrics_parity.py +8 -0
- package/hooks/hooks_constants/test_pytest_invocation.py +130 -0
- package/hooks/hooks_constants/test_session_start_injector.py +168 -0
- package/hooks/hooks_constants/test_shell_command_pipeline.py +135 -0
- package/hooks/hooks_constants/volatile_path_in_post_blocker_constants.py +1 -1
- package/hooks/hooks_constants/working_style_prompt_constants.py +30 -0
- package/hooks/observability/CLAUDE.md +2 -0
- package/hooks/observability/prose_matcher_advisory.py +237 -0
- package/hooks/observability/test_prose_matcher_advisory.py +143 -0
- package/hooks/session/CLAUDE.md +9 -1
- package/hooks/session/_path_setup.py +13 -0
- package/hooks/session/issue_tracker_session_starter.py +135 -0
- package/hooks/session/orchestrator_auto_starter.py +100 -0
- package/hooks/session/test__path_setup.py +28 -0
- package/hooks/session/test_issue_tracker_session_starter.py +104 -0
- package/hooks/session/test_orchestrator_auto_starter.py +99 -0
- package/hooks/session/test_working_style_prompt.py +47 -0
- package/hooks/session/untracked_repo_detector.py +1 -24
- package/hooks/session/working_style_prompt.py +36 -0
- package/hooks/validators/_path_setup.py +19 -0
- package/hooks/validators/run_all_validators.py +8 -13
- package/installable-surfaces.manifest.json +21 -0
- package/output-styles/CLAUDE.md +1 -3
- package/package.json +4 -2
- package/rules/CLAUDE.md +1 -0
- package/rules/durable-post-artifacts.md +2 -2
- package/rules/eli11-replies.md +6 -1
- package/rules/hedging-claims.md +4 -2
- package/rules/long-horizon-autonomy.md +3 -1
- package/rules/opus5-communication-contract.md +45 -0
- package/rules/plain-language.md +2 -2
- package/rules/research-mode.md +1 -1
- package/scripts/CLAUDE.md +11 -0
- package/scripts/Sync-RepoMain.ps1 +215 -0
- package/scripts/active_capability_references.py +218 -0
- package/scripts/ci/windows-installer-lifecycle.ps1 +78 -0
- package/scripts/claude_chain_runner.py +394 -6
- package/scripts/claude_chain_usage.py +1 -1
- package/scripts/codex_compat_materializer.py +105 -85
- package/scripts/dev_env_scripts_constants/CLAUDE.md +2 -0
- package/scripts/dev_env_scripts_constants/active_capability_constants.py +46 -0
- package/scripts/dev_env_scripts_constants/claude_chain_constants.py +74 -0
- package/scripts/dev_env_scripts_constants/verify_installable_package_constants.py +116 -0
- package/scripts/profile-isolation-launchers/config/mcp-bundles.json +25 -0
- package/scripts/profile-isolation-launchers/config/profile-isolation-constants.mjs +60 -0
- package/scripts/profile-isolation-launchers/config/profiles.manifest.json +54 -0
- package/scripts/profile-isolation-launchers/config/shared-allowlist.json +64 -0
- package/scripts/profile-isolation-launchers/launcher-runtime.mjs +180 -0
- package/scripts/profile-isolation-launchers/lib/profile-manifest.mjs +288 -0
- package/scripts/profile-isolation-launchers/mcp-bundles.mjs +275 -0
- package/scripts/profile-isolation-launchers/profile-isolation-contract.test.mjs +221 -0
- package/scripts/profile-isolation-launchers/tests/launcher-runtime.test.mjs +108 -0
- package/scripts/profile-isolation-launchers/tests/mcp-bundles.test.mjs +147 -0
- package/scripts/profile-isolation-launchers/tests/shortcut-contract.test.ps1 +102 -0
- package/scripts/profile-isolation-launchers/tests/version-compatibility.test.mjs +210 -0
- package/scripts/profile-isolation-launchers/version-compatibility.mjs +299 -0
- package/scripts/profile-isolation-launchers/windows/shortcut-inventory.ps1 +127 -0
- package/scripts/profile-isolation-launchers/windows/shortcut-manifest.json +51 -0
- package/scripts/profile-isolation-launchers/windows/shortcut-reconcile.ps1 +77 -0
- package/scripts/spawn_grok_batch.py +3 -0
- package/scripts/test_active_capability_references.py +108 -0
- package/scripts/test_claude_chain_runner.py +414 -82
- package/scripts/test_claude_chain_usage.py +12 -12
- package/scripts/test_resolve_worker_spawn.py +2 -2
- package/scripts/test_verify_installable_package.py +208 -0
- package/scripts/tests/test_codex_compat_materializer.py +33 -0
- package/scripts/verify_installable_package.py +612 -0
- package/settings.json +10 -0
- package/skills/CLAUDE.md +2 -0
- package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -0
- package/skills/_shared/pr-loop/scripts/audit_category_schema.py +355 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +32 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +7 -19
- package/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +94 -0
- package/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +21 -0
- package/skills/autoconverge/reference/convergence.md +2 -1
- package/skills/autoconverge/reference/stop-conditions.md +5 -3
- package/skills/beat-sheet/SKILL.md +54 -0
- package/skills/beat-sheet/reference/visual-beats.md +29 -0
- package/skills/bugteam/CONSTRAINTS.md +4 -4
- package/skills/bugteam/EXAMPLES.md +1 -1
- package/skills/bugteam/reference/README.md +1 -1
- package/skills/e-code-review/SKILL.md +26 -5
- package/skills/e-code-review/reference/effort-evaluation.md +35 -0
- package/skills/e-code-review/reference/medium.md +15 -4
- package/skills/e-code-review/scripts/config/e_code_review_effort_constants/__init__.py +41 -0
- package/skills/e-code-review/scripts/config/e_code_review_effort_constants/effort_constants.py +40 -0
- package/skills/e-code-review/scripts/e_code_review_scripts_constants/finding_pipeline_constants.py +49 -0
- package/skills/e-code-review/scripts/effort_defaults_evidence.json +186 -0
- package/skills/e-code-review/scripts/effort_evaluation.py +362 -0
- package/skills/e-code-review/scripts/finding_pipeline.py +140 -0
- package/skills/e-code-review/scripts/fixtures/demanding.json +26 -0
- package/skills/e-code-review/scripts/fixtures/easy.json +14 -0
- package/skills/e-code-review/scripts/fixtures/medium.json +20 -0
- package/skills/e-code-review/scripts/grok_code_review.py +16 -7
- package/skills/e-code-review/scripts/test_effort_evaluation.py +180 -0
- package/skills/e-code-review/scripts/test_finding_pipeline.py +197 -0
- package/skills/e-code-review/scripts/test_grok_code_review.py +77 -0
- package/skills/plan-to-pr/scripts/create_packet.py +4 -4
- package/skills/plan-to-pr/scripts/load_skill_constants.py +41 -0
- package/skills/plan-to-pr/scripts/validate_packet.py +4 -4
- package/skills/plan-to-pr/scripts/validate_protocol.py +4 -1
- package/skills/plan-to-pr/scripts/validate_run.py +4 -1
- package/skills/pr-converge/scripts/check_convergence.py +21 -19
- package/skills/pr-converge/scripts/check_convergence_availability.py +50 -7
- package/skills/pr-converge/scripts/conftest.py +35 -0
- package/skills/pr-converge/scripts/test_check_convergence_availability.py +65 -0
- package/skills/pr-converge/scripts/test_check_convergence_codex.py +11 -1
- package/skills/pr-converge/scripts/test_check_convergence_contract.py +9 -2
- package/skills/pr-loop-cloud-transport/SKILL.md +1 -1
- package/skills/rebase/SKILL.md +15 -3
- package/skills/reviewer-gates/SKILL.md +2 -2
- package/skills/show/SKILL.md +51 -0
- package/skills/show/references/accessibility.md +7 -0
- package/skills/show/references/art.md +3 -0
- package/skills/show/references/charts.md +3 -0
- package/skills/show/references/core-design.md +14 -0
- package/skills/show/references/erds.md +3 -0
- package/skills/show/references/flowcharts.md +3 -0
- package/skills/show/references/host-and-html.md +3 -0
- package/skills/show/references/illustrative-diagrams.md +10 -0
- package/skills/show/references/interaction.md +3 -0
- package/skills/show/references/mockups.md +3 -0
- package/skills/show/references/quality-gates.md +7 -0
- package/skills/show/references/structural-diagrams.md +3 -0
- package/skills/show/references/subject-inventory.md +21 -0
- package/skills/show/references/svg-contract.md +22 -0
- package/skills/show/routing.yaml +30 -0
- package/skills/show/samples/pr1262-v2.svg +222 -0
- package/skills/show/scripts/README.md +6 -0
- package/skills/show/scripts/validate-artifact.py +91 -0
- package/skills/show/scripts/validate-package.py +18 -0
- package/skills/show/templates/html-widget.html +4 -0
- package/skills/show/templates/svg-base.svg +19 -0
- package/skills/show/tests/fixtures/css-var.svg +6 -0
- package/skills/show/tests/fixtures/dead-ref.svg +7 -0
- package/skills/show/tests/fixtures/filled-glyph.svg +8 -0
- package/skills/show/tests/fixtures/inherited-fill.svg +18 -0
- package/skills/show/tests/fixtures/invalid.svg +1 -0
- package/skills/show/tests/fixtures/large-canvas.svg +21 -0
- package/skills/show/tests/fixtures/unfilled-connector.svg +15 -0
- package/skills/show/tests/fixtures/valid.html +1 -0
- package/skills/show/tests/test_validate-artifact.py +74 -0
- package/skills/show/tests/test_validators.py +59 -0
- package/skills/show/workflows/create-visual.md +13 -0
- package/skills/show/workflows/review-visual.md +20 -0
- package/skills/split-pr/SKILL.md +85 -0
- package/skills/split-pr/reference/path-layers.md +16 -0
- package/skills/split-pr/reference/proposal-format.md +15 -0
- package/skills/split-pr/reference/split-further-loop.md +10 -0
- package/skills/split-pr/reference/splitting-principles.md +26 -0
- package/skills/split-pr/scripts/analyze_pr.py +279 -0
- package/skills/split-pr/scripts/categorize_files.py +106 -0
- package/skills/split-pr/scripts/config/__init__.py +1 -0
- package/skills/split-pr/scripts/config/dependency_constants.py +14 -0
- package/skills/split-pr/scripts/config/git_operations_constants.py +36 -0
- package/skills/split-pr/scripts/config/packing_constants.py +61 -0
- package/skills/split-pr/scripts/config/plan_constants.py +49 -0
- package/skills/split-pr/scripts/config/split_pr_constants.py +110 -0
- package/skills/split-pr/scripts/execute_split_slices.py +82 -0
- package/skills/split-pr/scripts/pack_files_into_slices.py +212 -0
- package/skills/split-pr/scripts/split_pr_dependency_graph.py +70 -0
- package/skills/split-pr/scripts/split_pr_git_operations.py +184 -0
- package/skills/split-pr/scripts/split_pr_layer_order.py +58 -0
- package/skills/split-pr/scripts/split_pr_paginate.py +119 -0
- package/skills/split-pr/scripts/split_pr_process_runner.py +52 -0
- package/skills/split-pr/scripts/split_pr_script_types.py +126 -0
- package/skills/split-pr/scripts/split_pr_title.py +41 -0
- package/skills/split-pr/scripts/test_analyze_pr.py +228 -0
- package/skills/split-pr/scripts/test_categorize_files.py +55 -0
- package/skills/split-pr/scripts/test_categorize_files_packing.py +59 -0
- package/skills/split-pr/scripts/test_execute_split_slices.py +99 -0
- package/skills/split-pr/scripts/test_split_pr_dependency_graph.py +47 -0
- package/skills/split-pr/scripts/test_split_pr_git_operations.py +125 -0
- package/skills/split-pr/scripts/test_split_pr_layer_order.py +36 -0
- package/skills/split-pr/scripts/test_split_pr_paginate.py +65 -0
- package/skills/split-pr/scripts/test_split_pr_script_types.py +73 -0
- package/skills/split-pr/scripts/test_split_pr_title.py +28 -0
- package/skills/split-pr/scripts/test_verify_dependency_graph.py +46 -0
- package/skills/split-pr/scripts/test_verify_plan.py +56 -0
- package/skills/split-pr/scripts/test_verify_plan_contract.py +50 -0
- package/skills/split-pr/scripts/test_verify_plan_path_normalization.py +45 -0
- package/skills/split-pr/scripts/verify_dependency_graph.py +111 -0
- package/skills/split-pr/scripts/verify_plan.py +139 -0
- package/system-prompts/software-engineer.xml +11 -2
- package/commands/initialize.md +0 -90
- package/commands/stubcheck.md +0 -88
- package/output-styles/caveman-agent.md +0 -37
|
@@ -45,6 +45,8 @@ from pr_loop_shared_constants.copilot_quota_constants import (
|
|
|
45
45
|
)
|
|
46
46
|
from pr_loop_shared_constants.reviews_disabled_constants import (
|
|
47
47
|
CLAUDE_REVIEWS_DISABLED_BUGBOT_TOKEN,
|
|
48
|
+
CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN,
|
|
49
|
+
CLAUDE_REVIEWS_DISABLED_CODEX_TOKEN,
|
|
48
50
|
CLAUDE_REVIEWS_DISABLED_COPILOT_TOKEN,
|
|
49
51
|
CLAUDE_REVIEWS_DISABLED_ENV_VAR_NAME,
|
|
50
52
|
CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR,
|
|
@@ -120,8 +122,15 @@ def _log_disk_settings_fallback_once() -> None:
|
|
|
120
122
|
)
|
|
121
123
|
|
|
122
124
|
|
|
125
|
+
@functools.lru_cache(maxsize=1)
|
|
123
126
|
def _resolve_reviews_settings() -> _ReviewsSettings:
|
|
124
|
-
"""Return disabled and enabled tokens from disk, or env when disk is unreadable.
|
|
127
|
+
"""Return disabled and enabled tokens from disk, or env when disk is unreadable.
|
|
128
|
+
|
|
129
|
+
Cached for the process. Four reviewer gates ask for these tokens in one
|
|
130
|
+
run, and settings cannot change under a running check, so the disk read
|
|
131
|
+
and JSON parse happen once. A test that rebinds the settings path calls
|
|
132
|
+
``_resolve_reviews_settings.cache_clear()`` first.
|
|
133
|
+
"""
|
|
125
134
|
all_disk_env_entries = _try_read_disk_env_block()
|
|
126
135
|
if all_disk_env_entries is not None:
|
|
127
136
|
return _ReviewsSettings(
|
|
@@ -147,18 +156,52 @@ def _is_copilot_disabled_via_resolved_settings() -> bool:
|
|
|
147
156
|
)
|
|
148
157
|
|
|
149
158
|
|
|
159
|
+
def _is_off_by_default_reviewer_disabled(reviewer_token: str) -> bool:
|
|
160
|
+
"""Return True when the resolved settings leave an opt-in reviewer off.
|
|
161
|
+
|
|
162
|
+
::
|
|
163
|
+
|
|
164
|
+
enabled names the token, disabled empty -> False (gate runs)
|
|
165
|
+
neither list names the token -> True (off by default)
|
|
166
|
+
both lists name the token -> True (opt-out wins)
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
reviewer_token: The lowercase reviewer token to look up in both lists.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
True when the reviewer stays off for this run.
|
|
173
|
+
"""
|
|
174
|
+
reviews_settings = _resolve_reviews_settings()
|
|
175
|
+
is_opted_out = reviewer_token in reviews_settings.disabled_tokens
|
|
176
|
+
is_opted_in = reviewer_token in reviews_settings.enabled_tokens
|
|
177
|
+
return is_opted_out or not is_opted_in
|
|
178
|
+
|
|
179
|
+
|
|
150
180
|
def _is_bugbot_disabled_via_resolved_settings() -> bool:
|
|
151
181
|
"""Return True when the resolved settings disable the bugbot reviewer.
|
|
152
182
|
|
|
153
183
|
Bugbot is off by default. It is disabled when the disabled list names it, or
|
|
154
184
|
when the enabled list does not name it.
|
|
155
185
|
"""
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
186
|
+
return _is_off_by_default_reviewer_disabled(CLAUDE_REVIEWS_DISABLED_BUGBOT_TOKEN)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _is_bugteam_disabled_via_resolved_settings() -> bool:
|
|
190
|
+
"""Return True when the resolved settings disable the bug-audit family.
|
|
191
|
+
|
|
192
|
+
Bugteam is off by default. It is disabled when the disabled list names it,
|
|
193
|
+
or when the enabled list does not name it.
|
|
194
|
+
"""
|
|
195
|
+
return _is_off_by_default_reviewer_disabled(CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _is_codex_disabled_via_resolved_settings() -> bool:
|
|
199
|
+
"""Return True when the resolved settings disable the Codex reviewer.
|
|
200
|
+
|
|
201
|
+
Codex is off by default. It is disabled when the disabled list names it, or
|
|
202
|
+
when the enabled list does not name it.
|
|
203
|
+
"""
|
|
204
|
+
return _is_off_by_default_reviewer_disabled(CLAUDE_REVIEWS_DISABLED_CODEX_TOKEN)
|
|
162
205
|
|
|
163
206
|
|
|
164
207
|
def _unavailable_note(reviewer_token: str, message: str) -> str:
|
|
@@ -3,6 +3,41 @@
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
6
8
|
_scripts_directory = Path(__file__).resolve().parent
|
|
7
9
|
if str(_scripts_directory) not in sys.path:
|
|
8
10
|
sys.path.insert(0, str(_scripts_directory))
|
|
11
|
+
|
|
12
|
+
import check_convergence_availability # noqa: E402
|
|
13
|
+
from pr_loop_shared_constants.reviews_disabled_constants import ( # noqa: E402
|
|
14
|
+
CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN,
|
|
15
|
+
CLAUDE_REVIEWS_DISABLED_CODEX_TOKEN,
|
|
16
|
+
CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR,
|
|
17
|
+
CLAUDE_REVIEWS_ENABLED_ENV_VAR_NAME,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
_MISSING_SETTINGS_PATH = Path("settings-absent-in-tests.json")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.fixture(autouse=True)
|
|
24
|
+
def opt_gated_reviewers_in(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
25
|
+
"""Point settings at an absent file and opt bugteam and codex in.
|
|
26
|
+
|
|
27
|
+
Bugteam and codex are off by default, and the resolver reads the real
|
|
28
|
+
``~/.claude/settings.json`` first. Both together would decide these cases
|
|
29
|
+
from whatever the host machine has on disk. Aiming the resolver at an
|
|
30
|
+
absent path restores the env fallback, and the opt-in lets each case reach
|
|
31
|
+
the gate it was written for. A case that tests the lists themselves
|
|
32
|
+
overrides this from its own body.
|
|
33
|
+
"""
|
|
34
|
+
check_convergence_availability._resolve_reviews_settings.cache_clear()
|
|
35
|
+
monkeypatch.setattr(
|
|
36
|
+
check_convergence_availability,
|
|
37
|
+
"get_claude_user_settings_path",
|
|
38
|
+
lambda: _MISSING_SETTINGS_PATH,
|
|
39
|
+
)
|
|
40
|
+
all_opted_in_tokens = CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR.join(
|
|
41
|
+
(CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN, CLAUDE_REVIEWS_DISABLED_CODEX_TOKEN)
|
|
42
|
+
)
|
|
43
|
+
monkeypatch.setenv(CLAUDE_REVIEWS_ENABLED_ENV_VAR_NAME, all_opted_in_tokens)
|
|
@@ -86,6 +86,7 @@ def _write_settings(
|
|
|
86
86
|
def _reset_probe_cache_and_env(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
87
87
|
availability._probe_copilot_quota.cache_clear()
|
|
88
88
|
availability._log_disk_settings_fallback_once.cache_clear()
|
|
89
|
+
availability._resolve_reviews_settings.cache_clear()
|
|
89
90
|
monkeypatch.delenv("CLAUDE_REVIEWS_DISABLED", raising=False)
|
|
90
91
|
monkeypatch.delenv("CLAUDE_REVIEWS_ENABLED", raising=False)
|
|
91
92
|
monkeypatch.setattr(
|
|
@@ -324,3 +325,67 @@ def should_probe_copilot_when_neither_flag_env_nor_disk_disable_it(
|
|
|
324
325
|
waiver = availability._resolve_copilot_waiver(False)
|
|
325
326
|
assert waiver.is_waived is True
|
|
326
327
|
assert waiver.bypass_note == "copilot unavailable: quota exhausted"
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def should_disable_bugteam_when_neither_disk_list_names_it(
|
|
331
|
+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
332
|
+
) -> None:
|
|
333
|
+
settings_path = _write_settings(
|
|
334
|
+
tmp_path, reviews_disabled_value="", reviews_enabled_value=""
|
|
335
|
+
)
|
|
336
|
+
monkeypatch.setattr(
|
|
337
|
+
availability, "get_claude_user_settings_path", lambda: settings_path
|
|
338
|
+
)
|
|
339
|
+
assert availability._is_bugteam_disabled_via_resolved_settings() is True
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def should_enable_bugteam_when_disk_enables_it_even_if_env_omits_opt_in(
|
|
343
|
+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
344
|
+
) -> None:
|
|
345
|
+
monkeypatch.delenv("CLAUDE_REVIEWS_ENABLED", raising=False)
|
|
346
|
+
settings_path = _write_settings(
|
|
347
|
+
tmp_path, reviews_disabled_value="", reviews_enabled_value="bugteam"
|
|
348
|
+
)
|
|
349
|
+
monkeypatch.setattr(
|
|
350
|
+
availability, "get_claude_user_settings_path", lambda: settings_path
|
|
351
|
+
)
|
|
352
|
+
assert availability._is_bugteam_disabled_via_resolved_settings() is False
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def should_disable_bugteam_when_disk_disables_and_enables_it(
|
|
356
|
+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
357
|
+
) -> None:
|
|
358
|
+
settings_path = _write_settings(
|
|
359
|
+
tmp_path, reviews_disabled_value="bugteam", reviews_enabled_value="bugteam"
|
|
360
|
+
)
|
|
361
|
+
monkeypatch.setattr(
|
|
362
|
+
availability, "get_claude_user_settings_path", lambda: settings_path
|
|
363
|
+
)
|
|
364
|
+
assert availability._is_bugteam_disabled_via_resolved_settings() is True
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def should_disable_codex_when_neither_disk_list_names_it(
|
|
368
|
+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
369
|
+
) -> None:
|
|
370
|
+
settings_path = _write_settings(
|
|
371
|
+
tmp_path, reviews_disabled_value="", reviews_enabled_value=""
|
|
372
|
+
)
|
|
373
|
+
monkeypatch.setattr(
|
|
374
|
+
availability, "get_claude_user_settings_path", lambda: settings_path
|
|
375
|
+
)
|
|
376
|
+
assert availability._is_codex_disabled_via_resolved_settings() is True
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def should_enable_codex_when_disk_enables_it_even_if_env_omits_opt_in(
|
|
380
|
+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
381
|
+
) -> None:
|
|
382
|
+
monkeypatch.delenv("CLAUDE_REVIEWS_ENABLED", raising=False)
|
|
383
|
+
settings_path = _write_settings(
|
|
384
|
+
tmp_path, reviews_disabled_value="", reviews_enabled_value="codex"
|
|
385
|
+
)
|
|
386
|
+
monkeypatch.setattr(
|
|
387
|
+
availability, "get_claude_user_settings_path", lambda: settings_path
|
|
388
|
+
)
|
|
389
|
+
assert availability._is_codex_disabled_via_resolved_settings() is False
|
|
390
|
+
|
|
391
|
+
|
|
@@ -370,7 +370,7 @@ def should_resolve_codex_down_true_when_env_disables_codex(
|
|
|
370
370
|
) is True
|
|
371
371
|
|
|
372
372
|
|
|
373
|
-
def
|
|
373
|
+
def should_resolve_codex_down_false_when_flag_unset_and_codex_opted_in(
|
|
374
374
|
monkeypatch: pytest.MonkeyPatch,
|
|
375
375
|
) -> None:
|
|
376
376
|
monkeypatch.delenv("CLAUDE_REVIEWS_DISABLED", raising=False)
|
|
@@ -380,6 +380,16 @@ def should_resolve_codex_down_false_when_flag_unset_and_env_empty(
|
|
|
380
380
|
) is False
|
|
381
381
|
|
|
382
382
|
|
|
383
|
+
def should_resolve_codex_down_true_when_neither_list_names_codex(
|
|
384
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
385
|
+
) -> None:
|
|
386
|
+
monkeypatch.delenv("CLAUDE_REVIEWS_ENABLED", raising=False)
|
|
387
|
+
monkeypatch.delenv("CLAUDE_JOB_DIR", raising=False)
|
|
388
|
+
assert check_convergence._resolve_codex_down(
|
|
389
|
+
False, check_convergence._read_job_state()
|
|
390
|
+
) is True
|
|
391
|
+
|
|
392
|
+
|
|
383
393
|
def should_resolve_codex_down_true_when_job_state_sticky_down(
|
|
384
394
|
tmp_path: Path,
|
|
385
395
|
monkeypatch: pytest.MonkeyPatch,
|
|
@@ -294,14 +294,21 @@ def test_resolve_bugteam_post_blocked_true_when_env_disables_bugteam(
|
|
|
294
294
|
assert check_convergence._resolve_bugteam_post_blocked(False) is True
|
|
295
295
|
|
|
296
296
|
|
|
297
|
-
def
|
|
297
|
+
def test_resolve_bugteam_post_blocked_false_when_flag_unset_and_bugteam_opted_in(
|
|
298
298
|
monkeypatch: pytest.MonkeyPatch,
|
|
299
299
|
) -> None:
|
|
300
300
|
monkeypatch.delenv("CLAUDE_REVIEWS_DISABLED", raising=False)
|
|
301
301
|
assert check_convergence._resolve_bugteam_post_blocked(False) is False
|
|
302
302
|
|
|
303
303
|
|
|
304
|
-
def
|
|
304
|
+
def test_resolve_bugteam_post_blocked_true_when_neither_list_names_bugteam(
|
|
305
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
306
|
+
) -> None:
|
|
307
|
+
monkeypatch.delenv("CLAUDE_REVIEWS_ENABLED", raising=False)
|
|
308
|
+
assert check_convergence._resolve_bugteam_post_blocked(False) is True
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def test_resolve_bugteam_post_blocked_false_when_opted_in_and_env_disables_copilot(
|
|
305
312
|
monkeypatch: pytest.MonkeyPatch,
|
|
306
313
|
) -> None:
|
|
307
314
|
monkeypatch.setenv("CLAUDE_REVIEWS_DISABLED", "copilot")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pr-loop-cloud-transport
|
|
3
|
-
description: Runs any PR-loop skill in a Claude Code session whose gh CLI cannot act on the PR. Use at run start when pr-converge, autoconverge, bugteam,
|
|
3
|
+
description: Runs any PR-loop skill in a Claude Code session whose gh CLI cannot act on the PR. Use at run start when pr-converge, autoconverge, bugteam, clean-room audit, pr-fix-protocol, or copilot-review runs in a cloud session, when `command -v gh` or `gh auth status` fails, or when an MCP tool call fails with InputValidationError.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# PR-loop cloud transport
|
package/skills/rebase/SKILL.md
CHANGED
|
@@ -93,7 +93,9 @@ When in doubt, ask. Both work; the choice affects history shape, not correctness
|
|
|
93
93
|
|
|
94
94
|
## Phase 3 — Verification gates (mandatory before push)
|
|
95
95
|
|
|
96
|
-
`py_compile`, `tsc --noEmit`, `cargo check`, etc. validate **syntax and types**, not **import resolution and runtime correctness**. Run real checks
|
|
96
|
+
`py_compile`, `tsc --noEmit`, `cargo check`, etc. validate **syntax and types**, not **import resolution and runtime correctness**. Run real checks.
|
|
97
|
+
|
|
98
|
+
Before each gate command, state in one line which gate it is and why it applies to this rebase ("post-rebase gate: `pkg_x` carried a conflict resolution, running its suite").
|
|
97
99
|
|
|
98
100
|
8. **Real import check.** For Python:
|
|
99
101
|
|
|
@@ -105,7 +107,16 @@ When in doubt, ask. Both work; the choice affects history shape, not correctness
|
|
|
105
107
|
|
|
106
108
|
9. **Test collection.** `pytest --collect-only -q` on the changed packages catches NameError, AttributeError, and ImportError surfaces beyond plain imports.
|
|
107
109
|
|
|
108
|
-
10. **Targeted test run
|
|
110
|
+
10. **Targeted test run — scoped by content diff.** First check, per candidate package, whether the rebase changed its content at all:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
git diff <pre-rebase-tip> HEAD -- <package>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- **Empty diff:** the package's files are byte-for-byte what the branch already carried before the rebase, and that state was verified pre-rebase. The compile and collect-only gates (steps 8–9) cover the remaining import-level risk; skip the package's full suite.
|
|
117
|
+
- **Non-empty diff, a conflict resolution, or an auto-merged file (step 6) in the package:** run its full suite. Do not push a rebase that dropped or broke test coverage that was passing pre-rebase.
|
|
118
|
+
|
|
119
|
+
Capture the pre-rebase tip SHA before the rebase begins; step 15 pins the force-with-lease to that same SHA.
|
|
109
120
|
|
|
110
121
|
11. **Reference scan for removals/renames.** For every symbol the rebase deleted or renamed (per the commit messages from step 4), scan the post-rebase tree using the same tool-preference order as step 4:
|
|
111
122
|
|
|
@@ -145,6 +156,7 @@ When in doubt, ask. Both work; the choice affects history shape, not correctness
|
|
|
145
156
|
- **Auditing only `git diff --name-only`.** Files unchanged by the rebase can still break if their imports depended on what the rebase removed.
|
|
146
157
|
- **Force-pushing under "the user asked me to fix the conflicts" interpretation.** Force-push is a separate authorization from "fix this." Ask.
|
|
147
158
|
- **Bare `--force` instead of `--force-with-lease=<branch>:<sha>`.** Loses the safety net against concurrent pushes.
|
|
159
|
+
- **Running full suites for packages the rebase left byte-for-byte the same.** The step-10 content diff settles it in seconds; a long suite on unchanged content stalls the session.
|
|
148
160
|
|
|
149
161
|
## Quick decision flowchart
|
|
150
162
|
|
|
@@ -157,7 +169,7 @@ Solo, ≤5 commits ahead? ──► straight rebase
|
|
|
157
169
|
After rebase, BEFORE push:
|
|
158
170
|
python -c "import …" ──► must succeed
|
|
159
171
|
pytest --collect-only ──► must succeed
|
|
160
|
-
|
|
172
|
+
pytest, packages w/ diff ──► must pass
|
|
161
173
|
symbol scan (serena → Grep) ──► no stale references
|
|
162
174
|
|
|
163
175
|
Push:
|
|
@@ -16,7 +16,7 @@ description: >-
|
|
|
16
16
|
- **Skill-capable contexts** (a lead session with the `Skill` tool): `Skill({skill: "reviewer-gates", args: "--skill <caller> <gate> [gate parameters]"})`.
|
|
17
17
|
- **Fallback** (a subagent or teammate without the `Skill` tool): the caller's spawn prompt says "Read `~/.claude/skills/reviewer-gates/SKILL.md` and apply the `<gate>` section with the parameters below."
|
|
18
18
|
|
|
19
|
-
Every invocation carries the caller's identity (`--skill <caller>`, e.g. `pr-converge`, `
|
|
19
|
+
Every invocation carries the caller's identity (`--skill <caller>`, e.g. `pr-converge`, `bugteam`). The refusal line in Gate 1 and every logged decision names the caller, so a multi-skill session's transcript shows which loop each gate served.
|
|
20
20
|
|
|
21
21
|
## Gate 1: Reviewer opt-out (`CLAUDE_REVIEWS_DISABLED`)
|
|
22
22
|
|
|
@@ -24,7 +24,7 @@ The `CLAUDE_REVIEWS_DISABLED` environment variable is a comma-separated token li
|
|
|
24
24
|
|
|
25
25
|
| Token | Disables |
|
|
26
26
|
|---|---|
|
|
27
|
-
| `bugteam` | The whole bug-audit family: `/bugteam`,
|
|
27
|
+
| `bugteam` | The whole bug-audit family: `/bugteam`, `clean-room audit (code-quality-agent)`, and audit dispatch in `/pr-converge` |
|
|
28
28
|
| `bugbot` | Cursor Bugbot triggering and polling |
|
|
29
29
|
| `copilot` | GitHub Copilot review requests and polling |
|
|
30
30
|
| `codex` | Codex reviewer requests and polling |
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: show
|
|
3
|
+
description: Create and review inline visual explanations, diagrams, interactive widgets, mockups, charts, and illustrations. Triggers on "/show", "show me", "draw", "diagram this", "visualize", "map this out", "make it interactive", or a request for a mockup, chart, or illustration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Show
|
|
7
|
+
|
|
8
|
+
Use this skill when a user asks to show, draw, map, visualize, explain visually, or build an interactive visual.
|
|
9
|
+
|
|
10
|
+
## Routes
|
|
11
|
+
|
|
12
|
+
Pick the row whose intent matches the request, then follow `workflows/create-visual.md`.
|
|
13
|
+
|
|
14
|
+
| Intent | Route |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Steps, decisions, lifecycle, transformation | `flowchart` |
|
|
17
|
+
| Architecture, containment, hierarchy | `structural` |
|
|
18
|
+
| Mechanism, intuition, spatial metaphor | `illustrative` |
|
|
19
|
+
| Entity or class relationships | `erd` |
|
|
20
|
+
| Controls that change a visual explanation | `interactive` |
|
|
21
|
+
| UI surface, form, card, dashboard | `mockup` |
|
|
22
|
+
| Quantitative or geographic data | `chart` |
|
|
23
|
+
| Illustration or generative art | `art` |
|
|
24
|
+
|
|
25
|
+
Each route's references and template live in `routing.yaml`; the template sets the output type.
|
|
26
|
+
|
|
27
|
+
## Invariants
|
|
28
|
+
|
|
29
|
+
- Design, palette, and color meaning follow `references/core-design.md`.
|
|
30
|
+
- SVG output follows `references/svg-contract.md`; HTML output follows `references/host-and-html.md`.
|
|
31
|
+
- Prefer multiple focused visuals over one dense canvas, and keep explanatory prose outside the visual.
|
|
32
|
+
- Keep one diagram family per visual.
|
|
33
|
+
- When the visual shows code, a diff, or a plan that lives in a repo, read the real lines and tie every arrow to a `path:line` citation before drawing. When the picture and the source disagree, the picture is wrong.
|
|
34
|
+
- `samples/` holds good examples the user has picked out. Read them on demand to study what works; the rules stay in the references.
|
|
35
|
+
|
|
36
|
+
## Workflows
|
|
37
|
+
|
|
38
|
+
- New visual: `workflows/create-visual.md`
|
|
39
|
+
- Review or repair: `workflows/review-visual.md`
|
|
40
|
+
|
|
41
|
+
## Validation
|
|
42
|
+
|
|
43
|
+
Run from any working directory:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
python <skill-root>/scripts/validate-package.py
|
|
47
|
+
python <skill-root>/scripts/validate-artifact.py <artifact>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The package is complete only when package checks, artifact checks, and rendered inspection all pass.
|
|
51
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Accessibility
|
|
2
|
+
|
|
3
|
+
Interactive controls have accessible names and visible focus. Decorative icons use `aria-hidden="true"`.
|
|
4
|
+
|
|
5
|
+
SVG roots use `role="img"`. Text remains readable in light and dark modes. Color never carries meaning without a label, shape, position, or legend.
|
|
6
|
+
|
|
7
|
+
The hidden summary heading each HTML widget opens with is set in `references/host-and-html.md`; the `<title>` and `<desc>` order each SVG opens with is set in `references/svg-contract.md`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Core design
|
|
2
|
+
|
|
3
|
+
Use flat surfaces, transparent outer containers, sentence case, the 16-at-680 scaled text floor set in `references/svg-contract.md`, and weights 400 or 500. Keep visible prose outside the visual. Use no decorative gradients, glow, blur, noise, or drop shadows. Use no emoji. Keep a visual compact and split it when labels or relationships become hard to read.
|
|
4
|
+
|
|
5
|
+
## Color
|
|
6
|
+
|
|
7
|
+
Color is the default, in the style of `samples/`: pick a palette of three to four named hues (for example a red, a green, an amber) plus neutral grays and near-black text, and use it throughout the visual.
|
|
8
|
+
|
|
9
|
+
- Paint category and state surfaces with light tinted fills of the palette hues (for example `#DFF0E4` under a `#1E8449` stroke), with white or warm-white cards for plain content.
|
|
10
|
+
- Draw strokes and text in strong fixed colors: near-black `#1A1A1A` for primary text, mid-gray for secondary, a palette hue for anything whose color carries meaning.
|
|
11
|
+
- Use each hue for one meaning and keep that meaning consistent across the visual; a short legend explains any pairing the reader cannot work out alone.
|
|
12
|
+
- The palette is fixed rather than host-derived, so every SVG owns its background rect — see `references/svg-contract.md`.
|
|
13
|
+
- Keep contrast strong: text and strokes hold up against the fill behind them.
|
|
14
|
+
- Reserve a monochrome outline style for the rare case the user asks for it.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Illustrative diagrams
|
|
2
|
+
|
|
3
|
+
Draw the mechanism or a useful spatial metaphor.
|
|
4
|
+
|
|
5
|
+
- Draw each idea as a physical object: machine, pipe, valve, stamp, funnel, conveyor, lever, drawer. Reach for an object first, and for a word only when no object carries the idea.
|
|
6
|
+
- Text inside the visual is evidence: exact identifiers, field names, and example values, verbatim, in monospace. Explanatory sentences stay in the surrounding prose.
|
|
7
|
+
- Color carries meaning and holds the same meaning across every panel — for example red for a defect, green for correct flow, amber for the change. One story per panel, panels numbered, read in order.
|
|
8
|
+
- Every route and arrow ends touching its target. Long paths carry motion cues such as chevrons or trails to show direction.
|
|
9
|
+
|
|
10
|
+
Use one functional two-stop gradient only when it is a continuous physical property. Keep physical scene colors consistent and give a dark-mode treatment when needed.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Quality gates
|
|
2
|
+
|
|
3
|
+
Judgment checks a script cannot make. Run them by eye on the rendered result, after `scripts/validate-artifact.py` passes.
|
|
4
|
+
|
|
5
|
+
- The artifact is self-contained and uses an approved external-resource origin when a resource is needed.
|
|
6
|
+
- Rendered output has no clipping, unintended overlap, or unreadable contrast.
|
|
7
|
+
- The visual reads at display scale, not just at full zoom.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Subject inventory
|
|
2
|
+
|
|
3
|
+
List every element of the subject a reader expects to find, then mark each one kept or cut and say why in prose.
|
|
4
|
+
|
|
5
|
+
For a diff or a pull request the list is fixed and needs no judgment:
|
|
6
|
+
|
|
7
|
+
- Files touched
|
|
8
|
+
- Identifiers added and removed
|
|
9
|
+
- Behavior changed
|
|
10
|
+
- Tests added
|
|
11
|
+
- Docs changed
|
|
12
|
+
- Commits
|
|
13
|
+
|
|
14
|
+
Read those six from the repo itself:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git diff --stat <base>..<head>
|
|
18
|
+
git log --oneline <base>..<head>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Every element then sits in a visual or gets named in the surrounding prose. An inventory too large for one canvas becomes an overview visual plus detail visuals.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# SVG contract
|
|
2
|
+
|
|
3
|
+
Put `<title>`, `<desc>`, then `<defs>` first. Every connector has `fill="none"`; arrowheads use the standard marker. Avoid negative coordinates, clipping, crossing labels, and standalone labels outside a region or callout.
|
|
4
|
+
|
|
5
|
+
## Canvas tiers
|
|
6
|
+
|
|
7
|
+
Pick one of two widths:
|
|
8
|
+
|
|
9
|
+
- **Standard** — `viewBox="0 0 680 H"`. Use it for a single small explainer.
|
|
10
|
+
- **Large infographic** — `viewBox="0 0 W H"` with `W` from 1360 to 2000. This is the default for anything with two or more panels or more than about 6 labeled elements.
|
|
11
|
+
|
|
12
|
+
## Text floor
|
|
13
|
+
|
|
14
|
+
The smallest caption sits at `16 × (width / 680)` units, rounded to the nearest whole unit: 16 at 680, 32 at 1360, 41 at 1760. Body text sits above that floor.
|
|
15
|
+
|
|
16
|
+
## Safe area
|
|
17
|
+
|
|
18
|
+
The safe area scales with the canvas the same way: `40 × (width / 680)` units, so 40 at 680 and about 80 at 1360. Keep authored content inside it.
|
|
19
|
+
|
|
20
|
+
## Background
|
|
21
|
+
|
|
22
|
+
Every SVG draws its own opaque warm-white background rect (for example `#F2EFE6` or `#FFFFFF`) as the first shape after `<defs>`, covering the full viewBox. The visual carries a fixed palette (see `references/core-design.md`), so an owned background keeps it legible on light and dark hosts alike.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
workflow: workflows/create-visual.md
|
|
2
|
+
shared_references:
|
|
3
|
+
- references/core-design.md
|
|
4
|
+
- references/accessibility.md
|
|
5
|
+
- references/quality-gates.md
|
|
6
|
+
routes:
|
|
7
|
+
flowchart:
|
|
8
|
+
references: [references/svg-contract.md, references/subject-inventory.md, references/flowcharts.md]
|
|
9
|
+
template: templates/svg-base.svg
|
|
10
|
+
structural:
|
|
11
|
+
references: [references/svg-contract.md, references/subject-inventory.md, references/structural-diagrams.md]
|
|
12
|
+
template: templates/svg-base.svg
|
|
13
|
+
illustrative:
|
|
14
|
+
references: [references/svg-contract.md, references/subject-inventory.md, references/illustrative-diagrams.md]
|
|
15
|
+
template: templates/svg-base.svg
|
|
16
|
+
erd:
|
|
17
|
+
references: [references/host-and-html.md, references/subject-inventory.md, references/erds.md]
|
|
18
|
+
template: templates/html-widget.html
|
|
19
|
+
interactive:
|
|
20
|
+
references: [references/host-and-html.md, references/interaction.md]
|
|
21
|
+
template: templates/html-widget.html
|
|
22
|
+
mockup:
|
|
23
|
+
references: [references/host-and-html.md, references/mockups.md]
|
|
24
|
+
template: templates/html-widget.html
|
|
25
|
+
chart:
|
|
26
|
+
references: [references/host-and-html.md, references/charts.md]
|
|
27
|
+
template: templates/html-widget.html
|
|
28
|
+
art:
|
|
29
|
+
references: [references/art.md]
|
|
30
|
+
template: templates/html-widget.html
|