claude-code-conductor 2.68.0__tar.gz → 2.69.0__tar.gz
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.
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/tier_autoapply.py +101 -37
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/CHANGELOG.md +32 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/PKG-INFO +1 -1
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/__init__.py +1 -1
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_tier_autoapply.py +648 -37
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_tier_security_fixes.py +5 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/.gitignore +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/CLAUDE.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/code-reviewer.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/design-critic.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/developer.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/security-reviewer.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/systematic-debugger.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/tester.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/wt_developer.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/wt_systematic-debugger.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/agents/wt_tester.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/breaking-changes.txt +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/deletions.txt +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/docs/autonomous-mode-onboarding.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/docs/config-policy.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/docs/nul-boundary.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/docs/parallel-agents-setup.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/docs/platform-adapters.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/docs/settings.json.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/_hook_utils.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/check_agent_invocation.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/consolidate_memory.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/patterns_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/permission_handler.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/permission_handler_toast.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/planner_check.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/post_tool.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/pre_compact.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/pre_tool.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/recall_autorebuild.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/recall_inject.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/report_contract_check.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/report_path_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/restore_session.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/select_tier.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/session_mode_watch.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/session_start.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/session_stop.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/session_utils.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/stop.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/tier_gap_check.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/permission_rules.json +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/settings.json +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/autonomous-mode/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/autonomous-mode/scripts/mode_line.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/brainstorm/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/codex-review/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/c3-omission-declaration.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/design-critic-rubric.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/design-rubric.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/interview-rubric.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/reachability-map.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/record-protocol.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/scripts/detect_execution_verification.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/scripts/record_agent_outcome.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/develop/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/doc/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/extract-lib/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/init-session/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/init-session/scripts/session_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/mcp-config/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/parallel-agents/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/pattern-status/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/recall/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/review-phase/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/setup/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/setup/reference.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/start/SKILL.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/skills/start/scripts/archive_reports.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/state/.gitkeep +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.gitignore +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/ARCHITECTURE.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/LICENSE +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/LICENSES/fastembed-LICENSE +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/LICENSES/fastembed-NOTICE +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/LICENSES/numpy-LICENSE +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/LICENSES/onnxruntime-LICENSE +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/README.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/hatch_build.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/pyproject.toml +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/__main__.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/_db_params.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/_excludes.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/_terminal.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/adapters.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_ask.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_doctor.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_metrics.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_plan.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_recall.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_run.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_tier.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/cli_update.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/db.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/embedding.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/gitutil.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/mcp_server.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrate.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/001_initial.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/003_tier_cost.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/004_agent_outcomes.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/005_drop_agent_tier_bandit.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/006_review_decisions_severity.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/007_review_decisions_resolution.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/008_drop_agent_runs.sql +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/README.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/migrations/__init__.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/paths.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/plan_validator.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/platforms.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/pricing.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/question.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/recall_chunker.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/recall_index.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/refgraph.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/src/c3/usage_ingester.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/__init__.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/_pre_compact_helpers.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/conftest.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/fixtures/usage/README.md +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/fixtures/usage/mainline.jsonl +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/__init__.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_check_agent_invocation.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_consolidate_memory.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_detect_execution_verification.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_hook_utils.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_permission_handler.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_permission_handler_toast.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_planner_check.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_planner_check_dev.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_post_tool.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_pre_tool.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_recall_autorebuild.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_recall_inject.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_record_agent_outcome.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_record_review_decision.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_report_path_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_restore_session.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_review_hint_inject.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_select_tier.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_select_tier_escalation.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_session_start.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_session_stop.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_session_utils.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_settings_tier_autoapply_registration.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_similarity_boost.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_statusline.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_statusline_template_sync.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_sync_check.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_template_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/hooks/test_tier_gap_check.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/__init__.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/_skill_helpers.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_c3_omission_declaration.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_init_session_no_task_type.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_marker_compliance.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_parallel_agents_skill_tier.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_planner_lightweight.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_reachability_map.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_recall_skill.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_session_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_setup_templates.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_start_skill_new_flow.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_adapters.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_archive_reports.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_audit_review_decisions.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_check_deletions.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_ci_workflows.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_claude_gitignore.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_ask.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_doctor.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_doctor_launcher.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_entry.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_init.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_list.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_metrics.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_plan.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_recall.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_run.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_tier.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_update_breaking_changes.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_cli_update_deletions.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_db.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_db_connect_lint.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_docstring_consistency.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_embedding.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_excludes.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_extract_breaking_changes.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_gitutil.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_hooks_stdin_idiom.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_init_only_patterns.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_mcp_server_elicit.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_migrate.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_mode_line.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_no_bare_python_launcher.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_no_passonly_tests.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_nul_boundary_lint.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_paths.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_patterns_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_plan_validator.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_pre_compact.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_precompact_additional.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_precompact_toctou_fixes.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_pricing.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_recall_chunker.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_recall_index.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_references_migration.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_refgraph.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_refgraph_query.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_refgraph_structural.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_report_contract_check.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_scripts_src_bootstrap.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_scripts_stdout_encoding.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_session_mode_watch.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_session_utils_additional.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_settings_hooks_registration.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_skill_no_builtin_conflict.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_start_skill_archive_contract.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_statusline.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_stop_additional.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_stop_agent_memory_warn.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_stop_hook.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_stop_precompact_fixes.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_sync_template_stop.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_template_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_usage_ingester.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_worktree_guard.py +0 -0
- {claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/tests/test_wt_agent_sync.py +0 -0
{claude_code_conductor-2.68.0 → claude_code_conductor-2.69.0}/.claude/hooks/tier_autoapply.py
RENAMED
|
@@ -20,7 +20,9 @@ check_agent は reviewer 系のみ)のため実行順序に依存しない(
|
|
|
20
20
|
- tier_selection 不在/破損/非文字列 tier のときは注入せず素通り
|
|
21
21
|
(source=frontmatter-default・frontmatter の sonnet が実効するため)。
|
|
22
22
|
- `LAUNCH_LOG_ROLES = {developer, wt_developer, tester, wt_tester}` は
|
|
23
|
-
注入有無に関わらず applied-state(tier_autoapply.jsonl)へ 1
|
|
23
|
+
注入有無に関わらず applied-state(tier_autoapply.jsonl)へ 1 行追記した
|
|
24
|
+
(ロックを取得できない場合のみ追記を断念する。注入は断念に影響されない・
|
|
25
|
+
`_append_applied_state` 参照)。
|
|
24
26
|
reviewer 系・その他 role は記録も注入もしない(exit 0 素通り)。
|
|
25
27
|
- 起動プロンプト先頭の `C3_TASK_ID:` マーカーを抽出し jsonl の `task_id` に
|
|
26
28
|
載せた(T8・並列経路の record 突合キー)。
|
|
@@ -46,8 +48,10 @@ from __future__ import annotations
|
|
|
46
48
|
import collections
|
|
47
49
|
import json
|
|
48
50
|
import os
|
|
51
|
+
import random
|
|
49
52
|
import re
|
|
50
53
|
import sys
|
|
54
|
+
import time
|
|
51
55
|
from datetime import datetime, timezone
|
|
52
56
|
|
|
53
57
|
try:
|
|
@@ -83,6 +87,7 @@ if not (_CLAUDE_DIR.endswith(os.sep + ".claude") or _CLAUDE_DIR.endswith("/.clau
|
|
|
83
87
|
|
|
84
88
|
TIER_SELECTION_PATH = os.path.join(_CLAUDE_DIR, "state", "tier_selection.json")
|
|
85
89
|
APPLIED_STATE_PATH = os.path.join(_CLAUDE_DIR, "state", "tier_autoapply.jsonl")
|
|
90
|
+
LOCK_FILE_PATH = APPLIED_STATE_PATH + ".lock"
|
|
86
91
|
|
|
87
92
|
# §3-2 ロール分岐表の定数。
|
|
88
93
|
# APPLY_ROLES: 無条件 APPLY(起動フェーズを問わず tier_selection.json のトップレベル
|
|
@@ -117,6 +122,12 @@ _ROTATE_TAIL_LINES = 500
|
|
|
117
122
|
|
|
118
123
|
_PROMPT_PREFIX_MAX_CHARS = 200
|
|
119
124
|
|
|
125
|
+
# ロック取得の非ブロック試行+ms リトライパラメータ(§2-1)。
|
|
126
|
+
# 非ブロック 1 回試行で失敗時に以下の間隔で再試行し、締切 5 秒で断念する。
|
|
127
|
+
_LOCK_RETRY_INTERVAL_SEC = 0.02 # 基本リトライ間隔 20ms
|
|
128
|
+
_LOCK_RETRY_JITTER_SEC = 0.02 # 一様乱数 [0, 20ms) を毎回加算(脱同期・P4)
|
|
129
|
+
_LOCK_DEADLINE_SEC = 5.0 # 締切(P2・B 裁定 #3)
|
|
130
|
+
|
|
120
131
|
# T8: 起動プロンプト先頭の C3_TASK_ID マーカー抽出用(§3-1・SR-AI-001 で \A 化)。
|
|
121
132
|
# 文字列先頭アンカー \A + allowlist + 上限200字で誤抽出・秘密混入を構造排除する
|
|
122
133
|
# (record MAX_TASK_LEN=200 と整合)。re.MULTILINE の行頭 ^ は本文孤立行・フェンス内・
|
|
@@ -291,17 +302,52 @@ def _rotate_if_needed(path: str) -> None:
|
|
|
291
302
|
pass
|
|
292
303
|
|
|
293
304
|
|
|
294
|
-
def
|
|
295
|
-
"""ロックファイルのバイト0
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
305
|
+
def _try_os_lock(lock_f) -> bool:
|
|
306
|
+
"""ロックファイルのバイト0に排他ロックを非ブロック 1 回試行した。
|
|
307
|
+
|
|
308
|
+
取得成功時 True、競合失敗時 False。競合以外の OSError(EBADF 等)も False 扱い。
|
|
309
|
+
Windows は seek(0) の後 msvcrt.locking LK_NBLCK / POSIX は fcntl.flock LOCK_EX|LOCK_NB。
|
|
310
|
+
msvcrt / fcntl 両方不在の環境では取得成功扱いで True を返す(DC-AS-002・ADR-5)。
|
|
311
|
+
"""
|
|
312
|
+
if msvcrt is None and fcntl is None:
|
|
313
|
+
# ロック機構が両方不在(理論上rare)の場合は取得成功とみなす
|
|
314
|
+
return True
|
|
315
|
+
try:
|
|
316
|
+
# 冒頭ガードにより、ここに到達する時点で msvcrt / fcntl の少なくとも一方は
|
|
317
|
+
# 非 None が保証されている(DC-AS-004・CR-Q-005)。if/else で全経路が bool を
|
|
318
|
+
# 返すことを構造から読めるようにし、到達不能な末尾 return は置かない。
|
|
319
|
+
if msvcrt is not None:
|
|
320
|
+
lock_f.seek(0)
|
|
321
|
+
msvcrt.locking(lock_f.fileno(), msvcrt.LK_NBLCK, 1)
|
|
322
|
+
return True
|
|
323
|
+
else:
|
|
324
|
+
fcntl.flock(lock_f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
325
|
+
return True
|
|
326
|
+
except OSError:
|
|
327
|
+
return False
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _acquire_lock(lock_f) -> bool:
|
|
331
|
+
"""非ブロック試行+ms リトライループでロック取得を試行した。
|
|
332
|
+
|
|
333
|
+
time.monotonic() 基準の締切内に _try_os_lock が成功したら True、
|
|
334
|
+
締切超過で失敗時は False。リトライ待ち時間はジッター付き。
|
|
335
|
+
"""
|
|
336
|
+
deadline = time.monotonic() + _LOCK_DEADLINE_SEC
|
|
337
|
+
while True:
|
|
338
|
+
if _try_os_lock(lock_f):
|
|
339
|
+
return True
|
|
340
|
+
if time.monotonic() >= deadline:
|
|
341
|
+
return False
|
|
342
|
+
time.sleep(_LOCK_RETRY_INTERVAL_SEC + random.uniform(0, _LOCK_RETRY_JITTER_SEC))
|
|
301
343
|
|
|
302
344
|
|
|
303
345
|
def _os_unlock(lock_f) -> None:
|
|
304
|
-
"""
|
|
346
|
+
"""_try_os_lock で取得したロックを解放した(失敗時は無視)。
|
|
347
|
+
|
|
348
|
+
取得側と同一領域(バイト0の 1 バイト)を対象にするため、Windows は
|
|
349
|
+
_try_os_lock と同じく seek(0) を先行させる(DC-AS-003・非対称だと解放漏れになる)。
|
|
350
|
+
"""
|
|
305
351
|
try:
|
|
306
352
|
if msvcrt is not None:
|
|
307
353
|
lock_f.seek(0)
|
|
@@ -316,54 +362,72 @@ def _append_applied_state(row: dict) -> None:
|
|
|
316
362
|
"""applied-state(jsonl)へ 1 行を単一 write で追記した(§3-4・追記前にローテーション)。
|
|
317
363
|
|
|
318
364
|
専用ロックファイル(`<jsonl>.lock`)の OS ロックで並行 append を直列化した。
|
|
319
|
-
|
|
320
|
-
|
|
365
|
+
ロック取得は非ブロック試行+ms リトライ(ジッター付き・締切 `_LOCK_DEADLINE_SEC`)で、
|
|
366
|
+
取得できたときだけ追記する。締切超過・ロックファイル open 失敗・mkdir 失敗は
|
|
367
|
+
「追記せず stderr に固定文言」で断念し、無ロックのまま追記する経路は持たない(P1・ADR-1)。
|
|
368
|
+
|
|
369
|
+
注入判定への影響はない(P5)。断念時も呼び出し側は stdout へ updatedInput を
|
|
370
|
+
出力して注入を継続する。
|
|
321
371
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
OS ハンドル解放に委ね、明示的な削除を行わない。
|
|
372
|
+
ロックファイルは削除せず残す(CR F-6)。`.claude/state/*` の gitignore exclude
|
|
373
|
+
パターンで配布対象外にしている(_rotate_if_needed 同様の設計)。残っていても
|
|
374
|
+
ロック自体は OS がハンドルクローズ/プロセス終了時に解放するため後続を妨げない。
|
|
326
375
|
"""
|
|
327
376
|
line = json.dumps(row, ensure_ascii=False)
|
|
328
|
-
lock_path = APPLIED_STATE_PATH + ".lock"
|
|
329
377
|
# item2(SR-V-002・Low): jsonl 本体・ロックファイルのいずれかが symlink の場合は
|
|
330
378
|
# 追記全体を沈黙 skip(リンク先への誘導書き込みを防ぐ・fail-safe)。open で
|
|
331
379
|
# follow する前に検証する。Windows は O_NOFOLLOW 非対応のため islink で分岐する
|
|
332
380
|
# (POSIX 慣行に合わせた可搬な検証)。tier_gap_check.py 読み取り側と同型。
|
|
333
381
|
# [CR-NEW3] islink 検証→open 間の TOCTOU レースは構造的に残存するが既知・脅威モデル外
|
|
334
382
|
# (Windows O_NOFOLLOW 非対応による設計選択。stale-lock TOCTOU と同種の回避不能パターン)。
|
|
335
|
-
if os.path.islink(APPLIED_STATE_PATH) or os.path.islink(
|
|
383
|
+
if os.path.islink(APPLIED_STATE_PATH) or os.path.islink(LOCK_FILE_PATH):
|
|
336
384
|
return
|
|
337
385
|
try:
|
|
338
386
|
os.makedirs(os.path.dirname(APPLIED_STATE_PATH), exist_ok=True)
|
|
339
|
-
except OSError
|
|
340
|
-
|
|
387
|
+
except OSError:
|
|
388
|
+
# mkdir 失敗(断念理由: mkdir-failed)。P3 に合わせ可観測性を確保。
|
|
389
|
+
print("[tier_autoapply] append skipped: reason=mkdir-failed", file=sys.stderr)
|
|
341
390
|
return
|
|
342
391
|
|
|
343
392
|
lock_f = None
|
|
344
393
|
try:
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
394
|
+
try:
|
|
395
|
+
lock_f = open(LOCK_FILE_PATH, "a+", encoding="utf-8")
|
|
396
|
+
except OSError:
|
|
397
|
+
# ロックファイル open 失敗(断念理由: lockfile-open-failed)
|
|
398
|
+
print("[tier_autoapply] append skipped: reason=lockfile-open-failed", file=sys.stderr)
|
|
399
|
+
return
|
|
400
|
+
|
|
401
|
+
locked = False
|
|
402
|
+
try:
|
|
403
|
+
locked = _acquire_lock(lock_f)
|
|
404
|
+
except OSError:
|
|
405
|
+
# リトライループ中の OSError は取得失敗扱いで断念(fail-safe)
|
|
406
|
+
locked = False
|
|
407
|
+
|
|
408
|
+
# 締切超過・ロック取得失敗時は追記せず断念した(P1)
|
|
409
|
+
if not locked:
|
|
410
|
+
print("[tier_autoapply] append skipped: reason=deadline", file=sys.stderr)
|
|
411
|
+
return
|
|
412
|
+
|
|
413
|
+
try:
|
|
414
|
+
_rotate_if_needed(APPLIED_STATE_PATH)
|
|
415
|
+
with open(APPLIED_STATE_PATH, "a", encoding="utf-8") as f:
|
|
416
|
+
f.write(line + "\n")
|
|
417
|
+
except OSError:
|
|
418
|
+
# 追記本体(rotate/write)失敗(断念理由: write-failed)。P3 に合わせ可観測性を
|
|
419
|
+
# 確保する(CR-E-002・改訂 2)。他 3 経路と同形式(固定文言のみ・外部由来文字列なし)。
|
|
420
|
+
print("[tier_autoapply] append skipped: reason=write-failed", file=sys.stderr)
|
|
362
421
|
finally:
|
|
422
|
+
# open 成功後の全経路(追記完了・断念・例外)で解放とクローズを保証した。
|
|
423
|
+
# _os_unlock 自身が失敗を握るためここでの追加ガードは不要。
|
|
363
424
|
if lock_f is not None:
|
|
364
425
|
if locked:
|
|
365
426
|
_os_unlock(lock_f)
|
|
366
|
-
|
|
427
|
+
try:
|
|
428
|
+
lock_f.close()
|
|
429
|
+
except OSError:
|
|
430
|
+
pass
|
|
367
431
|
|
|
368
432
|
|
|
369
433
|
def main() -> None:
|
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.69.0] - 2026-08-13
|
|
4
|
+
|
|
5
|
+
### 修正
|
|
6
|
+
|
|
7
|
+
- **`tier_autoapply.py` のロック機構を非ブロック試行+ms リトライへ置換した**(フレーキー根治・
|
|
8
|
+
学習記録の行消失の構造的排除)。従来の `msvcrt.locking(LK_LOCK)` は CRT 仕様で「1 秒間隔
|
|
9
|
+
リトライ・10 回で OSError」のため、複数 agent の同時起動時に待機側のリトライが 1 秒境界に
|
|
10
|
+
同期するロックコンボイが発生し、リトライを枯渇した個体が無ロック追記フォールバックに落ちて
|
|
11
|
+
**他プロセスの追記行を上書き消失させる**実欠陥があった(`TestConcurrency` の非決定的失敗
|
|
12
|
+
〔2026-08-04 起票〕の根本原因。実運用の parallel-agents wave 一斉起動でも発生しうる)。
|
|
13
|
+
新実装は LK_NBLCK / `LOCK_EX|LOCK_NB` の非ブロック試行+ms 粒度リトライ(20ms 間隔+
|
|
14
|
+
0〜20ms ジッターで脱同期・`time.monotonic()` 基準の締切 5 秒)で、実測でコンボイ・行消失とも
|
|
15
|
+
消滅(42 回反復失敗 0・20 並列時の最大取得待ち 0.109 秒)
|
|
16
|
+
|
|
17
|
+
### 変更
|
|
18
|
+
|
|
19
|
+
- **ロック取得失敗時の無ロック追記フォールバックを全廃し断念設計へ変更した**。ロック競合が
|
|
20
|
+
締切 5 秒を超えた場合、当該 1 行の記録を断念して stderr に固定文言を出す(学習記録 1 行の
|
|
21
|
+
欠落に留まり、他プロセスの行を壊さない)。記録処理到達後の断念 4 経路
|
|
22
|
+
(`reason=deadline` / `reason=lockfile-open-failed` / `reason=mkdir-failed` /
|
|
23
|
+
`reason=write-failed`)すべてが固定文言の stderr 証跡を持つ(沈黙断念ゼロ・外部由来文字列は
|
|
24
|
+
含めない)。記録の断念は tier 機械適用(model 注入)に影響しない
|
|
25
|
+
- hook の最悪ブロック時間は従来の約 10 秒から締切 5 秒へ半減した
|
|
26
|
+
|
|
27
|
+
### 内部
|
|
28
|
+
|
|
29
|
+
- `tests/hooks/test_tier_autoapply.py` に P1〜P5 の性質テスト群・断念 4 経路の完全一致固定・
|
|
30
|
+
実競合下のジッター検証(jitter=0 対照で赤化する検知力を実証済み)・ADR-5 / mkdir / write の
|
|
31
|
+
回帰網を追加(52→56 テスト)。`TestConcurrency` は判定コード不変
|
|
32
|
+
- `docs/spec/00-index.md` の凍結宣言に注記 1 行を追加(02-hooks.md / 05-state-db.md の
|
|
33
|
+
ロック記述は旧実装前提である旨)
|
|
34
|
+
|
|
3
35
|
## [2.68.0] - 2026-08-13
|
|
4
36
|
|
|
5
37
|
### 破壊的変更
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.69.0
|
|
4
4
|
Summary: Multi-agent orchestration framework for Claude Code with Codex/Cursor adapters (C3)
|
|
5
5
|
Project-URL: Homepage, https://github.com/satoh-y-0323/claude-code-conductor
|
|
6
6
|
Project-URL: Repository, https://github.com/satoh-y-0323/claude-code-conductor
|