specfuse-loop 0.17.0__tar.gz → 0.18.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.
- {specfuse_loop-0.17.0/specfuse_loop.egg-info → specfuse_loop-0.18.0}/PKG-INFO +1 -1
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/pyproject.toml +1 -1
- specfuse_loop-0.18.0/specfuse/loop/data/VERSION +1 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/operator-escalation.md +4 -4
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/loop.py +61 -5
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0/specfuse_loop.egg-info}/PKG-INFO +1 -1
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse_loop.egg-info/SOURCES.txt +1 -0
- specfuse_loop-0.18.0/tests/test_attempt_note_untracked_files.py +126 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_doc_hygiene.py +44 -0
- specfuse_loop-0.17.0/specfuse/loop/data/VERSION +0 -1
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/LICENSE +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/NOTICE +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/README.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/setup.cfg +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/__init__.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/budget.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/diagnose_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/drafting_answers.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/drafting_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/drafting_questions.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/driver_command.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/driver_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/monitoring_read.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/providers/__init__.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/providers/answers.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/providers/bugs.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/providers/feature.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/providers/findings_autofix.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/providers/findings_diagnose.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/providers/triage.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/queue_read.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/repo_detect.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/triage_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/agent/worktree.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/__init__.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/_filelock.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/_miniyaml.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/_wu_sections.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/adopt_feature.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/agent_policy.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/arm_eval.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/arm_sweep.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/arm_txn.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/bug_lane.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/bug_lane_run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/bug_lane_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/build_provenance.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/changelog.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/closing_requirements.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/cost.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/criteria_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/CHANGELOG.seed.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/LEARNINGS.template.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/concepts/adopting-auto-mode.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/concepts/architecture-addendum-gates-and-iterative-planning.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/concepts/autonomy-stop-classes.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/concepts/ralph-lineage.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/getting-started.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/glossary.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/methodology.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/skills.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/gitignore.snippet +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/monitoring-secrets-checklist.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/monitoring.overrides.yml.example +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/monitoring.yml.example +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/roadmap.template.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/close-discipline.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/correlation-ids.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/design-for-diagnosis.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/human-output.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/never-touch.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/planning-discipline.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/result-contract.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/security-boundaries.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/verification-discipline.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules-local/README.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/schemas/driver-event.schema.json +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/schemas/event.schema.json +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/schemas/events/initiative_created.schema.json +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/schemas/events/spec_issue_resolved.schema.json +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/schemas/events/spec_issue_routed.schema.json +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/schemas/events/spec_validated.schema.json +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/templates/DECISIONS.template.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/templates/GATE.template.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/templates/LEARNINGS-pending.template.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/templates/PLAN.template.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/templates/WU.template.md +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/verification.yml.example +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/workflows/specfuse-monitor.yml +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/decisions_format.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/driver_edit.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/escalation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/events_stats.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/gate_commands.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/gate_eval.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/gh_backend.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/gh_features.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/heartbeat.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/judge.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/labels.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/learnings_query.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/lint_closing.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/lint_monitoring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/lint_plan.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/lint_roadmap.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/notify.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/notify_escalation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/notify_sla.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/plan_baseline.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/policy_proposals.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/policy_review.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/prerun.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/prerun_capture.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/promotion.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/rearm_migration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/replay_spin.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/roadmap_archive.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/scaffold.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/triage.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/upgrade_merge_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/validate_event.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/__init__.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/adapters.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/artifact.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/autofix.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/autofix_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/autofix_run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/autofix_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/cli.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/diagnose_cli.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/diagnosis.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/fingerprint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/issues.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/providers/__init__.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/providers/_azure_auth.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/providers/azure_app_insights.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/providers/azure_service_bus.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/redaction.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/monitor/schedule.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse_loop.egg-info/dependency_links.txt +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse_loop.egg-info/entry_points.txt +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse_loop.egg-info/requires.txt +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse_loop.egg-info/top_level.txt +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_abandon_feature_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_abandoned_work_reported.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_abandoned_wu_strands_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_adopt_feature.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_budget.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_bug_selection_dedup.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_default_features_root.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_driver_command.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_driver_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_driver_restart.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_escalation_on_issue.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_escalation_run_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_findings_seam.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_invoke_timeout.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_invoke_usage.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_item_worktree.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_lock.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_policy_key_ownership.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_policy_queue.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_policy_schema.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_policy_triage_dial.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_provider_answers.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_provider_bugs.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_provider_feature.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_provider_findings_autofix.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_provider_findings_diagnose.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_provider_isolation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_provider_triage.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_queue_read.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_relays_driver_output.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_repo_detect.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_run_progress.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_seam.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_agent_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_answer_escalation_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_app_insights_adapters.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_archive_ref_reconciliation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_eval.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_eval_lint_class.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_eval_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_gate_edits_uncommitted.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_sweep.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_sweep_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_txn.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_arm_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_artifact_redaction.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_attempt_outcome_contract.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_attempt_outcome_emission.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_attention_nonwriting_guard.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_attention_silence_section.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_attention_skill_structure.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autoclose_deferral_visibility.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autoclose_gate_note.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autoclose_stub_states_what_passed.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autofix_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autofix_live.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autofix_predicate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autofix_run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autofix_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autosync.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autosync_consent.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autosync_firstrun.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autosync_no_cwd_leak.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_autosync_plugin.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_azure_credential_resolution.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_backend.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_baseline_escalation_message.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_baseline_persistence.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_baseline_probe.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_baseline_provenance.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_baseline_tree_hash_key.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bash_routing.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bats_suites_gated.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_binary_verdict.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bookkeeping_commit_crash_run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bookkeeping_commit_hook_crash.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bookkeeping_no_verify.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_ci_pending.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_guardrails.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_label_nonfatal.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_labels_registered.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_policy_contract.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_pr_number_carried.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_preflight_and_dial.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_stopped_outcome_pr_number.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_bug_lane_test_paths.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_build_provenance.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_changed_file_test_selection.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_changelog_append_only.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_changelog_collection.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_changelog_release_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_changelog_schema.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_ci_conclusion_wait.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_ci_runs_every_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_claude_resolution.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_close_b_pending_learnings.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_close_records_feature_oracle.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_close_wu_self_reference.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_closing_deliverable_guard.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_closing_guard_contracts.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_closing_guard_prediction.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_closing_learnings_destination.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_closing_requirements.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_coauthor_trailer_allowlist.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_console_encoding.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_convergent_iteration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_convergent_wu_lint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_correlation_id_override.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_correlation_id_two_surfaces.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_cost_lifetime.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_cost_tracking.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_criteria_per_gate_lint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_criteria_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_criteria_worklist.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_decision_citation_lint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_decision_followups_discharged.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_decision_override_lint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_decisions_format.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_degraded_oracle.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_deliverable_missing_note.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_deliverable_presence_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_derive_agent_policy_review_mode.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_derive_agent_policy_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_derive_monitoring_discovery.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_derive_monitoring_skill_registration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_design_for_diagnosis_rule.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_deterministic_refusal_repeat.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_diagnose_headless.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_diagnose_issue_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_diagnosis.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_diagnosis_roundtrip_live.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_dispatch_skeleton.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_doctor.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_done_feature_gates.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_draft_feature_answers_mode.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_drafting_answer_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_drafting_invoke.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_drafting_question_issue.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_drafting_questions.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_drafting_reply_shape.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_edit_detection.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_event_registry_covers_emitters.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_integration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_lock.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_module_surface.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_restart_halt_surfaced.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_restart_halt_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_restart_hold.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_staleness_gate_summary.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_driver_staleness_warning.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_dry_run_no_branch_mutation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_duration_tracking.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_empty_files_escalation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_ensure_feature_branch.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_ensure_feature_branch_base.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_escalation_assignee_policy.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_escalation_contract.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_escalation_crash_containment.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_escalation_dedup_search.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_escalation_emit.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_event_gate_full_envelope.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_events_redaction.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_events_stats.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_extra_gates.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_failure_artifact_model.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_failure_signature_fail_prefix.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_failure_signature_skips_log_noise.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_feature_branch_auto_sync.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_feature_branch_squash_merge.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_feature_branch_stale_base.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_feature_id_resolution.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_feature_oracle_e2e.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_feature_provider_drafting_dispatch.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_feature_review_accumulation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_filelock_portable.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_find_pr_no_search_index.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_fingerprint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_fix_bug_diff_self_check.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_fix_bug_headless.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_fix_bug_reads_comments.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_fold_contract_documented.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_followups_artifact.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_force_full_close.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_frontmatter_scalar_quoting.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_broad_run.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_budget.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_budget_post_dispatch.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_commands_needs.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_eval.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_eval_calibration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_eval_intermediate_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_eval_repo_flag.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_eval_terminal_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gate_report_verdict.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gh_backend.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gh_features.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_git_env_isolation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_gitleaks_pinning.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_groom_backlog_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_guard_refusal_failure_class.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_guard_refusal_failure_excerpt.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_hashed_denylist.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_hashed_denylist_ci.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_heartbeat.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_heartbeat_adapter.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_human_output_rule.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_human_work_unit.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_hyphenated_gate_name.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_init_integration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_installed_copy_driver_e2e.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_interpreter_normalization.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_judge_close_path.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_judge_cost.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_judge_module.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_judge_path_registry.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_label_provisioning_runner_contract.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_label_registry.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_label_registry_covers_consumers.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lazy_baseline_e2e.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_leak_findings_redaction.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_leak_scan.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_leak_scan_content.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_learnings_curate_vendored_promote.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_learnings_query.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_learnings_staging.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_learnings_suggest_signature_filter.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_legacy_4wu_terminal_flips.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lifecycle_integration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lifetime_accounting.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_ac_observable.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_bare_produces_path.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_boundary_consistency.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_boundary_extraction.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_close_intermediate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_close_verdict_not_predecided.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_close_wu.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_closing.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_closing_criteria.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_closing_criteria_pristine.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_correlation_id.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_correlation_id_close_intermediate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_feature_oracle_declared.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_gate_proportionality.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_monitoring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_oracle_env.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_plan_contract_fields.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_plan_errors.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_plan_next_draft.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_plan_relative_import.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_plan_verdict_exempt.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_planning_sections.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_produces_driver_helper.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_produces_satisfiability.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_roadmap.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_sections.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_task_graph_yaml_selection.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_lint_verification_reference.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_live_tests_opt_in.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_load_bearing_close_lint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_attempt_evidence.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_auto_archive.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_caveman_preamble.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_close_intermediate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_criteria_skeleton.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_criteria_survival.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_defaults_by_type.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_effort.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_failure_note_cap.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_files_changed_guard.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_gate_budget.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_gate_needs.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_model_alias.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_orchestration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_post_pass_invariant.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_reset_preserving_events.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_smoke_runner.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_unsandboxed.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_worklist_injection.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_loop_zero_token_guard.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_make_repo_gpgsign_isolation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_max_attempts_configurable.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_migrate_legacy.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_miniyaml_equivalence.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_miniyaml_negative.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitor_cli.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitor_issue_lifecycle.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitor_runner_surfaces.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitoring_bootstrap_artifacts.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitoring_cron_dialect.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitoring_example.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitoring_fenced_blocks.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_monitoring_seed.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_no_pytest_subprocess.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_notify.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_notify_escalation.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_notify_sla.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_operator_escalation_rule.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_oracle_set_declared.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_oracle_unrunnable_attribution.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_pick_feature_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_pin_honesty_and_integrity.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_pin_marker_not_inherited.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_pin_marker_spawn_sites.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_plan_baseline.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_planned_cost_lint.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_planning_cost_floor.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_policy_proposals.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_policy_review.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_pr_checks_json_field.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_pre_existing_claims_cite_evidence.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_prep_halt_operator_surface.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_prepare_feature.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_prepare_scaffold_sync.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_prerun_capture.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_prerun_oracles.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_prerun_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_bracket_literal.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_bracket_wildcard.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_field.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_in_diff.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_justification.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_recursive_glob.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_semantics_unified.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_produces_shape.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_promotion_ledger.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_provider_escalation_traces.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_provision_labels.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_queue_stalled_adapter.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_rearm_clears_stale_criteria_state.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_rearm_fold_marker.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_rearm_migration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_red_baseline_never_reused.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_redaction_windows_home.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_replay_spin.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_resolve_base.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_restart_cap_counts_progress.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_result_block.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_result_block_audience.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_resume_command_build.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_roadmap_add_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_roadmap_archive_cli.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_roadmap_archive_shim.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_roadmap_archive_skill.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_roadmap_archive_skill_delegates.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_roadmap_link_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_roadmap_row_parser.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_ruff_verdict_lines.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_data_in_sync.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_docs.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_init.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_label_provisioning.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_manifest.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_resources.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_seed_sanity.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_skew_halts.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_upgrade.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_scaffold_wiring.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_schedule_dialect.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_seed_documents_prerun_keys.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_service_bus_dlq_adapter.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_session_env_preflight.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_shipped_templates_parse.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_skill_discovery_links.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_skills_vendored_in_sync.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_spinning_rearm_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_squash_commit_hook_crash.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_stop_rationale_captured.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_surefire_run_level_signature.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_surefire_verdict_lines.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_template_closing_shapes.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_terminal_flip_ownership.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_terminal_flips.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_terminal_gate_message.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_tiered_verification_e2e.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_timeout_kill_portable.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_triage.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_triage_apply.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_triage_skill_contract.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_triage_skips_agent_escalations.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_tsc_verdict_lines.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_umbrella_version_resolution.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_unterminated_frontmatter.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_untracked_feature_folder.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_untracked_file_absorption.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_upgrade_integration.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_upgrade_merge_gate.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_validate_event.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_validate_event_driver_types.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_verdict_coupling.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_verify_empty_gate_set.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_version_consistency.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_version_skew.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_windows_gate_exec.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_worktree_restore.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_wu_execution_metadata.py +0 -0
- {specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/tests/test_wu_template_renders_lintable.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specfuse-loop"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.18.0"
|
|
8
8
|
description = "Local-first executor for the Specfuse Plan + Work Unit gate-cycle methodology."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.18.0
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/operator-escalation.md
RENAMED
|
@@ -6,7 +6,7 @@ Licensed under the Apache License, Version 2.0. See LICENSE.
|
|
|
6
6
|
# Rule: operator escalation framing
|
|
7
7
|
|
|
8
8
|
Binding whenever work **stops and needs a human decision** — a `blocked` work
|
|
9
|
-
unit, a gate at `awaiting_review`, a
|
|
9
|
+
unit, a gate at `awaiting_review`, a `not_met` verdict, a scope question, a refusal,
|
|
10
10
|
or any skill that asks before writing.
|
|
11
11
|
|
|
12
12
|
The audience is someone **deciding**, not someone executing. They may not have
|
|
@@ -60,7 +60,7 @@ so in that line rather than dropping it silently.
|
|
|
60
60
|
## The feature briefing — required when the halt is at feature scope
|
|
61
61
|
|
|
62
62
|
The six parts frame a **decision**. When the halt is at feature or gate scope —
|
|
63
|
-
a
|
|
63
|
+
a `not_met` terminal verdict, a feature that stopped partway and needs a human —
|
|
64
64
|
the decision is not the whole question. The operator also needs to know whether
|
|
65
65
|
the work *achieved what it was funded to achieve*, and that is a separate
|
|
66
66
|
question from whether the tasks passed.
|
|
@@ -124,11 +124,11 @@ success is the failure this section prevents.
|
|
|
124
124
|
|
|
125
125
|
- **Options without a recommendation.** Surfacing choices and stopping pushes the
|
|
126
126
|
analysis back onto the person who asked. Always make the call; they can override.
|
|
127
|
-
- **A refusal reported as a malfunction.** A withheld terminal flip on a
|
|
127
|
+
- **A refusal reported as a malfunction.** A withheld terminal flip on a `not_met`
|
|
128
128
|
verdict is the contract working. Reporting it in the same tone as a crash makes
|
|
129
129
|
a correct system look broken and invites someone to "fix" the safety catch.
|
|
130
130
|
- **Writing the human's own justification for them.** Where a field records *why a
|
|
131
|
-
human
|
|
131
|
+
human decided something* — a `type: human` unit's `evidence:` line, `/unblock-wu`'s
|
|
132
132
|
rationale, a contract-change acknowledgment — that text must come from the human.
|
|
133
133
|
An agent that drafts it has removed the signature it was collecting. Ask; do not
|
|
134
134
|
supply.
|
|
@@ -123,7 +123,7 @@ SPECFUSE_DIR = Path(".specfuse")
|
|
|
123
123
|
REPO_ROOT = SPECFUSE_DIR.parent
|
|
124
124
|
FEATURES_DIR = SPECFUSE_DIR / "features"
|
|
125
125
|
VERIFICATION_PATH = SPECFUSE_DIR / "verification.yml"
|
|
126
|
-
DRIVER_VERSION = "0.
|
|
126
|
+
DRIVER_VERSION = "0.18.0"
|
|
127
127
|
# Oldest scaffold layout this driver can drive. init.sh stamps the scaffold's own
|
|
128
128
|
# version into `.specfuse/VERSION`; check_scaffold_version() fails loud at startup if
|
|
129
129
|
# the consumer's scaffold is older than this, pointing at `specfuse upgrade`. Bump
|
|
@@ -2964,14 +2964,68 @@ def apply_diff(diff_text: str) -> bool:
|
|
|
2964
2964
|
return proc.returncode == 0
|
|
2965
2965
|
|
|
2966
2966
|
|
|
2967
|
+
def _untracked_file_blocks(max_chars: int) -> str:
|
|
2968
|
+
"""Render files the attempt CREATED as diff-shaped blocks, capped (#3249).
|
|
2969
|
+
|
|
2970
|
+
`git diff` only reports tracked content, so a file that did not exist at
|
|
2971
|
+
`head_before` has nothing to diff against and never reached the attempt
|
|
2972
|
+
note. FEAT-2026-0100/T03 spun twice against six failures in a new test
|
|
2973
|
+
module that the note did not contain — the operator had to guess.
|
|
2974
|
+
|
|
2975
|
+
`--exclude-standard` honours .gitignore, which keeps `work/` out: folding
|
|
2976
|
+
the notes directory into a note would nest each attempt's evidence inside
|
|
2977
|
+
the next one's. Binary files are named but not inlined.
|
|
2978
|
+
|
|
2979
|
+
Best-effort like its caller: any git error yields "".
|
|
2980
|
+
"""
|
|
2981
|
+
try:
|
|
2982
|
+
raw = subprocess.run(
|
|
2983
|
+
["git", "ls-files", "--others", "--exclude-standard", "-z"],
|
|
2984
|
+
capture_output=True, text=True, check=True,
|
|
2985
|
+
).stdout
|
|
2986
|
+
except (subprocess.CalledProcessError, OSError):
|
|
2987
|
+
return ""
|
|
2988
|
+
blocks: list[str] = []
|
|
2989
|
+
used = 0
|
|
2990
|
+
for path in filter(None, raw.split("\0")):
|
|
2991
|
+
if used >= max_chars:
|
|
2992
|
+
blocks.append("… (further created files omitted)\n")
|
|
2993
|
+
break
|
|
2994
|
+
header = f"--- /dev/null\n+++ b/{path}\n"
|
|
2995
|
+
try:
|
|
2996
|
+
data = Path(path).read_bytes()
|
|
2997
|
+
except OSError:
|
|
2998
|
+
continue
|
|
2999
|
+
if b"\x00" in data:
|
|
3000
|
+
body = f"(binary file, {len(data)} bytes - content omitted)\n"
|
|
3001
|
+
else:
|
|
3002
|
+
text = data.decode("utf-8", errors="replace")
|
|
3003
|
+
# `+` prefix so the block reads as the new-file hunk it stands for.
|
|
3004
|
+
body = "".join(f"+{line}\n" for line in text.splitlines())
|
|
3005
|
+
room = max_chars - used - len(header)
|
|
3006
|
+
if len(body) > room:
|
|
3007
|
+
body = body[:max(room, 0)] + "\n… (file truncated)\n"
|
|
3008
|
+
block = header + body
|
|
3009
|
+
blocks.append(block)
|
|
3010
|
+
used += len(block)
|
|
3011
|
+
return "".join(blocks)
|
|
3012
|
+
|
|
3013
|
+
|
|
2967
3014
|
def capture_working_tree_diff(head_before: str, max_chars: int = 20000) -> str:
|
|
2968
|
-
"""Return
|
|
3015
|
+
"""Return the working tree's departure from `head_before`, capped.
|
|
2969
3016
|
|
|
2970
3017
|
Folded into a failing attempt's evidence note BEFORE the per-attempt
|
|
2971
3018
|
`git reset --hard` discards the rejected work, so a blocked WU stays
|
|
2972
3019
|
diagnosable — a human (or /gate-status) can see the diff that was rolled
|
|
2973
3020
|
back, not just a truncated failure excerpt (#168).
|
|
2974
3021
|
|
|
3022
|
+
Covers tracked changes via `git diff` AND files the attempt created, which
|
|
3023
|
+
`git diff` cannot see (#3249). Created files get a reserved share of the
|
|
3024
|
+
budget rather than whatever a concatenation leaves over: truncating the
|
|
3025
|
+
combined text would let a large tracked diff consume everything and drop
|
|
3026
|
+
the new file again, on exactly the large attempts where diagnosis is
|
|
3027
|
+
hardest.
|
|
3028
|
+
|
|
2975
3029
|
Best-effort: returns "" on any git error or a clean tree. Truncated to
|
|
2976
3030
|
max_chars so a large refactor's diff cannot bloat the committed note.
|
|
2977
3031
|
"""
|
|
@@ -2982,9 +3036,11 @@ def capture_working_tree_diff(head_before: str, max_chars: int = 20000) -> str:
|
|
|
2982
3036
|
).stdout
|
|
2983
3037
|
except (subprocess.CalledProcessError, OSError):
|
|
2984
3038
|
return ""
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
3039
|
+
created = _untracked_file_blocks(max_chars // 2)
|
|
3040
|
+
budget = max_chars - len(created)
|
|
3041
|
+
if len(out) > budget:
|
|
3042
|
+
out = out[:max(budget, 0)] + "\n… (diff truncated)\n"
|
|
3043
|
+
return out + created
|
|
2988
3044
|
|
|
2989
3045
|
|
|
2990
3046
|
def persist_attempt_notes(
|
|
@@ -186,6 +186,7 @@ tests/test_arm_sweep_gate.py
|
|
|
186
186
|
tests/test_arm_txn.py
|
|
187
187
|
tests/test_arm_wiring.py
|
|
188
188
|
tests/test_artifact_redaction.py
|
|
189
|
+
tests/test_attempt_note_untracked_files.py
|
|
189
190
|
tests/test_attempt_outcome_contract.py
|
|
190
191
|
tests/test_attempt_outcome_emission.py
|
|
191
192
|
tests/test_attention_nonwriting_guard.py
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2026 Specfuse contributors
|
|
3
|
+
# Licensed under the Apache License, Version 2.0. See LICENSE.
|
|
4
|
+
#
|
|
5
|
+
"""An attempt note records files the attempt CREATED, not only ones it changed (#3249).
|
|
6
|
+
|
|
7
|
+
`capture_working_tree_diff` folds `git diff <head_before>` into a failing
|
|
8
|
+
attempt's evidence note before the per-attempt `git reset --hard` discards the
|
|
9
|
+
work. `git diff` only sees tracked content, so a file that did not exist at
|
|
10
|
+
`head_before` has nothing to diff against and never reaches the note.
|
|
11
|
+
|
|
12
|
+
That is not a theoretical gap. FEAT-2026-0100/T03 spun twice on 2026-09-06
|
|
13
|
+
against six failures in `tests/test_verify_empty_gate_set.py`; the note carried
|
|
14
|
+
diffs for the WU file, `events.jsonl` and `loop.py`, and the one file that
|
|
15
|
+
explained the failure — the new test module, patching `loop.verify` without
|
|
16
|
+
restoring it — was absent. The operator had to guess, which is what
|
|
17
|
+
`/gate-status` ended up doing.
|
|
18
|
+
|
|
19
|
+
Same lesson `verify_files_changed` already learned for its own purpose (#3119):
|
|
20
|
+
`git diff` is not a complete account of what an attempt did.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import os
|
|
26
|
+
import subprocess
|
|
27
|
+
import tempfile
|
|
28
|
+
import unittest
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
|
|
31
|
+
from tests._loop_loader import load_loop
|
|
32
|
+
|
|
33
|
+
loop = load_loop()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _git(*args: str, cwd: Path) -> str:
|
|
37
|
+
return subprocess.run(
|
|
38
|
+
["git", *args], cwd=cwd, capture_output=True, text=True, check=True,
|
|
39
|
+
).stdout
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class TestAttemptNoteRecordsUntrackedFiles(unittest.TestCase):
|
|
43
|
+
|
|
44
|
+
def setUp(self):
|
|
45
|
+
self._tmp = tempfile.TemporaryDirectory()
|
|
46
|
+
self.repo = Path(self._tmp.name)
|
|
47
|
+
_git("init", "-q", cwd=self.repo)
|
|
48
|
+
_git("config", "user.email", "t@example.com", cwd=self.repo)
|
|
49
|
+
_git("config", "user.name", "t", cwd=self.repo)
|
|
50
|
+
(self.repo / "tracked.py").write_text("original\n")
|
|
51
|
+
(self.repo / ".gitignore").write_text("work/\n")
|
|
52
|
+
_git("add", "-A", cwd=self.repo)
|
|
53
|
+
_git("commit", "-qm", "base", cwd=self.repo)
|
|
54
|
+
self.head_before = _git("rev-parse", "HEAD", cwd=self.repo).strip()
|
|
55
|
+
self._cwd = os.getcwd()
|
|
56
|
+
os.chdir(self.repo)
|
|
57
|
+
|
|
58
|
+
def tearDown(self):
|
|
59
|
+
os.chdir(self._cwd)
|
|
60
|
+
self._tmp.cleanup()
|
|
61
|
+
|
|
62
|
+
def test_a_created_file_reaches_the_note(self):
|
|
63
|
+
# The FEAT-2026-0100/T03 shape: the attempt edits one tracked file and
|
|
64
|
+
# creates the test module that actually breaks the suite.
|
|
65
|
+
(self.repo / "tracked.py").write_text("edited\n")
|
|
66
|
+
(self.repo / "new_test.py").write_text("SENTINEL_CREATED_CONTENT = 1\n")
|
|
67
|
+
|
|
68
|
+
out = loop.capture_working_tree_diff(self.head_before)
|
|
69
|
+
|
|
70
|
+
self.assertIn("tracked.py", out, "the tracked diff must still be there")
|
|
71
|
+
self.assertIn(
|
|
72
|
+
"new_test.py", out,
|
|
73
|
+
"a file the attempt CREATED is exactly what the note was missing "
|
|
74
|
+
"when FEAT-2026-0100/T03 spun twice (#3249)")
|
|
75
|
+
self.assertIn(
|
|
76
|
+
"SENTINEL_CREATED_CONTENT", out,
|
|
77
|
+
"naming the file is not enough — the note has to carry what the "
|
|
78
|
+
"file says, or it still cannot be diagnosed from the artifacts")
|
|
79
|
+
|
|
80
|
+
def test_gitignored_paths_stay_out(self):
|
|
81
|
+
# work/ holds the notes themselves; folding them into a note would
|
|
82
|
+
# nest each attempt's evidence inside the next one's.
|
|
83
|
+
(self.repo / "work").mkdir()
|
|
84
|
+
(self.repo / "work" / "attempt-1.md").write_text("SHOULD_NOT_APPEAR\n")
|
|
85
|
+
(self.repo / "new_test.py").write_text("kept\n")
|
|
86
|
+
|
|
87
|
+
out = loop.capture_working_tree_diff(self.head_before)
|
|
88
|
+
|
|
89
|
+
self.assertNotIn("SHOULD_NOT_APPEAR", out)
|
|
90
|
+
self.assertIn("new_test.py", out)
|
|
91
|
+
|
|
92
|
+
def test_a_clean_tree_still_returns_empty(self):
|
|
93
|
+
self.assertEqual("", loop.capture_working_tree_diff(self.head_before))
|
|
94
|
+
|
|
95
|
+
def test_the_cap_still_bounds_the_note(self):
|
|
96
|
+
(self.repo / "big_new.py").write_text("x" * 50_000)
|
|
97
|
+
out = loop.capture_working_tree_diff(self.head_before, max_chars=2_000)
|
|
98
|
+
self.assertLess(
|
|
99
|
+
len(out), 4_000,
|
|
100
|
+
"an untracked file must not escape the cap that keeps a committed "
|
|
101
|
+
"note from bloating")
|
|
102
|
+
|
|
103
|
+
def test_a_large_tracked_diff_does_not_squeeze_out_the_created_file(self):
|
|
104
|
+
"""The regression that would reintroduce the bug at a different size.
|
|
105
|
+
|
|
106
|
+
Truncating a concatenation would let a big tracked diff consume the
|
|
107
|
+
whole budget, and the created file — the thing this fix exists to
|
|
108
|
+
surface — would vanish again on exactly the large attempts where
|
|
109
|
+
diagnosis matters most.
|
|
110
|
+
"""
|
|
111
|
+
(self.repo / "tracked.py").write_text("y" * 40_000)
|
|
112
|
+
(self.repo / "new_test.py").write_text("SENTINEL_CREATED_CONTENT = 1\n")
|
|
113
|
+
|
|
114
|
+
out = loop.capture_working_tree_diff(self.head_before, max_chars=4_000)
|
|
115
|
+
|
|
116
|
+
self.assertIn("SENTINEL_CREATED_CONTENT", out)
|
|
117
|
+
|
|
118
|
+
def test_a_binary_file_is_named_but_not_inlined(self):
|
|
119
|
+
(self.repo / "blob.bin").write_bytes(b"\x00\x01\x02BINARY\x00")
|
|
120
|
+
out = loop.capture_working_tree_diff(self.head_before)
|
|
121
|
+
self.assertIn("blob.bin", out)
|
|
122
|
+
self.assertNotIn("BINARY", out)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
unittest.main()
|
|
@@ -28,6 +28,15 @@ import unittest
|
|
|
28
28
|
REPO_ROOT = pathlib.Path(__file__).parent.parent
|
|
29
29
|
DOCS = REPO_ROOT / "docs"
|
|
30
30
|
WU_TEMPLATE = REPO_ROOT / ".specfuse" / "templates" / "WU.template.md"
|
|
31
|
+
RULES = REPO_ROOT / ".specfuse" / "rules"
|
|
32
|
+
SKILLS = REPO_ROOT / ".specfuse" / "skills"
|
|
33
|
+
|
|
34
|
+
# Slash commands the methodology has removed. A retired command may still be
|
|
35
|
+
# named in a provenance blockquote — that is history — but never in a live
|
|
36
|
+
# instruction. Add a line here when a command is retired (#3241).
|
|
37
|
+
RETIRED_COMMANDS = (
|
|
38
|
+
"/accept-hedged-close", # removed by FEAT-2026-0085, shipped in 0.15.0
|
|
39
|
+
)
|
|
31
40
|
|
|
32
41
|
# Markdown inline link with a relative path target (skips absolute URLs and
|
|
33
42
|
# pure-anchor links). Captures the path portion, dropping any `#anchor`.
|
|
@@ -74,6 +83,41 @@ class TestScaffoldDocHygiene(unittest.TestCase):
|
|
|
74
83
|
"that trips the Markdown parser — use ' - ' instead",
|
|
75
84
|
)
|
|
76
85
|
|
|
86
|
+
def test_no_live_instruction_cites_a_retired_command(self):
|
|
87
|
+
"""A retired slash command may be named in HISTORY, never in an
|
|
88
|
+
instruction an agent is expected to follow (#3241).
|
|
89
|
+
|
|
90
|
+
`operator-escalation.md` told the reader that a field recording why a
|
|
91
|
+
human accepted something is "`/accept-hedged-close`'s reason line" —
|
|
92
|
+
for a command FEAT-2026-0085 removed in 0.15.0. An agent following
|
|
93
|
+
that looks for a reason line it can never find. The rule shipped in
|
|
94
|
+
the packaged scaffold, so every consumer read it.
|
|
95
|
+
|
|
96
|
+
Provenance blocks are exempt by design: they record what a past
|
|
97
|
+
feature actually did, and rewriting them to erase a command that did
|
|
98
|
+
once exist would be its own defect. The discriminator is the
|
|
99
|
+
blockquote — a `>`-prefixed line is history, anything else is a live
|
|
100
|
+
instruction. Same reasoning `closing_requirements.py` applies to the
|
|
101
|
+
deliberately-unused requirement ID between `close-i` and `close-k`.
|
|
102
|
+
"""
|
|
103
|
+
offenders: list[str] = []
|
|
104
|
+
for md in sorted(RULES.rglob("*.md")) + sorted(SKILLS.rglob("SKILL.md")):
|
|
105
|
+
for lineno, line in enumerate(
|
|
106
|
+
md.read_text(encoding="utf-8").splitlines(), start=1):
|
|
107
|
+
if line.lstrip().startswith(">"):
|
|
108
|
+
continue # provenance, not instruction
|
|
109
|
+
for retired in RETIRED_COMMANDS:
|
|
110
|
+
if retired in line:
|
|
111
|
+
rel = md.relative_to(REPO_ROOT)
|
|
112
|
+
offenders.append(f"{rel}:{lineno}: {retired} — {line.strip()}")
|
|
113
|
+
self.assertEqual(
|
|
114
|
+
[], offenders,
|
|
115
|
+
"these live instructions cite a command that no longer exists;\n"
|
|
116
|
+
"name a surface that still exists, or move the mention into a\n"
|
|
117
|
+
"provenance blockquote if it is recording history:\n "
|
|
118
|
+
+ "\n ".join(offenders),
|
|
119
|
+
)
|
|
120
|
+
|
|
77
121
|
|
|
78
122
|
if __name__ == "__main__":
|
|
79
123
|
unittest.main()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.17.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/concepts/adopting-auto-mode.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/docs/concepts/ralph-lineage.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/monitoring-secrets-checklist.md
RENAMED
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/monitoring.overrides.yml.example
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/design-for-diagnosis.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/planning-discipline.md
RENAMED
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/security-boundaries.md
RENAMED
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/rules/verification-discipline.md
RENAMED
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/schemas/driver-event.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/templates/DECISIONS.template.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfuse_loop-0.17.0 → specfuse_loop-0.18.0}/specfuse/loop/data/workflows/specfuse-monitor.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|