claude-dev-env 4.3.0 → 7.0.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/.agents/agents/pr-description-writer.md +2 -2
- package/.agents/agents/test_agent_frontmatter.py +2 -2
- package/.agents/agents/test_pr_description_writer_style.py +1 -3
- package/.agents/skills/e-code-review/SKILL.md +12 -12
- package/.agents/skills/e-code-review/preflight-proposal.contract.test.mjs +20 -0
- package/.agents/skills/e-code-review/reference/fix.md +15 -17
- package/.agents/skills/e-code-review/reference/loop.md +35 -39
- package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +2 -1
- package/.agents/skills/e-code-review/reference/preflight-proposal.md +44 -9
- package/.agents/skills/e-code-review/reference/runner-selection.md +13 -14
- package/.agents/skills/issue-tracker/SKILL.md +5 -4
- package/.agents/skills/pull-request/SKILL.md +11 -13
- package/.agents/skills/pull-request/reference/publication-tasks.md +3 -3
- package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +9 -1
- package/.agents/skills/pull-request/scripts/pull_request.py +33 -44
- package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +9 -0
- package/.agents/skills/pull-request/scripts/test_pull_request.py +1 -3
- package/.agents/skills/skill-builder/SKILL.md +3 -196
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
- package/bin/install.agents-home.test.mjs +15 -13
- package/bin/install.mjs +28 -0
- package/bin/install.policy-lint.test.mjs +78 -0
- package/bin/install.prune.test.mjs +59 -20
- package/bin/install.pstack-plugin.test.mjs +114 -0
- package/bin/install.test.mjs +37 -0
- package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
- package/hooks/advisory/pr_done_reminder.py +342 -0
- package/hooks/advisory/test_pr_done_reminder.py +249 -0
- package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
- package/hooks/blocking/code_rules_paired_test.py +22 -15
- package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
- package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
- package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
- package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +68 -133
- package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +18 -18
- package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
- package/hooks/git-hooks/pre_commit.py +52 -11
- package/hooks/git-hooks/test_installed_policy_lint.py +159 -0
- package/hooks/git-hooks/test_native_policy_commit.py +87 -0
- package/hooks/git-hooks/test_pre_commit.py +246 -0
- package/hooks/hooks.json +1 -1
- package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
- package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -43
- package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
- package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
- package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +20 -32
- package/package.json +2 -2
- package/rules/durable-post-artifacts.md +2 -1
- package/rules/git-workflow.md +6 -6
- package/scripts/check.ps1 +0 -1
- package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
- package/scripts/ci/installer-lifecycle.test.mjs +26 -0
- package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
- package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
- package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +5 -41
- package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +0 -10
- package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +1 -1
- package/scripts/policy_lint/adapter_detectors.py +13 -6
- package/scripts/policy_lint/adapters.py +7 -4
- package/scripts/policy_lint/config/constants.py +5 -0
- package/scripts/policy_lint/engine.py +48 -4
- package/scripts/policy_lint/model.py +1 -0
- package/scripts/policy_lint/registry.py +1 -1
- package/scripts/policy_lint/selection.py +2 -1
- package/scripts/policy_lint/selection_git.py +2 -0
- package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
- package/scripts/shared_tree_paths.py +32 -3
- package/scripts/test_shared_tree_paths.py +33 -0
- package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
- package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
- package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
- package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
- package/scripts/tests/test_policy_lint_selection.py +25 -2
- package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
- package/scripts/tests/test_rules.py +3 -7
- package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
- package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
- package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
- package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
- package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
- package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
- package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
- package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
- package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
- package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
- package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
- package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
- package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
- package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
- package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
- package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
- package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
- package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
- package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
- package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
- package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
- package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
- package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
- package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
- package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
- package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
- package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
- package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
- package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
- package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
- package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
- package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
- package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
- package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
- package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
- package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
- package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
- package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
- package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
- package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
- package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/SKILL.md +0 -431
- package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
- package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
- package/.agents/skills/autoconverge/reference/convergence.md +0 -219
- package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
- package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
- package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
- package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
- package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
- package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
- package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
- package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
- package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
- package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
- package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
- package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
- package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
- package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
- package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
- package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
- package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
- package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
- package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
- package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
- package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
- package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
- package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
- package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
- package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
- package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
- package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
- package/.agents/skills/hitl/SKILL.md +0 -45
- package/.agents/skills/pr-cleanup/SKILL.md +0 -140
- package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
- package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
- package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
- package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
- package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
- package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
- package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
- package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
- package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
- package/.agents/skills/pr-refinement/SKILL.md +0 -31
- package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
- package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
- package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
- package/.agents/skills/pr-small-cl/SKILL.md +0 -52
- package/.agents/skills/pr-title-description/SKILL.md +0 -96
- package/.agents/skills/prototype/SKILL.md +0 -85
- package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
- package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
- package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
- package/.agents/skills/prototype/scripts/conftest.py +0 -15
- package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
- package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
- package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
- package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
- package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
- package/.agents/skills/prototype/workflows/promotion.md +0 -25
- package/.agents/skills/prototype/workflows/sandbox.md +0 -35
- package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
- package/.agents/skills/rebase/AGENTS.md +0 -1
- package/.agents/skills/rebase/SKILL.md +0 -178
- package/.agents/skills/review-router/SKILL.md +0 -51
- package/.agents/skills/review-router/reference/route-policy.json +0 -7
- package/.agents/skills/review-router/reference/task-seeds.md +0 -1
- package/.agents/skills/review-router/scripts/conftest.py +0 -4
- package/.agents/skills/review-router/scripts/review_router.py +0 -50
- package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
- package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
- package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
- package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
- package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
- package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
- package/.agents/skills/review-tier/SKILL.md +0 -56
- package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
- package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
- package/.agents/skills/review-tier/scripts/conftest.py +0 -4
- package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
- package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
- package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
- package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
- package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
- package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
- package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
- package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
- package/.agents/skills/session-log/AGENTS.md +0 -1
- package/.agents/skills/session-log/SKILL.md +0 -170
- package/.agents/skills/session-log/templates/frontmatter.md +0 -40
- package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
- package/.agents/skills/session-tidy/AGENTS.md +0 -1
- package/.agents/skills/session-tidy/SKILL.md +0 -191
- package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
- package/.agents/skills/skill-builder/references/description-field.md +0 -111
- package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
- package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
- package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
- package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
- package/.agents/skills/skill-builder/references/skill-types.md +0 -232
- package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
- package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
- package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
- package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
- package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
- package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
- package/.agents/skills/update/.claude/CLAUDE.md +0 -1
- package/.agents/skills/update/AGENTS.md +0 -1
- package/.agents/skills/update/SKILL.md +0 -190
- package/_shared/pr-loop/AGENTS.md +0 -1
- package/_shared/pr-loop/CLAUDE.md +0 -1
- package/_shared/pr-loop/audit-contract.md +0 -183
- package/_shared/pr-loop/audit-reply-template.md +0 -151
- package/_shared/pr-loop/code-rules-gate.md +0 -65
- package/_shared/pr-loop/fix-protocol.md +0 -60
- package/_shared/pr-loop/gh-payloads.md +0 -75
- package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
- package/_shared/pr-loop/precatch-rubric.md +0 -66
- package/_shared/pr-loop/preflight-proposal.md +0 -56
- package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
- package/_shared/pr-loop/state-schema.md +0 -45
- package/_shared/pr-loop/worker-spawn.md +0 -189
- /package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +0 -0
|
@@ -6,11 +6,11 @@ reason when the task is conditional. This file is a task seed catalog, not a
|
|
|
6
6
|
markdown progress board.
|
|
7
7
|
|
|
8
8
|
1. Resolve one repository, action, and selected author. For create, resolve the source branch, base, and head. For other actions, resolve one existing pull request target. Create actions publish drafts.
|
|
9
|
-
2. Invoke the required `pr-description-writer` for create or full body rewrite, then record its title and body file.
|
|
9
|
+
2. Invoke the required `pr-description-writer` for create or full body rewrite, then record its title and body file. Mark `N/A` for comment or review bodies that do not rewrite the pull request description.
|
|
10
10
|
3. Validate every title, body, artifact, and local path input. Reject inline body input.
|
|
11
|
-
4.
|
|
11
|
+
4. Resolve the active managed root and run `<managed-root>/scripts/durable_post_lint.py` for the matching action. Record exit code `0` before credential lookup or network work.
|
|
12
12
|
5. Run `privacy-hygiene` before the GitHub post and record its clean result.
|
|
13
|
-
6. Upload binary evidence through `scripts/gh_artifact_upload.py`, replace local references with permanent URLs, and rerun the
|
|
13
|
+
6. Upload binary evidence through `scripts/gh_artifact_upload.py`, replace local references with permanent URLs, and rerun the body linter. Mark `N/A` when no binary evidence exists.
|
|
14
14
|
7. Resolve the selected author in the child process environment and prove that the parent environment and global `gh` account remain unchanged.
|
|
15
15
|
8. Run `.agents/skills/pull-request/scripts/pull_request.py` for exactly one action: `create`, `edit`, `comment`, or `review`.
|
|
16
16
|
9. When the user selects a legacy state file, run `recover_legacy_author.py <exact-state-file> --confirm-inactive` for exactly that record. Preserve every other record and delete the selected record only after successful restore. Mark `N/A` otherwise.
|
|
@@ -29,13 +29,21 @@ ALL_LINTER_ACTIONS_BY_COMMAND: dict[str, str] = {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
SELECTED_ACCOUNT_ENVIRONMENT_KEY = "GITHUB_DEFAULT_ACCOUNT"
|
|
32
|
+
CONFIG_DIR_OVERRIDE_ENVIRONMENT_KEY = "CLAUDE_CONFIG_DIR"
|
|
33
|
+
DEFAULT_MANAGED_ROOT_DIRECTORY_NAME = ".claude"
|
|
34
|
+
ALL_DURABLE_POST_LINTER_RELATIVE_PATH_PARTS = ("scripts", "durable_post_lint.py")
|
|
35
|
+
GITHUB_TOKEN_ENVIRONMENT_KEY = "GITHUB" + "_TOKEN"
|
|
36
|
+
GH_TOKEN_ENVIRONMENT_KEY = "GH" + "_TOKEN"
|
|
37
|
+
ALL_GITHUB_AUTHORIZATION_ENVIRONMENT_KEYS = (
|
|
38
|
+
GITHUB_TOKEN_ENVIRONMENT_KEY,
|
|
39
|
+
GH_TOKEN_ENVIRONMENT_KEY,
|
|
40
|
+
)
|
|
32
41
|
|
|
33
42
|
ACCOUNT_LOOKUP_FAILED_MESSAGE = "error: GitHub account lookup failed\n"
|
|
34
43
|
ACCOUNT_LOOKUP_EMPTY_MESSAGE = "error: GitHub account lookup returned no value\n"
|
|
35
44
|
ACTION_FAILED_MESSAGE = "error: GitHub action failed\n"
|
|
36
45
|
ACCOUNT_LOOKUP_FAILURE_EXIT_CODE = 1
|
|
37
46
|
PACKAGE_ROOT_PARENT_INDEX = 4
|
|
38
|
-
SKILLS_DIRECTORY_PARENT_INDEX = 2
|
|
39
47
|
|
|
40
48
|
ALL_GH_AUTH_SWITCH_COMMAND_HEAD: tuple[str, ...] = (
|
|
41
49
|
"gh",
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
|
-
import importlib
|
|
7
6
|
import os
|
|
8
7
|
import subprocess
|
|
9
8
|
import sys
|
|
@@ -19,12 +18,17 @@ from github_pr_command_constants.config.constants import (
|
|
|
19
18
|
ACTION_EDIT,
|
|
20
19
|
ACTION_FAILED_MESSAGE,
|
|
21
20
|
ACTION_REVIEW,
|
|
21
|
+
ALL_DURABLE_POST_LINTER_RELATIVE_PATH_PARTS,
|
|
22
|
+
ALL_GITHUB_AUTHORIZATION_ENVIRONMENT_KEYS,
|
|
22
23
|
ALL_LINTER_ACTIONS_BY_COMMAND,
|
|
23
24
|
ALL_REVIEW_FLAGS_BY_EVENT,
|
|
25
|
+
CONFIG_DIR_OVERRIDE_ENVIRONMENT_KEY,
|
|
26
|
+
DEFAULT_MANAGED_ROOT_DIRECTORY_NAME,
|
|
27
|
+
GH_TOKEN_ENVIRONMENT_KEY,
|
|
28
|
+
GITHUB_TOKEN_ENVIRONMENT_KEY,
|
|
24
29
|
PACKAGE_ROOT_PARENT_INDEX,
|
|
25
30
|
REVIEW_EVENT_COMMENT,
|
|
26
31
|
SELECTED_ACCOUNT_ENVIRONMENT_KEY,
|
|
27
|
-
SKILLS_DIRECTORY_PARENT_INDEX,
|
|
28
32
|
)
|
|
29
33
|
|
|
30
34
|
CommandRunner = Callable[..., subprocess.CompletedProcess[str]]
|
|
@@ -60,17 +64,33 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
60
64
|
return parser
|
|
61
65
|
|
|
62
66
|
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/
|
|
67
|
+
def _configured_managed_root(all_environment: Mapping[str, str]) -> Path:
|
|
68
|
+
configured_root_text = all_environment.get(CONFIG_DIR_OVERRIDE_ENVIRONMENT_KEY, "").strip()
|
|
69
|
+
if not configured_root_text:
|
|
70
|
+
return Path.home() / DEFAULT_MANAGED_ROOT_DIRECTORY_NAME
|
|
71
|
+
configured_root = Path(configured_root_text).expanduser()
|
|
72
|
+
if configured_root.is_absolute():
|
|
73
|
+
return configured_root
|
|
74
|
+
return Path.home() / configured_root
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _linter_path(all_environment: Mapping[str, str]) -> Path:
|
|
78
|
+
source_candidate = Path(__file__).resolve().parents[PACKAGE_ROOT_PARENT_INDEX].joinpath(
|
|
79
|
+
*ALL_DURABLE_POST_LINTER_RELATIVE_PATH_PARTS
|
|
80
|
+
)
|
|
81
|
+
if source_candidate.is_file():
|
|
82
|
+
return source_candidate
|
|
83
|
+
return _configured_managed_root(all_environment).joinpath(
|
|
84
|
+
*ALL_DURABLE_POST_LINTER_RELATIVE_PATH_PARTS
|
|
67
85
|
)
|
|
68
86
|
|
|
69
87
|
|
|
70
|
-
def _linter_arguments(
|
|
88
|
+
def _linter_arguments(
|
|
89
|
+
arguments: argparse.Namespace, all_environment: Mapping[str, str]
|
|
90
|
+
) -> list[str]:
|
|
71
91
|
all_arguments = [
|
|
72
92
|
sys.executable,
|
|
73
|
-
str(_linter_path()),
|
|
93
|
+
str(_linter_path(all_environment)),
|
|
74
94
|
"--action",
|
|
75
95
|
ALL_LINTER_ACTIONS_BY_COMMAND[arguments.action],
|
|
76
96
|
]
|
|
@@ -138,28 +158,9 @@ def _post_arguments(arguments: argparse.Namespace) -> list[str]:
|
|
|
138
158
|
]
|
|
139
159
|
|
|
140
160
|
|
|
141
|
-
def _shared_environment_key_names() -> tuple[str, str, tuple[str, ...]]:
|
|
142
|
-
shared_directory = (
|
|
143
|
-
Path(__file__).resolve().parents[PACKAGE_ROOT_PARENT_INDEX]
|
|
144
|
-
/ "_shared/pr-loop/scripts"
|
|
145
|
-
)
|
|
146
|
-
shared_directory_text = str(shared_directory)
|
|
147
|
-
if shared_directory_text not in sys.path:
|
|
148
|
-
sys.path.insert(0, shared_directory_text)
|
|
149
|
-
constants_module = importlib.import_module(
|
|
150
|
-
"pr_loop_shared_constants.post_audit_thread_constants"
|
|
151
|
-
)
|
|
152
|
-
return (
|
|
153
|
-
constants_module.GITHUB_TOKEN_ENV_VAR_NAME,
|
|
154
|
-
constants_module.GH_TOKEN_ENV_VAR_NAME,
|
|
155
|
-
constants_module.ALL_GH_TOKEN_ENV_VAR_NAMES,
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
|
|
159
161
|
def _lookup_environment(all_environment: Mapping[str, str]) -> dict[str, str]:
|
|
160
162
|
lookup_environment = dict(all_environment)
|
|
161
|
-
|
|
162
|
-
for each_name in all_authorization_names:
|
|
163
|
+
for each_name in ALL_GITHUB_AUTHORIZATION_ENVIRONMENT_KEYS:
|
|
163
164
|
lookup_environment.pop(each_name, None)
|
|
164
165
|
return lookup_environment
|
|
165
166
|
|
|
@@ -203,12 +204,9 @@ def _action_environment(
|
|
|
203
204
|
)
|
|
204
205
|
if account_authorization is None:
|
|
205
206
|
return None
|
|
206
|
-
parent_authorization_name, child_authorization_name, _ = (
|
|
207
|
-
_shared_environment_key_names()
|
|
208
|
-
)
|
|
209
207
|
action_environment = dict(all_environment)
|
|
210
|
-
action_environment.pop(
|
|
211
|
-
action_environment[
|
|
208
|
+
action_environment.pop(GITHUB_TOKEN_ENVIRONMENT_KEY, None)
|
|
209
|
+
action_environment[GH_TOKEN_ENVIRONMENT_KEY] = account_authorization
|
|
212
210
|
return action_environment
|
|
213
211
|
|
|
214
212
|
|
|
@@ -247,19 +245,10 @@ def main(
|
|
|
247
245
|
all_environment: Mapping[str, str],
|
|
248
246
|
command_runner: CommandRunner,
|
|
249
247
|
) -> int:
|
|
250
|
-
"""Run one validated pull request action.
|
|
251
|
-
|
|
252
|
-
Args:
|
|
253
|
-
all_arguments: Command arguments after the script name.
|
|
254
|
-
all_environment: Parent environment copied for child processes.
|
|
255
|
-
command_runner: Process runner used by tests and production.
|
|
256
|
-
|
|
257
|
-
Returns:
|
|
258
|
-
The linter, account lookup, or GitHub action exit status.
|
|
259
|
-
"""
|
|
248
|
+
"""Run one validated pull request action."""
|
|
260
249
|
arguments = _build_parser().parse_args(list(all_arguments))
|
|
261
250
|
completed_lint = command_runner(
|
|
262
|
-
_linter_arguments(arguments), check=False, shell=False
|
|
251
|
+
_linter_arguments(arguments, all_environment), check=False, shell=False
|
|
263
252
|
)
|
|
264
253
|
if completed_lint.returncode != 0:
|
|
265
254
|
return completed_lint.returncode
|
|
@@ -34,6 +34,15 @@ def test_account_boundary_constants_are_safe_and_stable() -> None:
|
|
|
34
34
|
assert constants.ACCOUNT_LOOKUP_EMPTY_MESSAGE.endswith("returned no value\n")
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
def test_durable_post_linter_location_uses_managed_root() -> None:
|
|
38
|
+
assert constants.CONFIG_DIR_OVERRIDE_ENVIRONMENT_KEY == "CLAUDE_CONFIG_DIR"
|
|
39
|
+
assert constants.DEFAULT_MANAGED_ROOT_DIRECTORY_NAME == ".claude"
|
|
40
|
+
assert constants.ALL_DURABLE_POST_LINTER_RELATIVE_PATH_PARTS == (
|
|
41
|
+
"scripts",
|
|
42
|
+
"durable_post_lint.py",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
37
46
|
def test_legacy_recovery_constants_define_one_record_boundary() -> None:
|
|
38
47
|
assert constants.ALL_GH_AUTH_SWITCH_COMMAND_HEAD == (
|
|
39
48
|
"gh",
|
|
@@ -25,9 +25,7 @@ PR_TITLE = "feat(skills): add guarded pull request publication"
|
|
|
25
25
|
ACCOUNT_A = "JonEcho"
|
|
26
26
|
ACCOUNT_B = "ReviewBot"
|
|
27
27
|
BODY_FILENAME = "pull-request-body.md"
|
|
28
|
-
LINTER_PATH =
|
|
29
|
-
_SCRIPTS_DIRECTORY.parents[1] / "_shared/pr-loop/scripts/durable_post_lint.py"
|
|
30
|
-
)
|
|
28
|
+
LINTER_PATH = _SCRIPTS_DIRECTORY.parents[3] / "scripts/durable_post_lint.py"
|
|
31
29
|
COMMENT_CLI = ["comment", "--repo", REPOSITORY, "--number", PR_NUMBER, "--body-file"]
|
|
32
30
|
ACTION_CASES = [
|
|
33
31
|
(
|
|
@@ -1,202 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skill-builder
|
|
3
3
|
disable-model-invocation: true
|
|
4
|
-
description:
|
|
5
|
-
Skill lifecycle: classify, scaffold, write via the skill-writer-agent, self-audit, compose
|
|
6
|
-
sub-skills, polish description triggers, enforce deterministic scripts. Triggers:
|
|
7
|
-
build a skill, new skill workflow, improve this skill, optimize skill description,
|
|
8
|
-
skill development lifecycle, skill modularity, skill composition, description
|
|
9
|
-
trigger catalog, deterministic skill scripts.
|
|
4
|
+
description: Placeholder for the skill-builder rework to follow pstack philosophy.
|
|
10
5
|
---
|
|
11
6
|
|
|
12
|
-
# Skill
|
|
7
|
+
# Skill builder
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Sources: [Anthropic best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices), [Lessons from Building Claude Code](references/thariq-x-post-skills.json), model skills (bugteam, pr-converge).
|
|
17
|
-
|
|
18
|
-
## Gotchas
|
|
19
|
-
|
|
20
|
-
Highest-signal content. Append a bullet each time a skill build fails in a new way.
|
|
21
|
-
|
|
22
|
-
> "The highest-signal content in any skill is the Gotchas section. These sections should be built up from common failure points that Claude runs into when using your skill."
|
|
23
|
-
|
|
24
|
-
- Story-form `description` burns always-on context and weakens selection — rewrite to capability stem + `Triggers:` list (`description-field.md`).
|
|
25
|
-
- Multi-capability packages fail modularity audit — split or thin orchestrator + named sub-skills (`skill-modularity.md`).
|
|
26
|
-
- Skipping the composition plan before Write reintroduces silent reimplementation of peer skills.
|
|
27
|
-
- Deterministic steps written only as prose (fenced source, giant `rg` lines, multi-step mechanical sequences) fail audit — extract to `scripts/` / `workflow/` / `templates/` / `reference/` (`deterministic-elements.md`).
|
|
28
|
-
- Markdown `- [ ]` checklists as the agent's progress board fail audit when a task tool exists — seed tasks via `TaskCreate` / `TodoWrite` (`deterministic-elements.md`).
|
|
29
|
-
|
|
30
|
-
## When this skill applies
|
|
31
|
-
|
|
32
|
-
Trigger for requests to **build**, **improve**, or **polish** a skill. This skill orchestrates the process — it classifies, scaffolds, gathers context, delegates writing to the `skill-writer-agent` agent, and self-audits the result.
|
|
33
|
-
|
|
34
|
-
For quick skill syntax questions or one-off SKILL.md edits, spawn the `skill-writer-agent` agent directly.
|
|
35
|
-
|
|
36
|
-
**Refusal cases — first match wins:**
|
|
37
|
-
|
|
38
|
-
- **No clear task or domain.** Respond exactly: `What should this skill do? Give me a one-sentence description of the capability.`
|
|
39
|
-
|
|
40
|
-
## The Process
|
|
41
|
-
|
|
42
|
-
Each workflow file provides step-by-step instructions. After routing below, open the corresponding workflow file and follow it.
|
|
43
|
-
|
|
44
|
-
### Routing
|
|
45
|
-
|
|
46
|
-
Assess the user’s intent:
|
|
47
|
-
|
|
48
|
-
**Creating a new skill?**
|
|
49
|
-
Read `${CLAUDE_SKILL_DIR}/workflows/new-skill.md` and follow it.
|
|
50
|
-
|
|
51
|
-
**Improving an existing skill?**
|
|
52
|
-
Read `${CLAUDE_SKILL_DIR}/workflows/improve-skill.md` and follow it.
|
|
53
|
-
|
|
54
|
-
**Final polish only (description optimization, trigger audit)?**
|
|
55
|
-
Read `${CLAUDE_SKILL_DIR}/workflows/polish-skill.md` and follow it.
|
|
56
|
-
|
|
57
|
-
**Ambiguous?** Ask: "Are you creating a new skill, improving an existing one, or doing a final polish pass?"
|
|
58
|
-
|
|
59
|
-
### The Claude A / Claude B pattern
|
|
60
|
-
|
|
61
|
-
You and the user are **Claude A** — the expert who designs and refines the skill. Subagents running the built skill on real tasks are **Claude B** — the agent using the skill to perform actual work.
|
|
62
|
-
|
|
63
|
-
> "Work with one instance of Claude (‘Claude A’) to create a Skill that is used by other instances (‘Claude B’). Claude A helps you design and refine instructions, while Claude B tests them in real tasks."
|
|
64
|
-
|
|
65
|
-
The feedback loop: observe Claude B’s behavior, bring insights back, refine the skill, test again.
|
|
66
|
-
|
|
67
|
-
## Skill type routing
|
|
68
|
-
|
|
69
|
-
> "After cataloging all of our skills, we noticed they cluster into a few recurring categories."
|
|
70
|
-
|
|
71
|
-
Classify into one of 9 types — type sets folder structure. Taxonomy and layouts: [`references/skill-types.md`](references/skill-types.md).
|
|
72
|
-
|
|
73
|
-
## Principles
|
|
74
|
-
|
|
75
|
-
These are non-negotiable. Every skill must satisfy them. Enforce via [`references/self-audit-checklist.md`](references/self-audit-checklist.md).
|
|
76
|
-
|
|
77
|
-
### Concision and defaults
|
|
78
|
-
|
|
79
|
-
> "Default assumption: Claude is already very smart. Only add context Claude doesn’t already have."
|
|
80
|
-
|
|
81
|
-
> "Don’t State the Obvious — focus on information that pushes Claude out of its normal way of thinking."
|
|
82
|
-
|
|
83
|
-
Challenge each sentence: "Does Claude really need this?"
|
|
84
|
-
|
|
85
|
-
### Degree of freedom
|
|
86
|
-
|
|
87
|
-
> "Match the level of specificity to the task’s fragility and variability."
|
|
88
|
-
|
|
89
|
-
High freedom (text guidance) for open fields. Low freedom (exact scripts, no parameters) for narrow bridges with cliffs.
|
|
90
|
-
|
|
91
|
-
> "Avoid Railroading Claude — give Claude the information it needs, but give it the flexibility to adapt."
|
|
92
|
-
|
|
93
|
-
### Progressive disclosure
|
|
94
|
-
|
|
95
|
-
Hub pattern, line caps, one-level references, TOC and path rules: [`references/progressive-disclosure.md`](references/progressive-disclosure.md).
|
|
96
|
-
|
|
97
|
-
### Modularity and composition
|
|
98
|
-
|
|
99
|
-
One skill = one capability. Multi-step work invokes **sub-skills** (peer skills) by name. Prefer compose over reimplement. Full rules: [`references/skill-modularity.md`](references/skill-modularity.md).
|
|
100
|
-
|
|
101
|
-
> "You can just reference other skills by name, and the model will invoke them if they are installed."
|
|
102
|
-
|
|
103
|
-
New-skill Gather records a composition plan before write. Self-audit modularity items are mandatory.
|
|
104
|
-
|
|
105
|
-
### Description field (trigger catalog)
|
|
106
|
-
|
|
107
|
-
The frontmatter `description` is **selection metadata** pre-loaded for every skill. Write a **trigger catalog**, not a story: short capability stem + concrete trigger phrases. No narrative, benefits language, or process dump.
|
|
108
|
-
|
|
109
|
-
Full rules: [`references/description-field.md`](references/description-field.md). Polish workflow Step 1 is the dedicated rewrite pass.
|
|
110
|
-
|
|
111
|
-
> "The description field is not a summary — it’s a description of when to trigger."
|
|
112
|
-
|
|
113
|
-
### Gotchas
|
|
114
|
-
|
|
115
|
-
Mandatory highest-signal section (see Gotchas above). Capture real failure modes; self-audit requires the section present and actionable.
|
|
116
|
-
|
|
117
|
-
### Templates and examples
|
|
118
|
-
|
|
119
|
-
> "Provide templates for output format" and "Examples help Claude understand the desired style and level of detail more clearly than descriptions alone."
|
|
120
|
-
|
|
121
|
-
Use the template pattern for structured outputs. Use the examples pattern (input/output pairs) for style-dependent work.
|
|
122
|
-
|
|
123
|
-
### Workflows and task seeds
|
|
124
|
-
|
|
125
|
-
Multi-step required work is a **task seed list** (plain bullets in a reference file) plus an instruction to register each item on the host task tool (`TaskCreate`, `TodoWrite`, or equivalent). Agents work the task list and mark complete with evidence.
|
|
126
|
-
|
|
127
|
-
Do **not** ship markdown `- [ ]` boards as the completion protocol when a task tool is available. Do **not** say "copy this checklist into your response and check it off."
|
|
128
|
-
|
|
129
|
-
Quality-critical operations still use feedback loops (run validator → fix → repeat). Spec: [`references/deterministic-elements.md`](references/deterministic-elements.md) (Task-tool tracking).
|
|
130
|
-
|
|
131
|
-
### Scripts
|
|
132
|
-
|
|
133
|
-
> "Handle error conditions rather than punting to Claude." "Make clear whether Claude should execute the script or read it as reference."
|
|
134
|
-
|
|
135
|
-
> "One of the most powerful tools you can give Claude is code — letting Claude spend its turns on composition rather than reconstructing boilerplate."
|
|
136
|
-
|
|
137
|
-
### Deterministic elements (mandatory classification)
|
|
138
|
-
|
|
139
|
-
Any skill element that is **deterministic** (same inputs → same outputs; machine-checkable success) ships as code, a fixed artifact, or a **session task seed** — not prose-only steps or markdown checkbox boards. Judgment, routing, and refusals stay in markdown.
|
|
140
|
-
|
|
141
|
-
Full rules, inventory table, task-tool tracking, CODE_RULES bar for skill scripts, and anti-patterns: [`references/deterministic-elements.md`](references/deterministic-elements.md).
|
|
142
|
-
|
|
143
|
-
New-skill Gather records a deterministic-elements inventory before write. Self-audit items register as session tasks and are mandatory on every delivery (pure-judgment skills mark script rows N/A with evidence).
|
|
144
|
-
|
|
145
|
-
### Setup and memory
|
|
146
|
-
|
|
147
|
-
> "Think through the Setup — some skills may need to be set up with context from the user. A good pattern is to store this in a config.json file."
|
|
148
|
-
|
|
149
|
-
> "Data stored in the skill directory may be deleted when you upgrade the skill, so store persistent data in `${CLAUDE_PLUGIN_DATA}`."
|
|
150
|
-
|
|
151
|
-
### Constraints and refusal cases
|
|
152
|
-
|
|
153
|
-
> bugteam pattern — non-negotiables separated from guidance, with design rationale. Explicit "first match wins" refusal conditions.
|
|
154
|
-
|
|
155
|
-
### Anti-patterns
|
|
156
|
-
|
|
157
|
-
> No Windows paths. Don’t offer too many options — provide a default with escape hatch. Avoid time-sensitive claims. Use consistent terminology. No deeply nested references.
|
|
158
|
-
|
|
159
|
-
Also: story-form descriptions; monolith multi-capability skills; silent reimplementation of peer skills; nested folders used as fake sub-skills; deterministic logic only in prose or fenced source; markdown `- [ ]` as the agent's work tracker.
|
|
160
|
-
|
|
161
|
-
## Self-audit
|
|
162
|
-
|
|
163
|
-
After every build, improvement, or polish pass, load `${CLAUDE_SKILL_DIR}/references/self-audit-checklist.md`, **register every bullet as a session task**, and complete each with evidence. Every item must pass before delivery. Fix failures, then re-audit.
|
|
164
|
-
|
|
165
|
-
## Delegation to skill-writer-agent
|
|
166
|
-
|
|
167
|
-
skill-builder orchestrates; the `skill-writer-agent` agent authors. The caller spawns it with `Agent(subagent_type="skill-writer-agent", ...)`. The handoff packet from Step 4 must include:
|
|
168
|
-
|
|
169
|
-
- Skill type and folder structure
|
|
170
|
-
- Gap analysis or observation findings (composition plan + description triggers + deterministic inventory)
|
|
171
|
-
- Degree of freedom assessment
|
|
172
|
-
- Initial gotchas
|
|
173
|
-
- Composition plan: related skills, sub-skills to invoke, split decisions
|
|
174
|
-
- Description trigger catalog: capability stem + trigger phrases (not prose)
|
|
175
|
-
- Deterministic elements inventory: each process step classified; code paths + paired tests
|
|
176
|
-
- Any constraints
|
|
177
|
-
|
|
178
|
-
See `${CLAUDE_SKILL_DIR}/references/delegation-map.md` for exact patterns.
|
|
179
|
-
|
|
180
|
-
## File index
|
|
181
|
-
|
|
182
|
-
| File | Purpose |
|
|
183
|
-
|------|---------|
|
|
184
|
-
| `SKILL.md` | This hub — principles, process, routing, file index |
|
|
185
|
-
| `references/skill-types.md` | 9-type taxonomy with folder structures per type |
|
|
186
|
-
| `references/progressive-disclosure.md` | Folder conventions, hub pattern, hard rules |
|
|
187
|
-
| `references/skill-modularity.md` | Cross-skill modularity, sub-skills, composition plan |
|
|
188
|
-
| `references/description-field.md` | Description as trigger catalog (not story prose) |
|
|
189
|
-
| `references/deterministic-elements.md` | Deterministic steps as code/task seeds; CODE_RULES; no markdown checkbox boards |
|
|
190
|
-
| `references/self-audit-checklist.md` | Post-build audit task seeds (register via TaskCreate / TodoWrite) |
|
|
191
|
-
| `references/delegation-map.md` | Subagent handoff patterns and transcript guidance |
|
|
192
|
-
| `workflows/new-skill.md` | Full lifecycle for new skills (6 steps) |
|
|
193
|
-
| `workflows/improve-skill.md` | Observation-first flow for existing skills (6 steps) |
|
|
194
|
-
| `workflows/polish-skill.md` | Description trigger-catalog audit and final validation (5 steps) |
|
|
195
|
-
| `templates/gap-analysis.md` | Gaps, composition plan, description triggers, deterministic inventory |
|
|
196
|
-
|
|
197
|
-
## Folder map
|
|
198
|
-
|
|
199
|
-
- `SKILL.md` — hub.
|
|
200
|
-
- `references/` — best-practice specifications and the audit checklist.
|
|
201
|
-
- `workflows/` — step-by-step workflows for each lifecycle phase.
|
|
202
|
-
- `templates/` — reusable templates for skill artifacts.
|
|
9
|
+
TODO: Rework to follow pstack philosophy.
|
|
@@ -107,6 +107,12 @@ ALL_GIT_DIFF_CACHED_UNIFIED_ZERO_COMMAND: tuple[str, ...] = (
|
|
|
107
107
|
"--unified=0",
|
|
108
108
|
)
|
|
109
109
|
|
|
110
|
+
ALL_GIT_DIFF_UNIFIED_ZERO_COMMAND: tuple[str, ...] = (
|
|
111
|
+
"git",
|
|
112
|
+
"diff",
|
|
113
|
+
"--unified=0",
|
|
114
|
+
)
|
|
115
|
+
|
|
110
116
|
GIT_DIFF_SUBPROCESS_TIMEOUT_SECONDS: int = 30
|
|
111
117
|
|
|
112
118
|
GIT_NO_MATCH_EXIT_CODE: int = 1
|
|
@@ -32,6 +32,7 @@ from pr_loop_shared_constants.terminology_sweep_constants import (
|
|
|
32
32
|
ALL_COMMON_ENGLISH_COMPOUND_TAIL_WORDS,
|
|
33
33
|
ALL_DIFF_FILE_PATH_STRIP_PREFIXES,
|
|
34
34
|
ALL_GIT_DIFF_CACHED_UNIFIED_ZERO_COMMAND,
|
|
35
|
+
ALL_GIT_DIFF_UNIFIED_ZERO_COMMAND,
|
|
35
36
|
ALL_GIT_GREP_BASE_TREE_COMMAND_PREFIX,
|
|
36
37
|
ALL_PROSE_STOPWORD_TOKENS,
|
|
37
38
|
ALL_STRING_ESCAPE_SEQUENCES,
|
|
@@ -622,21 +623,23 @@ def _identifier_names_on_added_code_lines(diff_text: str) -> frozenset[str]:
|
|
|
622
623
|
|
|
623
624
|
|
|
624
625
|
def _base_tree_names(
|
|
625
|
-
repository_root: Path,
|
|
626
|
+
repository_root: Path,
|
|
627
|
+
all_names: frozenset[str],
|
|
628
|
+
tree_revision: str,
|
|
626
629
|
) -> frozenset[str]:
|
|
627
|
-
"""Return the names the
|
|
630
|
+
"""Return the names the comparison tree already contains.
|
|
628
631
|
|
|
629
|
-
Each name is looked up as a whole word in
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
That is the behaviour the sweep has with no base-tree check at all.
|
|
632
|
+
Each name is looked up as a whole word in ``tree_revision``. A repository
|
|
633
|
+
with no commits yet, or a lookup that git cannot run, reports the name as
|
|
634
|
+
absent, so the sweep treats it as newly introduced.
|
|
633
635
|
|
|
634
636
|
Args:
|
|
635
637
|
repository_root: The repository root the lookups run in.
|
|
636
638
|
all_names: The identifier names to look up.
|
|
639
|
+
tree_revision: The revision whose tree is searched.
|
|
637
640
|
|
|
638
641
|
Returns:
|
|
639
|
-
The subset of names present in
|
|
642
|
+
The subset of names present in that tree.
|
|
640
643
|
"""
|
|
641
644
|
all_present_names: set[str] = set()
|
|
642
645
|
for each_name in sorted(all_names):
|
|
@@ -645,7 +648,7 @@ def _base_tree_names(
|
|
|
645
648
|
[
|
|
646
649
|
*ALL_GIT_GREP_BASE_TREE_COMMAND_PREFIX,
|
|
647
650
|
each_name,
|
|
648
|
-
|
|
651
|
+
tree_revision,
|
|
649
652
|
],
|
|
650
653
|
cwd=str(repository_root),
|
|
651
654
|
capture_output=True,
|
|
@@ -695,14 +698,16 @@ def _raise_for_git_failure(
|
|
|
695
698
|
|
|
696
699
|
|
|
697
700
|
def _strict_base_tree_names(
|
|
698
|
-
repository_root: Path,
|
|
701
|
+
repository_root: Path,
|
|
702
|
+
all_names: frozenset[str],
|
|
703
|
+
tree_revision: str,
|
|
699
704
|
) -> frozenset[str]:
|
|
700
705
|
all_present_names: set[str] = set()
|
|
701
706
|
for each_name in sorted(all_names):
|
|
702
707
|
all_arguments = (
|
|
703
708
|
*ALL_GIT_GREP_BASE_TREE_COMMAND_PREFIX,
|
|
704
709
|
each_name,
|
|
705
|
-
|
|
710
|
+
tree_revision,
|
|
706
711
|
)
|
|
707
712
|
grep_process = _run_strict_git(repository_root, all_arguments)
|
|
708
713
|
if grep_process.returncode == 0:
|
|
@@ -728,14 +733,53 @@ def strict_staged_terminology_findings(repository_root: Path) -> list[str]:
|
|
|
728
733
|
RuntimeError: Git could not read the staged diff or look up an
|
|
729
734
|
identifier in HEAD.
|
|
730
735
|
"""
|
|
731
|
-
|
|
732
|
-
repository_root,
|
|
736
|
+
return _strict_terminology_findings(
|
|
737
|
+
repository_root,
|
|
738
|
+
ALL_GIT_DIFF_CACHED_UNIFIED_ZERO_COMMAND,
|
|
739
|
+
GIT_BASE_TREE_REVISION,
|
|
733
740
|
)
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
def strict_base_terminology_findings(
|
|
744
|
+
repository_root: Path, base_revision: str
|
|
745
|
+
) -> list[str]:
|
|
746
|
+
"""Return near-miss findings for worktree changes against a base revision.
|
|
747
|
+
|
|
748
|
+
Args:
|
|
749
|
+
repository_root: The repository root the worktree diff is read from.
|
|
750
|
+
base_revision: The tree that worktree changes are compared against.
|
|
751
|
+
|
|
752
|
+
Returns:
|
|
753
|
+
One finding string per near-miss term on an added prose line.
|
|
754
|
+
|
|
755
|
+
Raises:
|
|
756
|
+
RuntimeError: Git could not read the committed diff or look up an
|
|
757
|
+
identifier in the comparison tree.
|
|
758
|
+
"""
|
|
759
|
+
all_arguments = (
|
|
760
|
+
*ALL_GIT_DIFF_UNIFIED_ZERO_COMMAND,
|
|
761
|
+
base_revision,
|
|
762
|
+
)
|
|
763
|
+
return _strict_terminology_findings(
|
|
764
|
+
repository_root,
|
|
765
|
+
all_arguments,
|
|
766
|
+
base_revision,
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
def _strict_terminology_findings(
|
|
771
|
+
repository_root: Path,
|
|
772
|
+
all_diff_arguments: Sequence[str],
|
|
773
|
+
tree_revision: str,
|
|
774
|
+
) -> list[str]:
|
|
775
|
+
diff_process = _run_strict_git(repository_root, all_diff_arguments)
|
|
734
776
|
_raise_for_git_failure(diff_process, GIT_DIFF_OPERATION)
|
|
735
777
|
all_added_names = _identifier_names_on_added_code_lines(diff_process.stdout)
|
|
736
778
|
preexisting_tuples = frozenset(
|
|
737
779
|
_identifier_token_tuple(each_name)
|
|
738
|
-
for each_name in _strict_base_tree_names(
|
|
780
|
+
for each_name in _strict_base_tree_names(
|
|
781
|
+
repository_root, all_added_names, tree_revision
|
|
782
|
+
)
|
|
739
783
|
)
|
|
740
784
|
return _find_terminology_near_misses(diff_process.stdout, preexisting_tuples)
|
|
741
785
|
|
|
@@ -743,16 +787,15 @@ def strict_staged_terminology_findings(repository_root: Path) -> list[str]:
|
|
|
743
787
|
def staged_terminology_findings(repository_root: Path) -> list[str]:
|
|
744
788
|
"""Return terminology near-miss findings for a repository's staged diff.
|
|
745
789
|
|
|
746
|
-
An identifier
|
|
747
|
-
|
|
748
|
-
identifiers are swept.
|
|
790
|
+
An identifier already present in HEAD is not treated as introduced, so
|
|
791
|
+
prose is not flagged against it.
|
|
749
792
|
|
|
750
793
|
Args:
|
|
751
794
|
repository_root: The repository root the staged diff is read from.
|
|
752
795
|
|
|
753
796
|
Returns:
|
|
754
|
-
One finding string per near-miss term on a staged
|
|
755
|
-
|
|
797
|
+
One finding string per near-miss term on a staged prose line, or an
|
|
798
|
+
empty list when the staged diff is empty or git cannot be run.
|
|
756
799
|
"""
|
|
757
800
|
diff_process = subprocess.run(
|
|
758
801
|
list(ALL_GIT_DIFF_CACHED_UNIFIED_ZERO_COMMAND),
|
|
@@ -770,7 +813,9 @@ def staged_terminology_findings(repository_root: Path) -> list[str]:
|
|
|
770
813
|
all_added_names = _identifier_names_on_added_code_lines(diff_process.stdout)
|
|
771
814
|
preexisting_tuples = frozenset(
|
|
772
815
|
_identifier_token_tuple(each_name)
|
|
773
|
-
for each_name in _base_tree_names(
|
|
816
|
+
for each_name in _base_tree_names(
|
|
817
|
+
repository_root, all_added_names, GIT_BASE_TREE_REVISION
|
|
818
|
+
)
|
|
774
819
|
)
|
|
775
820
|
return _find_terminology_near_misses(diff_process.stdout, preexisting_tuples)
|
|
776
821
|
|
|
@@ -31,6 +31,7 @@ sweep_module = _load_sweep_module()
|
|
|
31
31
|
sweep_diff = sweep_module.sweep_diff
|
|
32
32
|
staged_terminology_findings = sweep_module.staged_terminology_findings
|
|
33
33
|
strict_staged_terminology_findings = sweep_module.strict_staged_terminology_findings
|
|
34
|
+
strict_base_terminology_findings = sweep_module.strict_base_terminology_findings
|
|
34
35
|
main = sweep_module.main
|
|
35
36
|
parse_added_lines = sweep_module._parse_added_lines
|
|
36
37
|
|
|
@@ -53,6 +54,54 @@ def _init_git_repository(repository_path: Path) -> None:
|
|
|
53
54
|
)
|
|
54
55
|
|
|
55
56
|
|
|
57
|
+
def _run_repository_git(repository_path: Path, all_arguments: list[str]) -> str:
|
|
58
|
+
completed = subprocess.run(
|
|
59
|
+
all_arguments,
|
|
60
|
+
cwd=repository_path,
|
|
61
|
+
check=True,
|
|
62
|
+
capture_output=True,
|
|
63
|
+
text=True,
|
|
64
|
+
env=_hermetic_git_environment(),
|
|
65
|
+
)
|
|
66
|
+
return completed.stdout.strip()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _write_repository_text(
|
|
70
|
+
repository_path: Path, relative_path: str, text: str
|
|
71
|
+
) -> None:
|
|
72
|
+
(repository_path / relative_path).write_text(text, encoding="utf-8")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _commit_all(repository_path: Path, message: str) -> None:
|
|
76
|
+
_run_repository_git(repository_path, ["git", "add", "-A"])
|
|
77
|
+
_run_repository_git(repository_path, ["git", "commit", "-m", message])
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _head_revision(repository_path: Path) -> str:
|
|
81
|
+
return _run_repository_git(repository_path, ["git", "rev-parse", "HEAD"])
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _committed_near_miss_repository(repository_path: Path) -> str:
|
|
85
|
+
_init_git_repository(repository_path)
|
|
86
|
+
_write_repository_text(repository_path, "quota.py", "baseline = 1\n")
|
|
87
|
+
_write_repository_text(repository_path, "README.md", "Baseline quota text.\n")
|
|
88
|
+
_commit_all(repository_path, "base")
|
|
89
|
+
comparison_revision = _head_revision(repository_path)
|
|
90
|
+
_write_repository_text(
|
|
91
|
+
repository_path,
|
|
92
|
+
"quota.py",
|
|
93
|
+
"baseline = 1\npremium_request_interactions = 5\n",
|
|
94
|
+
)
|
|
95
|
+
_commit_all(repository_path, "identifier")
|
|
96
|
+
_write_repository_text(
|
|
97
|
+
repository_path,
|
|
98
|
+
"README.md",
|
|
99
|
+
"The premium-request-budget field gates the run.\n",
|
|
100
|
+
)
|
|
101
|
+
_commit_all(repository_path, "documentation")
|
|
102
|
+
return comparison_revision
|
|
103
|
+
|
|
104
|
+
|
|
56
105
|
CODE_AND_PROSE_DIFF = (
|
|
57
106
|
"diff --git a/api/quota.py b/api/quota.py\n"
|
|
58
107
|
"--- a/api/quota.py\n"
|
|
@@ -310,6 +359,16 @@ def test_staged_terminology_findings_empty_when_clean(tmp_path: Path) -> None:
|
|
|
310
359
|
assert staged_terminology_findings(tmp_path) == []
|
|
311
360
|
|
|
312
361
|
|
|
362
|
+
def test_strict_base_terminology_findings_reports_committed_near_miss(
|
|
363
|
+
tmp_path: Path,
|
|
364
|
+
) -> None:
|
|
365
|
+
comparison_revision = _committed_near_miss_repository(tmp_path)
|
|
366
|
+
all_findings = strict_base_terminology_findings(tmp_path, comparison_revision)
|
|
367
|
+
assert len(all_findings) == 1
|
|
368
|
+
assert "README.md:1" in all_findings[0]
|
|
369
|
+
assert "premium-request-budget" in all_findings[0]
|
|
370
|
+
|
|
371
|
+
|
|
313
372
|
def test_parse_added_lines_counts_pre_increment_content_as_added_line() -> None:
|
|
314
373
|
diff_with_pre_increment = (
|
|
315
374
|
"diff --git a/app.mjs b/app.mjs\n"
|