claude-dev-env 4.3.0 → 7.1.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 +35 -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 +35 -3
- package/.agents/skills/session-continuity/README.md +189 -0
- package/.agents/skills/session-continuity/SKILL.md +114 -0
- package/.agents/skills/session-continuity/continuity.mjs +375 -0
- package/.agents/skills/session-continuity/continuity.test.mjs +303 -0
- package/.agents/skills/skill-builder/SKILL.md +3 -196
- package/.agents/skills/syncing-submodules/scripts/test_sync_parent_pointer.py +0 -7
- package/.agents/skills/windows-scheduled-task/SKILL.md +153 -0
- 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/cde.mjs +36 -8
- package/bin/cde.test.mjs +48 -0
- package/bin/ever-shipped-skills.mjs +2 -20
- package/bin/ever-shipped-skills.test.mjs +8 -0
- package/bin/expand_home_directory_tokens.mjs +4 -5
- package/bin/expand_home_directory_tokens.test.mjs +128 -0
- package/bin/git_hooks_installer.mjs +22 -3
- package/bin/git_hooks_installer.test.mjs +159 -5
- package/bin/install-session-continuity.mjs +78 -0
- package/bin/install-session-continuity.test.mjs +42 -0
- package/bin/install.agents-home.test.mjs +15 -13
- package/bin/install.codex-rules.test.mjs +5 -2
- package/bin/install.cursor-rules.test.mjs +5 -2
- package/bin/install.mjs +506 -63
- package/bin/install.policy-lint.test.mjs +130 -0
- package/bin/install.profiles.test.mjs +10 -0
- package/bin/install.prune.test.mjs +286 -37
- package/bin/install.pstack-plugin.test.mjs +114 -0
- package/bin/install.test.mjs +537 -120
- package/bin/install.transaction.test.mjs +3 -3
- package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
- package/docs/CODE_RULES.md +1 -1
- 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_banned_identifiers.py +3 -0
- package/hooks/blocking/code_rules_paired_test.py +22 -15
- package/hooks/blocking/precommit_code_rules_gate.py +5 -8
- package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +7 -52
- package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -69
- package/hooks/blocking/test_code_rules_banned_identifiers.py +64 -0
- 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 +43 -342
- package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
- package/hooks/blocking/test_shared_stdin_adoption.py +1 -47
- package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
- package/hooks/git-hooks/git_hooks_constants/verification_notice_constants.py +116 -0
- package/hooks/git-hooks/post_commit.py +33 -0
- package/hooks/git-hooks/pre_commit.py +18 -49
- package/hooks/git-hooks/pre_push.py +45 -541
- package/hooks/git-hooks/test_installed_policy_lint.py +208 -0
- package/hooks/git-hooks/test_native_hook_support.py +129 -0
- package/hooks/git-hooks/test_native_policy_commit.py +120 -0
- package/hooks/git-hooks/test_post_commit.py +43 -0
- package/hooks/git-hooks/test_pre_commit.py +38 -148
- package/hooks/git-hooks/test_pre_push.py +48 -1631
- package/hooks/git-hooks/test_verification_notice.py +60 -0
- package/hooks/git-hooks/test_verification_start.py +173 -0
- package/hooks/git-hooks/verification_notice.py +192 -0
- package/hooks/git-hooks/verification_notice_context.py +253 -0
- package/hooks/git-hooks/verification_notice_state.py +237 -0
- package/hooks/git-hooks/verification_start.py +100 -0
- package/hooks/hooks.json +1 -120
- package/hooks/hooks_constants/banned_identifiers_constants.py +4 -0
- package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +1 -15
- package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -4
- package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -93
- package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -4
- package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +3 -66
- package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
- package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +46 -201
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +3 -25
- package/hooks/validation/test_post_tool_use_dispatcher.py +35 -298
- package/hooks/validators/run_all_validators.py +5 -1
- package/hooks/validators/security_checks.py +57 -2
- package/hooks/validators/test_hook_timing_harness.py +2 -5
- package/hooks/validators/test_run_all_validators_mutation_tool_parity.py +3 -11
- package/hooks/validators/test_run_all_validators_policy_lint.py +36 -0
- package/hooks/validators/test_security_checks.py +57 -0
- package/package.json +2 -2
- package/rules/confirm-implementation-forks.md +2 -0
- package/rules/durable-post-artifacts.md +2 -1
- package/rules/git-workflow.md +18 -6
- package/rules/pstack-host-mapping.md +48 -0
- package/rules/vault-context.md +3 -5
- package/rules/verify-runtime-state.md +7 -0
- package/scripts/audit-hooks-cli.mjs +5 -0
- package/scripts/audit-hooks.mjs +72 -16
- package/scripts/automatic_advisory/__init__.py +1 -0
- package/scripts/automatic_advisory/checkout.py +51 -0
- package/scripts/automatic_advisory/cli.py +334 -0
- package/scripts/automatic_advisory/config/__init__.py +1 -0
- package/scripts/automatic_advisory/config/constants.py +93 -0
- package/scripts/automatic_advisory/config/timing.py +4 -0
- package/scripts/automatic_advisory/configuration.py +197 -0
- package/scripts/automatic_advisory/execution.py +350 -0
- package/scripts/automatic_advisory/git.py +69 -0
- package/scripts/automatic_advisory/model.py +107 -0
- package/scripts/automatic_advisory/process_host.py +32 -0
- package/scripts/automatic_advisory/publisher.py +84 -0
- package/scripts/automatic_advisory/runner.py +399 -0
- package/scripts/automatic_advisory/state.py +116 -0
- package/scripts/automatic_advisory/window_flags.py +41 -0
- package/scripts/automatic_advisory/windows_job.py +122 -0
- 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/codex_compat_materializer.py +99 -13
- package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
- package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +35 -43
- package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +10 -10
- package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +14 -1
- package/scripts/local_report_cli.py +184 -0
- package/scripts/local_report_core.py +247 -0
- package/scripts/local_report_publisher.py +12 -0
- package/scripts/local_report_validation.py +357 -0
- package/scripts/local_verification/__init__.py +23 -0
- package/scripts/local_verification/check_runner.py +364 -0
- package/scripts/local_verification/check_support.py +99 -0
- package/scripts/local_verification/cli.py +158 -0
- package/scripts/local_verification/command_runner.py +84 -0
- package/scripts/local_verification/config/__init__.py +1 -0
- package/scripts/local_verification/config/constants.py +89 -0
- package/scripts/local_verification/config/timing.py +1 -0
- package/scripts/local_verification/git_state.py +146 -0
- package/scripts/local_verification/manifest.py +224 -0
- package/scripts/local_verification/model.py +174 -0
- package/scripts/local_verification/runner.py +234 -0
- package/scripts/policy_lint/adapter_detectors.py +13 -6
- package/scripts/policy_lint/adapter_pairing.py +58 -3
- package/scripts/policy_lint/adapters.py +7 -4
- package/scripts/policy_lint/config/approved_test_pairs.py +323 -0
- 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/pr_verification/__init__.py +1 -0
- package/scripts/pr_verification/branch_refs.py +114 -0
- package/scripts/pr_verification/config/__init__.py +1 -0
- package/scripts/pr_verification/config/constants.py +84 -0
- package/scripts/pr_verification/config/timing.py +5 -0
- package/scripts/pr_verification/github.py +137 -0
- package/scripts/pr_verification/github_api.py +376 -0
- package/scripts/pr_verification/github_labels.py +88 -0
- package/scripts/pr_verification/github_parsing.py +182 -0
- package/scripts/pr_verification/github_transport.py +91 -0
- package/scripts/pr_verification/lock.py +122 -0
- package/scripts/pr_verification/model.py +43 -0
- package/scripts/pr_verification/requirements.txt +1 -0
- package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
- package/scripts/shared_tree_paths.py +32 -3
- package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +97 -0
- package/scripts/test_shared_tree_paths.py +33 -0
- package/scripts/tests/test-audit-hooks-cli.mjs +150 -0
- package/scripts/tests/test-audit-hooks.mjs +94 -2
- package/scripts/tests/test_automatic_advisory.py +376 -0
- package/scripts/tests/test_automatic_advisory_job_cleanup.py +71 -0
- package/scripts/tests/test_automatic_advisory_polling.py +216 -0
- package/scripts/tests/test_automatic_advisory_recovery.py +320 -0
- package/scripts/tests/test_automatic_advisory_repairs.py +400 -0
- package/scripts/tests/test_automatic_advisory_settings.py +48 -0
- package/scripts/tests/test_automatic_advisory_window_flags.py +163 -0
- package/scripts/tests/test_closed_pr_label.py +157 -0
- package/scripts/tests/test_codex_compat_materializer.py +189 -6
- package/scripts/tests/test_github_labels.py +101 -0
- package/scripts/tests/test_github_transport.py +125 -0
- package/scripts/tests/test_local_report_publisher.py +396 -0
- package/scripts/tests/test_local_report_publisher_cli.py +85 -0
- package/scripts/tests/test_local_verification.py +348 -0
- package/scripts/tests/test_local_verification_cli.py +98 -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_pairing.py +163 -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_pr_verification_github.py +392 -0
- package/scripts/tests/test_pr_verification_lock.py +168 -0
- package/scripts/tests/test_rules.py +3 -7
- package/scripts/tests/test_verification_notice.py +347 -0
- package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.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/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/hooks/blocking/ask_user_question_shape_blocker.py +0 -83
- package/hooks/blocking/bot_mention_comment_blocker.py +0 -76
- package/hooks/blocking/claude_md_orphan_file_blocker.py +0 -129
- package/hooks/blocking/cursor_cli_python_misfire_blocker.py +0 -108
- package/hooks/blocking/destructive_command_blocker.py +0 -2073
- package/hooks/blocking/fable_spawn_gate.py +0 -187
- package/hooks/blocking/luna_fast_mode_gate.py +0 -160
- package/hooks/blocking/nas_ssh_binary_enforcer.py +0 -163
- package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +0 -260
- package/hooks/blocking/package_inventory_stale_blocker.py +0 -107
- package/hooks/blocking/pii_prevention_blocker.py +0 -365
- package/hooks/blocking/piped_pytest_blocker.py +0 -1223
- package/hooks/blocking/question_to_user_enforcer.py +0 -130
- package/hooks/blocking/send_user_file_open_locally_blocker.py +0 -71
- package/hooks/blocking/sensitive_file_protector.py +0 -167
- package/hooks/blocking/session_edit_stage_gate.py +0 -684
- package/hooks/blocking/session_handoff_blocker.py +0 -182
- package/hooks/blocking/shell_substitution_blocker.py +0 -350
- package/hooks/blocking/test_ask_user_question_shape.py +0 -69
- package/hooks/blocking/test_bot_mention_comment_blocker.py +0 -131
- package/hooks/blocking/test_claude_md_orphan_file_blocker.py +0 -1277
- package/hooks/blocking/test_cursor_cli_python_misfire_blocker.py +0 -208
- package/hooks/blocking/test_destructive_command_blocker.py +0 -2024
- package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +0 -105
- package/hooks/blocking/test_destructive_command_blocker_no_verify.py +0 -122
- package/hooks/blocking/test_destructive_command_blocker_patterns.py +0 -133
- package/hooks/blocking/test_fable_spawn_gate.py +0 -381
- package/hooks/blocking/test_inventory_deadlock_resolution.py +0 -154
- package/hooks/blocking/test_luna_fast_mode_gate.py +0 -211
- package/hooks/blocking/test_nas_ssh_binary_enforcer.py +0 -225
- package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +0 -231
- package/hooks/blocking/test_package_inventory_stale_blocker.py +0 -382
- package/hooks/blocking/test_pii_prevention_blocker.py +0 -1222
- package/hooks/blocking/test_pii_prevention_windows_git_path.py +0 -41
- package/hooks/blocking/test_pii_write_surface_ephemeral.py +0 -221
- package/hooks/blocking/test_piped_pytest_blocker.py +0 -587
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -233
- package/hooks/blocking/test_question_to_user_enforcer.py +0 -169
- package/hooks/blocking/test_send_user_file_open_locally_blocker.py +0 -118
- package/hooks/blocking/test_sensitive_file_protector.py +0 -365
- package/hooks/blocking/test_session_edit_stage_gate.py +0 -537
- package/hooks/blocking/test_session_edit_stage_gate_staging.py +0 -64
- package/hooks/blocking/test_session_edit_stage_gate_support.py +0 -204
- package/hooks/blocking/test_session_edit_stage_gate_tracker.py +0 -116
- package/hooks/blocking/test_session_handoff_blocker.py +0 -318
- package/hooks/blocking/test_shell_substitution_blocker.py +0 -298
- package/hooks/blocking/test_unscoped_search_blocker.py +0 -102
- package/hooks/blocking/test_write_existing_file_blocker.py +0 -122
- package/hooks/blocking/tests/test_pii_prevention_blocker.py +0 -259
- package/hooks/blocking/unscoped_search_blocker.py +0 -391
- package/hooks/blocking/write_existing_file_blocker.py +0 -124
- package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +0 -19
- package/hooks/hooks_constants/cursor_cli_python_misfire_blocker_constants.py +0 -79
- package/hooks/hooks_constants/fable_spawn_gate_constants.py +0 -61
- package/hooks/hooks_constants/luna_fast_mode_gate_constants.py +0 -45
- package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +0 -20
- package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +0 -57
- package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +0 -17
- package/hooks/hooks_constants/sensitive_file_protector_constants.py +0 -40
- package/hooks/hooks_constants/session_handoff_blocker_constants.py +0 -10
- package/hooks/hooks_constants/shell_substitution_blocker_constants.py +0 -80
- /package/.agents/skills/{_shared/pr-loop → session-continuity}/AGENTS.md +0 -0
- /package/{_shared/pr-loop → .agents/skills/session-continuity}/CLAUDE.md +0 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, unlinkSync, utimesSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import test from 'node:test';
|
|
9
|
+
import { continuityHookConfiguration } from '../../../bin/install-session-continuity.mjs';
|
|
10
|
+
|
|
11
|
+
const sourceDirectory = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const potetoText = '---\nname: Poteto Mode\n---\nPOTETO_SOURCE_EXPECTATION: prove the requested result.\n';
|
|
13
|
+
const secondText = 'SECOND_SKILL_EXPECTATION: measure twice before changing files.\n';
|
|
14
|
+
const sha256 = value => createHash('sha256').update(value).digest('hex');
|
|
15
|
+
|
|
16
|
+
function fixture(t, host) {
|
|
17
|
+
const root = mkdtempSync(join(tmpdir(), 'continuity contract '));
|
|
18
|
+
t.after(() => rmSync(root, { recursive: true, force: true }));
|
|
19
|
+
const skill = join(root, '.agents', 'skills', 'session-continuity');
|
|
20
|
+
mkdirSync(skill, { recursive: true });
|
|
21
|
+
for (const file of ['SKILL.md', 'continuity.mjs']) copyFileSync(join(sourceDirectory, file), join(skill, file));
|
|
22
|
+
const poteto = join(root, '.agents', 'skills', 'pstack', 'poteto-mode', 'SKILL.md');
|
|
23
|
+
mkdirSync(dirname(poteto), { recursive: true });
|
|
24
|
+
writeFileSync(poteto, potetoText);
|
|
25
|
+
const second = join(root, 'second-skill.md');
|
|
26
|
+
writeFileSync(second, secondText);
|
|
27
|
+
const script = join(skill, 'continuity.mjs');
|
|
28
|
+
const configPath = join(root, host === 'claude' ? 'settings.json' : 'hooks.json');
|
|
29
|
+
writeFileSync(configPath, JSON.stringify({ hooks: continuityHookConfiguration(host, script) }));
|
|
30
|
+
const env = { ...process.env };
|
|
31
|
+
delete env.CDE_CONTINUITY_ROOT;
|
|
32
|
+
delete env.CDE_POTETO_SOURCE;
|
|
33
|
+
const pathFor = session => join(root, '.agents', 'state', 'session-continuity', host, `${sha256(session)}.json`);
|
|
34
|
+
const cli = (command, session, data, expectedStatus = 0) => {
|
|
35
|
+
const result = spawnSync(process.execPath, [script, command, host, session], { input: JSON.stringify(data || {}), encoding: 'utf8', env });
|
|
36
|
+
assert.equal(result.status, expectedStatus, result.stderr || result.stdout);
|
|
37
|
+
return expectedStatus ? result.stderr : JSON.parse(result.stdout);
|
|
38
|
+
};
|
|
39
|
+
const fire = (event, session, fields = {}) => {
|
|
40
|
+
const payload = { hook_event_name: event, session_id: session, cwd: root, ...fields };
|
|
41
|
+
const config = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
42
|
+
const groups = config.hooks[event] || [];
|
|
43
|
+
const matching = groups.filter(group => !group.matcher || new RegExp(group.matcher).test(event === 'SessionStart' ? fields.source : fields.command_name));
|
|
44
|
+
return matching.flatMap(group => group.hooks.map(handler => {
|
|
45
|
+
const result = spawnSync(handler.command, { shell: true, input: JSON.stringify(payload), encoding: 'utf8', env });
|
|
46
|
+
assert.equal(result.status, 0, result.stderr);
|
|
47
|
+
return JSON.parse(result.stdout);
|
|
48
|
+
}));
|
|
49
|
+
};
|
|
50
|
+
const submit = (session, prompt) => fire('UserPromptSubmit', session, { prompt })[0];
|
|
51
|
+
const read = session => JSON.parse(readFileSync(pathFor(session), 'utf8'));
|
|
52
|
+
return { root, script, skill, poteto, second, pathFor, cli, fire, submit, read };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for (const host of ['claude', 'codex']) {
|
|
56
|
+
test(`${host}: configured invocation emits complete instructions, writes and reads back, restores without a path`, t => {
|
|
57
|
+
const f = fixture(t, host);
|
|
58
|
+
assert.deepEqual(f.fire('SessionStart', 'session-a', { source: 'startup' }), [{}]);
|
|
59
|
+
assert.equal(existsSync(f.pathFor('session-a')), false);
|
|
60
|
+
const prefix = host === 'codex' ? '$pstack:poteto-mode' : '/pstack:poteto-mode';
|
|
61
|
+
const prompt = `${prefix} for this entire session\nFinish the sample task. Keep changes local. Use second-skill for this task.`;
|
|
62
|
+
const output = f.submit('session-a', prompt);
|
|
63
|
+
assert.ok(output.systemMessage.includes(f.pathFor('session-a')));
|
|
64
|
+
const context = output.hookSpecificOutput.additionalContext;
|
|
65
|
+
assert.ok(context.includes(readFileSync(join(f.skill, 'SKILL.md'), 'utf8')));
|
|
66
|
+
assert.ok(context.includes(potetoText));
|
|
67
|
+
assert.ok(context.includes('Saved record read from disk:'));
|
|
68
|
+
let record = f.read('session-a');
|
|
69
|
+
assert.equal(record.requirements[0].scope, 'session');
|
|
70
|
+
assert.equal(record.requirements[0].source, f.poteto);
|
|
71
|
+
assert.equal(record.requirements[0].unavailable, null);
|
|
72
|
+
f.cli('update', 'session-a', {
|
|
73
|
+
expected_revision: record.revision, prompt_id: record.pending[0].id, quote: 'Finish the sample task.',
|
|
74
|
+
task: { goal: 'Finish the sample task', boundaries: ['local files'], constraints: ['Keep changes local'], completion: ['sample works'] },
|
|
75
|
+
set: [{ kind: 'rule', id: 'rule:local', text: 'Keep changes local.', scope: 'session', duration: 'this session', quote: 'Keep changes local.' },
|
|
76
|
+
{ kind: 'skill', name: 'second-skill', source: f.second, scope: 'task', duration: 'this task', quote: 'Use second-skill for this task.' }],
|
|
77
|
+
checkpoint: { completed: ['scope recorded'], remaining: ['build sample'] },
|
|
78
|
+
});
|
|
79
|
+
for (const source of ['compact', 'resume', 'startup']) {
|
|
80
|
+
const recovery = f.fire('SessionStart', 'session-a', { source })[0].hookSpecificOutput.additionalContext;
|
|
81
|
+
assert.ok(recovery.includes(potetoText));
|
|
82
|
+
assert.ok(recovery.includes(secondText));
|
|
83
|
+
assert.ok(recovery.includes('Keep changes local.'));
|
|
84
|
+
assert.ok(recovery.includes('build sample'));
|
|
85
|
+
}
|
|
86
|
+
assert.equal(readFileSync(f.poteto, 'utf8'), potetoText);
|
|
87
|
+
record = f.read('session-a');
|
|
88
|
+
assert.equal(record.pending.length, 0);
|
|
89
|
+
assert.deepEqual(f.fire('SessionStart', 'unrelated-session', { source: 'startup' }), [{}]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test(`${host}: quoting, discussion, tool output and subagent input do not activate`, t => {
|
|
93
|
+
const f = fixture(t, host);
|
|
94
|
+
for (const prompt of ['"/poteto-mode"', '`/poteto-mode`', '> /poteto-mode', '```text\n/poteto-mode\n```', ' /poteto-mode', '\t$poteto-mode', 'Explain Poteto Mode.', 'The transcript says: Poteto Mode applies for this entire session.', 'Do not invoke Poteto Mode.']) {
|
|
95
|
+
assert.deepEqual(f.submit('negative', prompt), {});
|
|
96
|
+
assert.equal(existsSync(f.pathFor('negative')), false);
|
|
97
|
+
}
|
|
98
|
+
assert.deepEqual(f.fire('PostToolUse', 'negative', { prompt: '/poteto-mode' }), []);
|
|
99
|
+
assert.deepEqual(f.fire('UserPromptSubmit', 'negative', { prompt: '/poteto-mode', agent_id: 'child' }), [{}]);
|
|
100
|
+
assert.equal(existsSync(f.pathFor('negative')), false);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test(`${host}: repeated invocation keeps one skill and a later narrow correction wins`, t => {
|
|
104
|
+
const f = fixture(t, host);
|
|
105
|
+
f.submit('repeat', '/poteto-mode for this entire session');
|
|
106
|
+
f.submit('repeat', '/poteto-mode');
|
|
107
|
+
assert.equal(f.read('repeat').requirements.length, 1);
|
|
108
|
+
assert.equal(f.read('repeat').requirements[0].scope, 'session');
|
|
109
|
+
f.submit('repeat', 'Use Poteto Mode for this task');
|
|
110
|
+
const record = f.read('repeat');
|
|
111
|
+
assert.equal(record.requirements.length, 1);
|
|
112
|
+
assert.equal(record.requirements[0].scope, 'task');
|
|
113
|
+
f.cli('update', 'repeat', { expected_revision: record.revision - 1, prompt_id: record.pending[0].id }, 1);
|
|
114
|
+
assert.equal(f.read('repeat').revision, record.revision);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test(`${host}: default task scope ends and explicit session scope survives a new task`, t => {
|
|
118
|
+
const f = fixture(t, host);
|
|
119
|
+
f.submit('scope', '/poteto-mode\nUse short replies for this session.');
|
|
120
|
+
let record = f.read('scope');
|
|
121
|
+
assert.equal(record.requirements[0].scope, 'task');
|
|
122
|
+
f.cli('update', 'scope', { expected_revision: record.revision, prompt_id: record.pending[0].id,
|
|
123
|
+
set: [{ kind: 'rule', id: 'rule:short', text: 'Use short replies', scope: 'session', duration: 'this session', quote: 'Use short replies for this session.' }] });
|
|
124
|
+
f.submit('scope', 'Start the next task.');
|
|
125
|
+
record = f.read('scope');
|
|
126
|
+
f.cli('update', 'scope', { expected_revision: record.revision, prompt_id: record.pending[0].id, quote: 'Start the next task.', new_task: true,
|
|
127
|
+
task: { goal: 'next task', boundaries: [], constraints: [], completion: ['verified'] } });
|
|
128
|
+
const recovery = f.fire('SessionStart', 'scope', { source: 'compact' })[0].hookSpecificOutput.additionalContext;
|
|
129
|
+
assert.ok(recovery.includes('Use short replies'));
|
|
130
|
+
assert.equal(recovery.includes(potetoText), false);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test(`${host}: source changes are compared and missing sources never use remembered contents`, t => {
|
|
134
|
+
const f = fixture(t, host);
|
|
135
|
+
f.submit('source', '/poteto-mode');
|
|
136
|
+
writeFileSync(f.poteto, potetoText.replace('prove the requested result', 'inspect the current result'));
|
|
137
|
+
const changed = f.fire('SessionStart', 'source', { source: 'compact' })[0].hookSpecificOutput.additionalContext;
|
|
138
|
+
assert.ok(changed.includes('CHANGED skill'));
|
|
139
|
+
assert.ok(changed.includes('before_excerpt'));
|
|
140
|
+
assert.ok(changed.includes('inspect the current result'));
|
|
141
|
+
unlinkSync(f.poteto);
|
|
142
|
+
const missing = f.fire('SessionStart', 'source', { source: 'resume' })[0].hookSpecificOutput.additionalContext;
|
|
143
|
+
assert.ok(missing.includes('UNAVAILABLE skill'));
|
|
144
|
+
assert.equal(missing.includes('POTETO_SOURCE_EXPECTATION'), false);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test(`${host}: sessions in the same repository never select each other's newer record`, t => {
|
|
148
|
+
const f = fixture(t, host);
|
|
149
|
+
f.submit('a', '/poteto-mode for this task');
|
|
150
|
+
f.submit('b', '/poteto-mode for this entire session');
|
|
151
|
+
const old = new Date('2000-01-01');
|
|
152
|
+
utimesSync(f.pathFor('b'), old, old);
|
|
153
|
+
assert.notEqual(f.pathFor('a'), f.pathFor('b'));
|
|
154
|
+
assert.equal(f.cli('show', 'a').record.requirements[0].scope, 'task');
|
|
155
|
+
assert.equal(f.cli('show', 'b').record.requirements[0].scope, 'session');
|
|
156
|
+
assert.ok(f.fire('SessionStart', 'b', { source: 'resume' })[0].hookSpecificOutput.additionalContext.includes(f.pathFor('b')));
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test(`${host}: deactivation survives compaction and restart; explicit invocation starts a fresh set`, t => {
|
|
160
|
+
const f = fixture(t, host);
|
|
161
|
+
f.submit('off', '/poteto-mode for this entire session');
|
|
162
|
+
const disabled = f.submit('off', '/session-continuity off');
|
|
163
|
+
assert.ok(disabled.systemMessage.includes('deactivated'));
|
|
164
|
+
if (host === 'claude') f.fire('UserPromptExpansion', 'off', { expansion_type: 'slash_command', command_name: 'session-continuity', prompt: '/session-continuity off' });
|
|
165
|
+
assert.equal(f.read('off').status, 'inactive');
|
|
166
|
+
assert.deepEqual(f.fire('SessionStart', 'off', { source: 'compact' }), [{}]);
|
|
167
|
+
assert.deepEqual(f.fire('SessionStart', 'off', { source: 'resume' }), [{}]);
|
|
168
|
+
assert.deepEqual(f.submit('off', 'Explain Poteto Mode.'), {});
|
|
169
|
+
f.submit('off', '/poteto-mode');
|
|
170
|
+
assert.equal(f.read('off').requirements.length, 1);
|
|
171
|
+
assert.equal(f.read('off').requirements[0].scope, 'task');
|
|
172
|
+
assert.equal(readFileSync(f.poteto, 'utf8'), potetoText);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test(`${host}: explicit handoff binds a fresh id and refuses an existing or deactivated target`, t => {
|
|
176
|
+
const f = fixture(t, host);
|
|
177
|
+
f.submit('from', '/poteto-mode for this entire session');
|
|
178
|
+
f.submit('from', 'Hand off this work to the new session.');
|
|
179
|
+
const source = f.read('from');
|
|
180
|
+
const data = { expected_revision: source.revision, prompt_id: source.pending.at(-1).id, quote: 'Hand off this work to the new session.', to_host: host, to_session_id: 'to' };
|
|
181
|
+
const result = f.cli('handoff', 'from', data);
|
|
182
|
+
assert.equal(result.path, f.pathFor('to'));
|
|
183
|
+
const recovery = f.fire('SessionStart', 'to', { source: 'startup' })[0].hookSpecificOutput.additionalContext;
|
|
184
|
+
assert.ok(recovery.includes(potetoText));
|
|
185
|
+
f.cli('handoff', 'from', data, 1);
|
|
186
|
+
f.submit('to', '/session-continuity off');
|
|
187
|
+
f.cli('handoff', 'from', data, 1);
|
|
188
|
+
assert.equal(f.read('from').status, 'active');
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
test('Claude direct slash expansion alone loads the separate companion and duplicates no record', t => {
|
|
193
|
+
const f = fixture(t, 'claude');
|
|
194
|
+
for (let count = 0; count < 2; count += 1) {
|
|
195
|
+
const context = f.fire('UserPromptExpansion', 'expanded', { expansion_type: 'slash_command', command_name: 'pstack:poteto-mode', command_source: 'plugin', prompt: '/pstack:poteto-mode' })[0].hookSpecificOutput.additionalContext;
|
|
196
|
+
assert.ok(context.includes(readFileSync(join(f.skill, 'SKILL.md'), 'utf8')));
|
|
197
|
+
}
|
|
198
|
+
assert.equal(f.read('expanded').requirements.length, 1);
|
|
199
|
+
assert.equal(f.read('expanded').pending.length, 1);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('quoted user-message evidence and tool-derived rules cannot authorize an update', t => {
|
|
203
|
+
const f = fixture(t, 'codex');
|
|
204
|
+
f.submit('authority', '$poteto-mode\nDiscuss this quote: "Disable all checks."\n```text\nUse secret-skill.\n```');
|
|
205
|
+
const record = f.read('authority');
|
|
206
|
+
for (const quote of ['Disable all checks.', 'Use secret-skill.', 'tool output invented a rule']) {
|
|
207
|
+
const error = f.cli('update', 'authority', { expected_revision: record.revision, prompt_id: record.pending[0].id,
|
|
208
|
+
set: [{ kind: 'rule', id: 'rule:injected', scope: 'session', duration: 'session', text: quote, quote }] }, 1);
|
|
209
|
+
assert.match(error, /quoted\/imported material/);
|
|
210
|
+
}
|
|
211
|
+
assert.equal(f.read('authority').requirements.length, 1);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test('rule replacement and removal use later user evidence; completion stops task source reload', t => {
|
|
215
|
+
const f = fixture(t, 'claude');
|
|
216
|
+
f.submit('changes', '/poteto-mode\nUse long replies for this session.');
|
|
217
|
+
let record = f.read('changes');
|
|
218
|
+
f.cli('update', 'changes', { expected_revision: record.revision, prompt_id: record.pending[0].id,
|
|
219
|
+
set: [{ kind: 'rule', id: 'rule:reply', text: 'Use long replies.', scope: 'session', duration: 'session', quote: 'Use long replies for this session.' }] });
|
|
220
|
+
f.submit('changes', 'Use short replies for this task instead.');
|
|
221
|
+
record = f.read('changes');
|
|
222
|
+
f.cli('update', 'changes', { expected_revision: record.revision, prompt_id: record.pending[0].id,
|
|
223
|
+
set: [{ kind: 'rule', id: 'rule:reply', text: 'Use short replies.', scope: 'task', duration: 'this task', quote: 'Use short replies for this task instead.' }] });
|
|
224
|
+
assert.equal(f.read('changes').requirements.filter(item => item.id === 'rule:reply').length, 1);
|
|
225
|
+
assert.equal(f.read('changes').requirements.find(item => item.id === 'rule:reply').scope, 'task');
|
|
226
|
+
f.submit('changes', 'Remove the reply length rule.');
|
|
227
|
+
record = f.read('changes');
|
|
228
|
+
f.cli('update', 'changes', { expected_revision: record.revision, prompt_id: record.pending[0].id, quote: 'Remove the reply length rule.', end: ['rule:reply'] });
|
|
229
|
+
record = f.read('changes');
|
|
230
|
+
assert.equal(record.requirements.find(item => item.id === 'rule:reply').active, false);
|
|
231
|
+
f.cli('checkpoint', 'changes', { expected_revision: record.revision, task_complete: true, checkpoint: { completed: ['verified sample'], remaining: [] } });
|
|
232
|
+
const recovery = f.fire('SessionStart', 'changes', { source: 'compact' })[0].hookSpecificOutput.additionalContext;
|
|
233
|
+
assert.equal(recovery.includes(potetoText), false);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test('a busy record blocks prompt processing, preserves state, and supports a safe retry', t => {
|
|
237
|
+
const f = fixture(t, 'claude');
|
|
238
|
+
f.submit('busy', '/poteto-mode');
|
|
239
|
+
const before = readFileSync(f.pathFor('busy'), 'utf8');
|
|
240
|
+
writeFileSync(f.pathFor('busy') + '.lock', 'test-writer');
|
|
241
|
+
const blocked = f.submit('busy', 'Use short replies for this session.');
|
|
242
|
+
assert.equal(blocked.decision, 'block');
|
|
243
|
+
assert.match(blocked.reason, /Record busy/);
|
|
244
|
+
assert.equal(readFileSync(f.pathFor('busy'), 'utf8'), before);
|
|
245
|
+
unlinkSync(f.pathFor('busy') + '.lock');
|
|
246
|
+
f.submit('busy', 'Use short replies for this session.');
|
|
247
|
+
assert.equal(f.read('busy').pending.length, 2);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test('clear deactivates a reused host id rather than inheriting an unrelated task', t => {
|
|
251
|
+
const f = fixture(t, 'claude');
|
|
252
|
+
f.submit('clear', '/poteto-mode for this entire session');
|
|
253
|
+
f.fire('SessionStart', 'clear', { source: 'clear' });
|
|
254
|
+
assert.equal(f.read('clear').status, 'inactive');
|
|
255
|
+
assert.deepEqual(f.fire('SessionStart', 'clear', { source: 'startup' }), [{}]);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
test('missing host identity and corrupt records produce visible recovery failures', t => {
|
|
259
|
+
const f = fixture(t, 'codex');
|
|
260
|
+
const missing = f.fire('UserPromptSubmit', '', { prompt: '$poteto-mode' })[0];
|
|
261
|
+
assert.equal(missing.decision, 'block');
|
|
262
|
+
f.submit('corrupt', '$poteto-mode');
|
|
263
|
+
writeFileSync(f.pathFor('corrupt'), '{bad json');
|
|
264
|
+
const failure = f.fire('SessionStart', 'corrupt', { source: 'resume' })[0];
|
|
265
|
+
assert.match(failure.systemMessage, /Session continuity failed/);
|
|
266
|
+
assert.match(failure.hookSpecificOutput.additionalContext, /Stop dependent work/);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
for (const host of ['claude', 'codex']) {
|
|
270
|
+
test(`${host}: two simultaneous configured callbacks keep distinct session records`, async t => {
|
|
271
|
+
const f = fixture(t, host);
|
|
272
|
+
const configuration = continuityHookConfiguration(host, f.script);
|
|
273
|
+
const command = configuration.UserPromptSubmit[0].hooks[0].command;
|
|
274
|
+
const fire = (session, scope) => new Promise((resolve, reject) => {
|
|
275
|
+
const env = { ...process.env };
|
|
276
|
+
delete env.CDE_CONTINUITY_ROOT;
|
|
277
|
+
delete env.CDE_POTETO_SOURCE;
|
|
278
|
+
const child = spawn(command, { shell: true, env });
|
|
279
|
+
let stdout = '';
|
|
280
|
+
let stderr = '';
|
|
281
|
+
child.stdout.on('data', chunk => { stdout += chunk; });
|
|
282
|
+
child.stderr.on('data', chunk => { stderr += chunk; });
|
|
283
|
+
child.on('error', reject);
|
|
284
|
+
child.on('close', code => code ? reject(new Error(stderr)) : resolve(JSON.parse(stdout)));
|
|
285
|
+
child.stdin.end(JSON.stringify({ hook_event_name: 'UserPromptSubmit', session_id: session, cwd: f.root, prompt: `/poteto-mode for this ${scope}` }));
|
|
286
|
+
});
|
|
287
|
+
await Promise.all([fire('parallel-a', 'task'), fire('parallel-b', 'entire session')]);
|
|
288
|
+
assert.equal(f.read('parallel-a').requirements[0].scope, 'task');
|
|
289
|
+
assert.equal(f.read('parallel-b').requirements[0].scope, 'session');
|
|
290
|
+
assert.notEqual(f.pathFor('parallel-a'), f.pathFor('parallel-b'));
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
test('a new explicit invocation after task completion starts a distinct task without restoring ended rules', t => {
|
|
295
|
+
const f = fixture(t, 'claude');
|
|
296
|
+
f.submit('completed', '/poteto-mode');
|
|
297
|
+
const before = f.read('completed');
|
|
298
|
+
f.cli('checkpoint', 'completed', { expected_revision: before.revision, task_complete: true, checkpoint: { completed: ['verified'], remaining: [] } });
|
|
299
|
+
const output = f.submit('completed', '/poteto-mode');
|
|
300
|
+
assert.notEqual(f.read('completed').task.id, before.task.id);
|
|
301
|
+
assert.equal(f.read('completed').task.completed, false);
|
|
302
|
+
assert.ok(output.hookSpecificOutput.additionalContext.includes(potetoText));
|
|
303
|
+
});
|
|
@@ -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.
|
|
@@ -74,10 +74,3 @@ def test_success_emits_one_json_record(
|
|
|
74
74
|
assert exit_code == 0
|
|
75
75
|
assert sync_record["status"] == "not_submodule"
|
|
76
76
|
assert captured_error == ""
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def test_native_post_commit_source_and_test_are_removed() -> None:
|
|
80
|
-
hook_directory = Path(__file__).resolve().parents[4] / "hooks" / "git-hooks"
|
|
81
|
-
|
|
82
|
-
assert not (hook_directory / "post_commit.py").exists()
|
|
83
|
-
assert not (hook_directory / "test_post_commit.py").exists()
|