@event4u/agent-config 1.13.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent-src/commands/agent-handoff.md +4 -1
- package/.agent-src/commands/agent-status.md +3 -0
- package/.agent-src/commands/agents-audit.md +4 -0
- package/.agent-src/commands/agents-cleanup.md +6 -1
- package/.agent-src/commands/agents-prepare.md +3 -0
- package/.agent-src/commands/analyze-reference-repo.md +4 -0
- package/.agent-src/commands/bug-fix.md +7 -3
- package/.agent-src/commands/bug-investigate.md +4 -0
- package/.agent-src/commands/chat-history-checkpoint.md +126 -0
- package/.agent-src/commands/chat-history-clear.md +6 -1
- package/.agent-src/commands/chat-history-resume.md +7 -2
- package/.agent-src/commands/chat-history.md +7 -2
- package/.agent-src/commands/check-current-md.md +137 -0
- package/.agent-src/commands/commit-in-chunks.md +118 -0
- package/.agent-src/commands/commit.md +4 -0
- package/.agent-src/commands/compress.md +37 -2
- package/.agent-src/commands/context-create.md +4 -0
- package/.agent-src/commands/context-refactor.md +4 -0
- package/.agent-src/commands/copilot-agents-init.md +3 -0
- package/.agent-src/commands/copilot-agents-optimize.md +3 -0
- package/.agent-src/commands/create-pr-description.md +4 -0
- package/.agent-src/commands/create-pr.md +4 -0
- package/.agent-src/commands/do-and-judge.md +4 -1
- package/.agent-src/commands/do-in-steps.md +3 -0
- package/.agent-src/commands/e2e-heal.md +4 -0
- package/.agent-src/commands/e2e-plan.md +4 -0
- package/.agent-src/commands/estimate-ticket.md +4 -1
- package/.agent-src/commands/feature-dev.md +4 -0
- package/.agent-src/commands/feature-explore.md +4 -0
- package/.agent-src/commands/feature-plan.md +4 -0
- package/.agent-src/commands/feature-refactor.md +4 -0
- package/.agent-src/commands/feature-roadmap.md +6 -0
- package/.agent-src/commands/fix-ci.md +4 -0
- package/.agent-src/commands/fix-portability.md +5 -2
- package/.agent-src/commands/fix-pr-bot-comments.md +4 -0
- package/.agent-src/commands/fix-pr-comments.md +4 -0
- package/.agent-src/commands/fix-pr-developer-comments.md +4 -0
- package/.agent-src/commands/fix-references.md +3 -0
- package/.agent-src/commands/fix-seeder.md +4 -0
- package/.agent-src/commands/implement-ticket.md +39 -13
- package/.agent-src/commands/jira-ticket.md +4 -0
- package/.agent-src/commands/judge.md +3 -0
- package/.agent-src/commands/memory-add.md +5 -3
- package/.agent-src/commands/memory-full.md +5 -2
- package/.agent-src/commands/memory-promote.md +7 -6
- package/.agent-src/commands/mode.md +3 -0
- package/.agent-src/commands/module-create.md +4 -0
- package/.agent-src/commands/module-explore.md +4 -0
- package/.agent-src/commands/onboard.md +33 -0
- package/.agent-src/commands/optimize-agents.md +4 -0
- package/.agent-src/commands/optimize-augmentignore.md +12 -0
- package/.agent-src/commands/optimize-rtk-filters.md +3 -0
- package/.agent-src/commands/optimize-skills.md +4 -0
- package/.agent-src/commands/override-create.md +4 -0
- package/.agent-src/commands/override-manage.md +4 -0
- package/.agent-src/commands/package-reset.md +3 -0
- package/.agent-src/commands/package-test.md +3 -0
- package/.agent-src/commands/prepare-for-review.md +4 -0
- package/.agent-src/commands/project-analyze.md +4 -0
- package/.agent-src/commands/project-health.md +4 -0
- package/.agent-src/commands/propose-memory.md +6 -8
- package/.agent-src/commands/quality-fix.md +4 -0
- package/.agent-src/commands/refine-ticket.md +12 -7
- package/.agent-src/commands/review-changes.md +39 -8
- package/.agent-src/commands/review-routing.md +4 -0
- package/.agent-src/commands/roadmap-create.md +18 -0
- package/.agent-src/commands/roadmap-execute.md +14 -1
- package/.agent-src/commands/rule-compliance-audit.md +4 -0
- package/.agent-src/commands/set-cost-profile.md +11 -0
- package/.agent-src/commands/sync-agent-settings.md +12 -0
- package/.agent-src/commands/sync-gitignore.md +3 -0
- package/.agent-src/commands/tests-create.md +4 -0
- package/.agent-src/commands/tests-execute.md +6 -3
- package/.agent-src/commands/threat-model.md +4 -0
- package/.agent-src/commands/update-form-request-messages.md +4 -0
- package/.agent-src/commands/upstream-contribute.md +4 -0
- package/.agent-src/commands/work.md +161 -0
- package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +2 -6
- package/.agent-src/guidelines/agent-infra/layered-settings.md +0 -1
- package/.agent-src/guidelines/agent-infra/memory-access.md +0 -7
- package/.agent-src/guidelines/agent-infra/role-contracts.md +2 -4
- package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +0 -1
- package/.agent-src/guidelines/php/patterns/strategy.md +180 -2
- package/.agent-src/personas/README.md +0 -1
- package/.agent-src/rules/artifact-drafting-protocol.md +7 -2
- package/.agent-src/rules/artifact-engagement-recording.md +133 -0
- package/.agent-src/rules/ask-when-uncertain.md +18 -13
- package/.agent-src/rules/augment-portability.md +64 -37
- package/.agent-src/rules/autonomous-execution.md +158 -0
- package/.agent-src/rules/chat-history-cadence.md +109 -0
- package/.agent-src/rules/chat-history-ownership.md +123 -0
- package/.agent-src/rules/chat-history-visibility.md +96 -0
- package/.agent-src/rules/cli-output-handling.md +27 -4
- package/.agent-src/rules/command-suggestion.md +134 -0
- package/.agent-src/rules/commit-policy.md +109 -0
- package/.agent-src/rules/direct-answers.md +114 -0
- package/.agent-src/rules/docs-sync.md +36 -0
- package/.agent-src/rules/downstream-changes.md +10 -9
- package/.agent-src/rules/improve-before-implement.md +9 -6
- package/.agent-src/rules/language-and-tone.md +85 -6
- package/.agent-src/rules/non-destructive-by-default.md +117 -0
- package/.agent-src/rules/package-ci-checks.md +4 -0
- package/.agent-src/rules/preservation-guard.md +20 -0
- package/.agent-src/rules/roadmap-progress-sync.md +159 -27
- package/.agent-src/rules/role-mode-adherence.md +1 -1
- package/.agent-src/rules/scope-control.md +42 -1
- package/.agent-src/rules/size-enforcement.md +2 -3
- package/.agent-src/rules/skill-quality.md +3 -8
- package/.agent-src/rules/ui-audit-before-build.md +106 -0
- package/.agent-src/rules/user-interaction.md +107 -51
- package/.agent-src/scripts/update_roadmap_progress.py +73 -9
- package/.agent-src/skills/blade-ui/SKILL.md +47 -3
- package/.agent-src/skills/command-routing/SKILL.md +32 -0
- package/.agent-src/skills/command-writing/SKILL.md +52 -2
- package/.agent-src/skills/description-assist/SKILL.md +21 -0
- package/.agent-src/skills/estimate-ticket/SKILL.md +0 -1
- package/.agent-src/skills/existing-ui-audit/SKILL.md +202 -0
- package/.agent-src/skills/fe-design/SKILL.md +78 -61
- package/.agent-src/skills/file-editor/SKILL.md +9 -0
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +4 -0
- package/.agent-src/skills/flux/SKILL.md +31 -4
- package/.agent-src/skills/guideline-writing/SKILL.md +24 -2
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +51 -9
- package/.agent-src/skills/livewire/SKILL.md +49 -4
- package/.agent-src/skills/md-language-check/SKILL.md +103 -0
- package/.agent-src/skills/php-coder/SKILL.md +24 -0
- package/.agent-src/skills/react-shadcn-ui/SKILL.md +121 -0
- package/.agent-src/skills/refine-prompt/SKILL.md +220 -0
- package/.agent-src/skills/refine-ticket/SKILL.md +32 -28
- package/.agent-src/skills/roadmap-management/SKILL.md +24 -11
- package/.agent-src/skills/rule-writing/SKILL.md +23 -1
- package/.agent-src/skills/skill-writing/SKILL.md +3 -5
- package/.agent-src/skills/upstream-contribute/SKILL.md +3 -3
- package/.agent-src/skills/using-git-worktrees/SKILL.md +3 -1
- package/.agent-src/templates/AGENTS.md +24 -6
- package/.agent-src/templates/agent-settings.md +149 -0
- package/.agent-src/templates/roadmaps.md +11 -4
- package/.agent-src/templates/scripts/implement_ticket/__init__.py +63 -26
- package/.agent-src/templates/scripts/implement_ticket/__main__.py +8 -2
- package/.agent-src/templates/scripts/memory_lookup.py +1 -1
- package/.agent-src/templates/scripts/telemetry/__init__.py +42 -0
- package/.agent-src/templates/scripts/telemetry/aggregator.py +154 -0
- package/.agent-src/templates/scripts/telemetry/boundary.py +171 -0
- package/.agent-src/templates/scripts/telemetry/engagement.py +238 -0
- package/.agent-src/templates/scripts/telemetry/report_renderer.py +170 -0
- package/.agent-src/templates/scripts/telemetry/settings.py +112 -0
- package/.agent-src/templates/scripts/telemetry_record.py +166 -0
- package/.agent-src/templates/scripts/telemetry_report.py +161 -0
- package/.agent-src/templates/scripts/telemetry_status.py +142 -0
- package/.agent-src/templates/scripts/work_engine/__init__.py +58 -0
- package/.agent-src/templates/scripts/work_engine/__main__.py +9 -0
- package/.agent-src/templates/scripts/work_engine/cli.py +195 -0
- package/.agent-src/templates/scripts/work_engine/cli_args.py +116 -0
- package/.agent-src/templates/scripts/{implement_ticket → work_engine}/delivery_state.py +10 -3
- package/.agent-src/templates/scripts/work_engine/directives/__init__.py +33 -0
- package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +98 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/analyze.py +1 -1
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/implement.py +3 -3
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/memory.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/plan.py +2 -2
- package/.agent-src/templates/scripts/work_engine/directives/backend/refine.py +396 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/report.py +37 -5
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/test.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/verify.py +2 -2
- package/.agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +116 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/contract.py +254 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +229 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/ui.py +231 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/__init__.py +113 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +44 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/apply.py +241 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/audit.py +414 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/design.py +335 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/polish.py +510 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/review.py +468 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +119 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +37 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +165 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +66 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +62 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +115 -0
- package/.agent-src/templates/scripts/work_engine/dispatcher.py +331 -0
- package/.agent-src/templates/scripts/work_engine/emitters.py +43 -0
- package/.agent-src/templates/scripts/work_engine/errors.py +19 -0
- package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +76 -0
- package/.agent-src/templates/scripts/work_engine/hooks/__init__.py +54 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +32 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +103 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +42 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_heartbeat.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_turn_check.py +49 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +53 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +52 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +84 -0
- package/.agent-src/templates/scripts/work_engine/hooks/context.py +66 -0
- package/.agent-src/templates/scripts/work_engine/hooks/events.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/exceptions.py +79 -0
- package/.agent-src/templates/scripts/work_engine/hooks/registry.py +60 -0
- package/.agent-src/templates/scripts/work_engine/hooks/runner.py +73 -0
- package/.agent-src/templates/scripts/work_engine/hooks/settings.py +141 -0
- package/.agent-src/templates/scripts/work_engine/input_builders.py +163 -0
- package/.agent-src/templates/scripts/work_engine/intent/__init__.py +47 -0
- package/.agent-src/templates/scripts/work_engine/intent/classify.py +280 -0
- package/.agent-src/templates/scripts/work_engine/migration/__init__.py +8 -0
- package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +231 -0
- package/.agent-src/templates/scripts/{implement_ticket → work_engine}/persona_policy.py +1 -1
- package/.agent-src/templates/scripts/work_engine/resolvers/__init__.py +22 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/diff.py +106 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/file.py +113 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +90 -0
- package/.agent-src/templates/scripts/work_engine/scoring/__init__.py +14 -0
- package/.agent-src/templates/scripts/work_engine/scoring/confidence.py +300 -0
- package/.agent-src/templates/scripts/work_engine/stack/__init__.py +31 -0
- package/.agent-src/templates/scripts/work_engine/stack/detect.py +187 -0
- package/.agent-src/templates/scripts/work_engine/state.py +641 -0
- package/.agent-src/templates/scripts/work_engine/state_io.py +202 -0
- package/.claude-plugin/marketplace.json +105 -2
- package/AGENTS.md +38 -8
- package/CHANGELOG.md +609 -0
- package/README.md +136 -14
- package/config/agent-settings.template.yml +45 -0
- package/config/gitignore-block.txt +4 -0
- package/docs/MIGRATION.md +122 -0
- package/docs/architecture.md +111 -35
- package/docs/contracts/STABILITY.md +95 -0
- package/docs/contracts/adr-chat-history-split.md +132 -0
- package/docs/contracts/adr-command-suggestion.md +146 -0
- package/docs/contracts/adr-implement-ticket-runtime.md +122 -0
- package/docs/contracts/adr-product-ui-track.md +384 -0
- package/docs/contracts/adr-prompt-driven-execution.md +187 -0
- package/docs/contracts/agent-memory-contract.md +149 -0
- package/docs/contracts/artifact-engagement-flow.md +262 -0
- package/docs/contracts/command-clusters.md +126 -0
- package/docs/contracts/command-suggestion-flow.md +148 -0
- package/docs/contracts/implement-ticket-flow.md +628 -0
- package/docs/contracts/linear-ai-rules-inclusion.md +143 -0
- package/docs/contracts/linear-ai-three-layers.md +131 -0
- package/docs/contracts/rule-interactions.md +107 -0
- package/docs/contracts/rule-interactions.yml +142 -0
- package/docs/contracts/ui-stack-extension.md +236 -0
- package/docs/contracts/ui-track-flow.md +338 -0
- package/docs/development.md +1 -1
- package/docs/getting-started.md +3 -3
- package/docs/installation.md +124 -2
- package/docs/migrations/commands-1.15.0.md +112 -0
- package/docs/showcase.md +204 -0
- package/docs/ui-track-mental-model.md +121 -0
- package/package.json +1 -1
- package/scripts/agent-config +199 -0
- package/scripts/audit_cloud_compatibility.py +288 -0
- package/scripts/build_cloud_bundle.py +458 -0
- package/scripts/build_linear_digest.py +263 -0
- package/scripts/chat_history.py +796 -7
- package/scripts/check_compression.py +139 -0
- package/scripts/check_iron_law_prominence.py +143 -0
- package/scripts/check_md_language.py +159 -0
- package/scripts/check_portability.py +38 -0
- package/scripts/check_public_links.py +185 -0
- package/scripts/check_references.py +1 -0
- package/scripts/check_reply_consistency.py +140 -0
- package/scripts/command_suggester/__init__.py +51 -0
- package/scripts/command_suggester/cooldown.py +132 -0
- package/scripts/command_suggester/loader.py +70 -0
- package/scripts/command_suggester/match.py +180 -0
- package/scripts/command_suggester/rank.py +120 -0
- package/scripts/command_suggester/render.py +86 -0
- package/scripts/command_suggester/sanitize.py +113 -0
- package/scripts/command_suggester/settings.py +125 -0
- package/scripts/command_suggester/types.py +78 -0
- package/scripts/hooks/augment-chat-history.sh +56 -0
- package/scripts/install-hooks.sh +67 -0
- package/scripts/install.py +150 -33
- package/scripts/lint_marketplace.py +27 -0
- package/scripts/lint_no_new_atomic_commands.py +179 -0
- package/scripts/lint_rule_interactions.py +149 -0
- package/scripts/memory_lookup.py +1 -1
- package/scripts/migrate_command_suggestions.py +151 -0
- package/scripts/release.py +297 -64
- package/scripts/schemas/command.schema.json +41 -0
- package/scripts/skill_linter.py +81 -0
- package/scripts/sync_agent_settings.py +42 -12
- package/scripts/update_counts.py +10 -0
- package/templates/consumer-settings/augment-cli-hooks.json +54 -0
- package/templates/consumer-settings/claude-settings.json +55 -1
- package/.agent-src/rules/chat-history.md +0 -171
- package/.agent-src/templates/scripts/implement_ticket/cli.py +0 -171
- package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +0 -134
- package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +0 -49
- package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +0 -140
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""``./agent-config telemetry:status`` — read-only status report.
|
|
3
|
+
|
|
4
|
+
Prints the current ``telemetry.artifact_engagement`` configuration
|
|
5
|
+
plus log statistics. Safe even when telemetry is disabled — never
|
|
6
|
+
creates the log, never validates, never writes. ``--format json`` is
|
|
7
|
+
the machine-readable contract.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from telemetry.engagement import EngagementSchemaError, parse_event
|
|
18
|
+
from telemetry.settings import TelemetrySettings, read_settings
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _last_event_ts(log_path: Path) -> str | None:
|
|
22
|
+
"""Return the ``ts`` of the last well-formed event, or None.
|
|
23
|
+
|
|
24
|
+
Reads from the tail to keep the cost bounded on long logs. We
|
|
25
|
+
skip malformed lines silently — Phase 4 surfaces those via the
|
|
26
|
+
aggregator's ``--strict`` flag.
|
|
27
|
+
"""
|
|
28
|
+
if not log_path.is_file():
|
|
29
|
+
return None
|
|
30
|
+
try:
|
|
31
|
+
with log_path.open("rb") as fh:
|
|
32
|
+
fh.seek(0, 2) # EOF
|
|
33
|
+
size = fh.tell()
|
|
34
|
+
chunk_size = min(size, 4096)
|
|
35
|
+
fh.seek(size - chunk_size)
|
|
36
|
+
tail = fh.read().decode("utf-8", errors="replace")
|
|
37
|
+
except OSError:
|
|
38
|
+
return None
|
|
39
|
+
for line in reversed(tail.splitlines()):
|
|
40
|
+
line = line.strip()
|
|
41
|
+
if not line:
|
|
42
|
+
continue
|
|
43
|
+
try:
|
|
44
|
+
event = parse_event(line + "\n")
|
|
45
|
+
except EngagementSchemaError:
|
|
46
|
+
continue
|
|
47
|
+
return event.ts
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _log_stats(log_path: Path) -> dict[str, Any]:
|
|
52
|
+
if not log_path.is_file():
|
|
53
|
+
return {"exists": False, "size_bytes": 0, "line_count": 0}
|
|
54
|
+
try:
|
|
55
|
+
size = log_path.stat().st_size
|
|
56
|
+
with log_path.open("rb") as fh:
|
|
57
|
+
line_count = sum(1 for _ in fh)
|
|
58
|
+
except OSError as exc:
|
|
59
|
+
return {"exists": True, "error": str(exc)}
|
|
60
|
+
return {"exists": True, "size_bytes": size, "line_count": line_count}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _build_report(settings: TelemetrySettings) -> dict[str, Any]:
|
|
64
|
+
log_path = settings.log_path
|
|
65
|
+
return {
|
|
66
|
+
"enabled": settings.enabled,
|
|
67
|
+
"section_present": settings.section_present,
|
|
68
|
+
"granularity": settings.granularity,
|
|
69
|
+
"record": {
|
|
70
|
+
"consulted": settings.record_consulted,
|
|
71
|
+
"applied": settings.record_applied,
|
|
72
|
+
},
|
|
73
|
+
"log": {
|
|
74
|
+
"path": str(log_path),
|
|
75
|
+
**_log_stats(log_path),
|
|
76
|
+
"last_event_ts": _last_event_ts(log_path),
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _render_text(report: dict[str, Any]) -> str:
|
|
82
|
+
lines: list[str] = []
|
|
83
|
+
enabled = "✅ enabled" if report["enabled"] else "⛔ disabled"
|
|
84
|
+
if not report["section_present"]:
|
|
85
|
+
enabled += " (no telemetry section in .agent-settings.yml — using defaults)"
|
|
86
|
+
lines.append(f" artifact-engagement: {enabled}")
|
|
87
|
+
lines.append(f" granularity: {report['granularity']}")
|
|
88
|
+
rec = report["record"]
|
|
89
|
+
lines.append(
|
|
90
|
+
f" record: consulted={rec['consulted']} "
|
|
91
|
+
f"applied={rec['applied']}"
|
|
92
|
+
)
|
|
93
|
+
log = report["log"]
|
|
94
|
+
lines.append(f" log path: {log['path']}")
|
|
95
|
+
if log.get("exists"):
|
|
96
|
+
if "error" in log:
|
|
97
|
+
lines.append(f" log error: {log['error']}")
|
|
98
|
+
else:
|
|
99
|
+
lines.append(
|
|
100
|
+
f" log size: {log['size_bytes']} bytes "
|
|
101
|
+
f"({log['line_count']} events)"
|
|
102
|
+
)
|
|
103
|
+
if log.get("last_event_ts"):
|
|
104
|
+
lines.append(f" last event ts: {log['last_event_ts']}")
|
|
105
|
+
else:
|
|
106
|
+
lines.append(" log: not yet created")
|
|
107
|
+
return "\n".join(lines)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def main(argv: list[str] | None = None) -> int:
|
|
111
|
+
parser = argparse.ArgumentParser(
|
|
112
|
+
prog="agent-config telemetry:status",
|
|
113
|
+
description=(
|
|
114
|
+
"Print the artifact-engagement telemetry status. Read-only "
|
|
115
|
+
"— never creates the log, never modifies settings."
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
parser.add_argument("--format", choices=("text", "json"), default="text")
|
|
119
|
+
parser.add_argument(
|
|
120
|
+
"--settings",
|
|
121
|
+
type=Path,
|
|
122
|
+
default=Path(".agent-settings.yml"),
|
|
123
|
+
help="Override settings path (tests).",
|
|
124
|
+
)
|
|
125
|
+
args = parser.parse_args(argv)
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
settings = read_settings(args.settings)
|
|
129
|
+
except OSError as exc:
|
|
130
|
+
print(f"❌ cannot read settings: {exc}", file=sys.stderr)
|
|
131
|
+
return 2
|
|
132
|
+
|
|
133
|
+
report = _build_report(settings)
|
|
134
|
+
if args.format == "json":
|
|
135
|
+
print(json.dumps(report, sort_keys=True, indent=2))
|
|
136
|
+
else:
|
|
137
|
+
print(_render_text(report))
|
|
138
|
+
return 0
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""``work_engine`` — universal execution engine (R1).
|
|
2
|
+
|
|
3
|
+
The package owns the linear step dispatcher that drives
|
|
4
|
+
``/implement-ticket`` and any future intent-routed flow. Phase 2 added
|
|
5
|
+
the persistent ``state`` schema and the v0→v1 migration; Phase 3 moves
|
|
6
|
+
the dispatcher, CLI and step modules over from the legacy
|
|
7
|
+
``implement_ticket`` package — which is now a thin compatibility shim
|
|
8
|
+
that re-exports from here with a ``DeprecationWarning``.
|
|
9
|
+
|
|
10
|
+
Architectural constraints (from
|
|
11
|
+
``docs/contracts/adr-implement-ticket-runtime.md`` and
|
|
12
|
+
``docs/contracts/implement-ticket-flow.md``):
|
|
13
|
+
|
|
14
|
+
- Runtime is Python 3.10+.
|
|
15
|
+
- The dispatcher is linear, not a DAG. Eight fixed steps, fixed order.
|
|
16
|
+
- ``DeliveryState`` is the only object shared between steps — no
|
|
17
|
+
hidden state, no side channels.
|
|
18
|
+
- Every step terminates in ``success | blocked | partial``. ``blocked``
|
|
19
|
+
and ``partial`` halt the flow and surface numbered questions.
|
|
20
|
+
- The dispatcher never calls git, writes commits, or opens PRs.
|
|
21
|
+
"""
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from .delivery_state import (
|
|
25
|
+
AGENT_DIRECTIVE_PREFIX,
|
|
26
|
+
DeliveryState,
|
|
27
|
+
Outcome,
|
|
28
|
+
Step,
|
|
29
|
+
StepResult,
|
|
30
|
+
agent_directive,
|
|
31
|
+
is_agent_directive,
|
|
32
|
+
)
|
|
33
|
+
from .cli import DEFAULT_STATE_FILE, main
|
|
34
|
+
from .dispatcher import STEP_ORDER, dispatch
|
|
35
|
+
from .persona_policy import (
|
|
36
|
+
DEFAULT_PERSONA,
|
|
37
|
+
PersonaPolicy,
|
|
38
|
+
known_personas,
|
|
39
|
+
resolve_policy,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
"AGENT_DIRECTIVE_PREFIX",
|
|
44
|
+
"DEFAULT_PERSONA",
|
|
45
|
+
"DEFAULT_STATE_FILE",
|
|
46
|
+
"DeliveryState",
|
|
47
|
+
"Outcome",
|
|
48
|
+
"PersonaPolicy",
|
|
49
|
+
"STEP_ORDER",
|
|
50
|
+
"Step",
|
|
51
|
+
"StepResult",
|
|
52
|
+
"agent_directive",
|
|
53
|
+
"dispatch",
|
|
54
|
+
"is_agent_directive",
|
|
55
|
+
"known_personas",
|
|
56
|
+
"main",
|
|
57
|
+
"resolve_policy",
|
|
58
|
+
]
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""Command-line entry point for ``/implement-ticket``.
|
|
2
|
+
|
|
3
|
+
Minimal Option-A transport: the script loads a persisted state file,
|
|
4
|
+
runs the dispatcher once, writes the updated state back, and prints
|
|
5
|
+
either the delivery report (on SUCCESS) or the halt surface —
|
|
6
|
+
directive plus numbered questions — on BLOCKED/PARTIAL.
|
|
7
|
+
|
|
8
|
+
The script never edits code, runs tests, or opens pull requests.
|
|
9
|
+
All of that is delegated to the agent via ``@agent-directive:``
|
|
10
|
+
markers per
|
|
11
|
+
``docs/contracts/implement-ticket-flow.md#agent-directives``. The
|
|
12
|
+
agent executes the directive, writes the resulting slice back to
|
|
13
|
+
the state file, and re-invokes this script to resume.
|
|
14
|
+
|
|
15
|
+
Wire format (R1 P4 S1, Option A2): the CLI accepts both the legacy
|
|
16
|
+
v0 wire format (``{"ticket": …, "persona": …}``) and the v1 schema
|
|
17
|
+
(``{"version": 1, "input": {"kind": "ticket", "data": …}}``). Loaded
|
|
18
|
+
state is wrapped in :class:`work_engine.state.WorkState` for the
|
|
19
|
+
boundary; before dispatch it is projected into a ``DeliveryState``
|
|
20
|
+
the step handlers understand. After dispatch the mutations are
|
|
21
|
+
mirrored back, and the file is rewritten in the **same** wire format
|
|
22
|
+
it was loaded with — Goldens captured against v0 stay v0 byte-for-
|
|
23
|
+
byte, while flows that already store v1 round-trip as v1.
|
|
24
|
+
|
|
25
|
+
Layout (post P2.3 of ``road-to-post-pr29-optimize.md``): this file
|
|
26
|
+
is a thin orchestrator. The argument parser, state I/O, file-input
|
|
27
|
+
builders, hook bootstrap, and stdout/stderr emitters live in their
|
|
28
|
+
own leaf modules under ``work_engine`` — see ``cli_args``,
|
|
29
|
+
``state_io``, ``input_builders``, ``hook_bootstrap``, ``emitters``,
|
|
30
|
+
``errors``. Public names (``main``, ``DEFAULT_STATE_FILE``) and the
|
|
31
|
+
private monkeypatch surface (``_build_hook_registry``,
|
|
32
|
+
``_CLIError``, ``_load_or_build``, …) are re-exported here so
|
|
33
|
+
existing imports and patch targets continue to resolve.
|
|
34
|
+
|
|
35
|
+
Exit codes:
|
|
36
|
+
|
|
37
|
+
- ``0`` — flow reached SUCCESS; ``state.report`` printed.
|
|
38
|
+
- ``1`` — flow halted BLOCKED; halt surface printed on stdout, the
|
|
39
|
+
state file carries the updated ``outcomes`` and ``questions`` so
|
|
40
|
+
the agent can resume.
|
|
41
|
+
- ``2`` — argument or I/O error (ticket file missing, JSON parse
|
|
42
|
+
failure, etc.). The state file is *not* written in this case.
|
|
43
|
+
"""
|
|
44
|
+
from __future__ import annotations
|
|
45
|
+
|
|
46
|
+
import sys
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
from typing import Sequence
|
|
49
|
+
|
|
50
|
+
from .cli_args import (
|
|
51
|
+
DEFAULT_STATE_FILE,
|
|
52
|
+
LEGACY_STATE_FILE,
|
|
53
|
+
_build_parser,
|
|
54
|
+
_FMT_V0,
|
|
55
|
+
_FMT_V1,
|
|
56
|
+
)
|
|
57
|
+
from .delivery_state import Outcome
|
|
58
|
+
from .dispatcher import (
|
|
59
|
+
assert_kind_supported,
|
|
60
|
+
dispatch,
|
|
61
|
+
load_directive_set,
|
|
62
|
+
select_directive_set,
|
|
63
|
+
)
|
|
64
|
+
from .emitters import _emit, _emit_halt
|
|
65
|
+
from .errors import _CLIError
|
|
66
|
+
from .hook_bootstrap import _build_hook_registry, _register_chat_history_hooks
|
|
67
|
+
from .hooks import HookContext, HookEvent, HookRunner
|
|
68
|
+
from .input_builders import (
|
|
69
|
+
_build_from_diff_file,
|
|
70
|
+
_build_from_file_file,
|
|
71
|
+
_build_from_prompt_file,
|
|
72
|
+
_load_or_build,
|
|
73
|
+
)
|
|
74
|
+
from .state_io import (
|
|
75
|
+
_load,
|
|
76
|
+
_maybe_raise_legacy_hint,
|
|
77
|
+
_read_json,
|
|
78
|
+
_save,
|
|
79
|
+
_sync_back,
|
|
80
|
+
_to_delivery,
|
|
81
|
+
_to_v0_dict,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
86
|
+
"""Run one dispatch cycle against the persisted state.
|
|
87
|
+
|
|
88
|
+
``argv`` is taken as-is; pass ``None`` to fall back to
|
|
89
|
+
``sys.argv[1:]`` (the usual entry-point contract).
|
|
90
|
+
"""
|
|
91
|
+
parser = _build_parser()
|
|
92
|
+
args = parser.parse_args(argv)
|
|
93
|
+
state_file: Path = args.state_file
|
|
94
|
+
|
|
95
|
+
runner = HookRunner(_build_hook_registry(args))
|
|
96
|
+
|
|
97
|
+
halt = runner.emit(
|
|
98
|
+
HookEvent.BEFORE_LOAD,
|
|
99
|
+
HookContext(state_file=state_file, args=args),
|
|
100
|
+
)
|
|
101
|
+
if halt is not None:
|
|
102
|
+
return _emit_halt(halt)
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
work, fmt = _load_or_build(state_file, args)
|
|
106
|
+
except _CLIError as exc:
|
|
107
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
108
|
+
return 2
|
|
109
|
+
|
|
110
|
+
halt = runner.emit(
|
|
111
|
+
HookEvent.AFTER_LOAD,
|
|
112
|
+
HookContext(state_file=state_file, work=work, fmt=fmt, args=args),
|
|
113
|
+
)
|
|
114
|
+
if halt is not None:
|
|
115
|
+
return _emit_halt(halt)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
set_name = select_directive_set(work)
|
|
119
|
+
assert_kind_supported(work.input.kind, set_name)
|
|
120
|
+
steps = load_directive_set(set_name)
|
|
121
|
+
except (ValueError, NotImplementedError) as exc:
|
|
122
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
123
|
+
return 2
|
|
124
|
+
|
|
125
|
+
delivery = _to_delivery(work)
|
|
126
|
+
|
|
127
|
+
halt = runner.emit(
|
|
128
|
+
HookEvent.BEFORE_DISPATCH,
|
|
129
|
+
HookContext(work=work, delivery=delivery, set_name=set_name, args=args),
|
|
130
|
+
)
|
|
131
|
+
if halt is not None:
|
|
132
|
+
return _emit_halt(halt)
|
|
133
|
+
|
|
134
|
+
final, halting = dispatch(delivery, steps, hooks=runner)
|
|
135
|
+
|
|
136
|
+
halt = runner.emit(
|
|
137
|
+
HookEvent.AFTER_DISPATCH,
|
|
138
|
+
HookContext(
|
|
139
|
+
work=work,
|
|
140
|
+
delivery=delivery,
|
|
141
|
+
final=final,
|
|
142
|
+
halting=halting,
|
|
143
|
+
args=args,
|
|
144
|
+
),
|
|
145
|
+
)
|
|
146
|
+
if halt is not None:
|
|
147
|
+
return _emit_halt(halt)
|
|
148
|
+
|
|
149
|
+
_sync_back(work, delivery)
|
|
150
|
+
|
|
151
|
+
halt = runner.emit(
|
|
152
|
+
HookEvent.BEFORE_SAVE,
|
|
153
|
+
HookContext(work=work, delivery=delivery, fmt=fmt, args=args),
|
|
154
|
+
)
|
|
155
|
+
if halt is not None:
|
|
156
|
+
return _emit_halt(halt)
|
|
157
|
+
|
|
158
|
+
_save(state_file, work, fmt)
|
|
159
|
+
|
|
160
|
+
halt = runner.emit(
|
|
161
|
+
HookEvent.AFTER_SAVE,
|
|
162
|
+
HookContext(work=work, state_file=state_file, fmt=fmt, args=args),
|
|
163
|
+
)
|
|
164
|
+
if halt is not None:
|
|
165
|
+
# State is already on disk; exit 2 still per the P3 branch table.
|
|
166
|
+
return _emit_halt(halt)
|
|
167
|
+
|
|
168
|
+
_emit(work, final, halting)
|
|
169
|
+
return 0 if final is Outcome.SUCCESS else 1
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
__all__ = [
|
|
173
|
+
"DEFAULT_STATE_FILE",
|
|
174
|
+
"LEGACY_STATE_FILE",
|
|
175
|
+
"_CLIError",
|
|
176
|
+
"_FMT_V0",
|
|
177
|
+
"_FMT_V1",
|
|
178
|
+
"_build_from_diff_file",
|
|
179
|
+
"_build_from_file_file",
|
|
180
|
+
"_build_from_prompt_file",
|
|
181
|
+
"_build_hook_registry",
|
|
182
|
+
"_build_parser",
|
|
183
|
+
"_emit",
|
|
184
|
+
"_emit_halt",
|
|
185
|
+
"_load",
|
|
186
|
+
"_load_or_build",
|
|
187
|
+
"_maybe_raise_legacy_hint",
|
|
188
|
+
"_read_json",
|
|
189
|
+
"_register_chat_history_hooks",
|
|
190
|
+
"_save",
|
|
191
|
+
"_sync_back",
|
|
192
|
+
"_to_delivery",
|
|
193
|
+
"_to_v0_dict",
|
|
194
|
+
"main",
|
|
195
|
+
]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Argument parser and state-file constants for the CLI entry point.
|
|
2
|
+
|
|
3
|
+
Extracted from ``cli.py`` in P2.3 of
|
|
4
|
+
``road-to-post-pr29-optimize.md``. Behaviour-preserving: the parser
|
|
5
|
+
shape, default values, help strings and exit-code semantics are
|
|
6
|
+
byte-identical to the pre-split version. The constants moved here
|
|
7
|
+
so the parser default and the legacy-file detector both reference
|
|
8
|
+
a single source of truth.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import argparse
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
DEFAULT_STATE_FILE = Path(".work-state.json")
|
|
16
|
+
"""State file used when ``--state-file`` is not passed.
|
|
17
|
+
|
|
18
|
+
Renamed from ``.implement-ticket-state.json`` in 1.15.0 alongside the
|
|
19
|
+
``implement_ticket → work_engine`` package move. The legacy filename is
|
|
20
|
+
still recognised on load (see :data:`LEGACY_STATE_FILE` below) so that
|
|
21
|
+
existing checkouts surface a clear migration message instead of a
|
|
22
|
+
silent "no state file" error."""
|
|
23
|
+
|
|
24
|
+
LEGACY_STATE_FILE = Path(".implement-ticket-state.json")
|
|
25
|
+
"""Pre-1.15.0 default state file. Detected only as a migration hint;
|
|
26
|
+
never written to. See ``docs/MIGRATION.md``."""
|
|
27
|
+
|
|
28
|
+
_FMT_V0 = "v0"
|
|
29
|
+
_FMT_V1 = "v1"
|
|
30
|
+
"""Wire-format markers carried alongside the loaded :class:`WorkState`.
|
|
31
|
+
|
|
32
|
+
Format-preserving roundtrip: ``_load`` records which shape it parsed,
|
|
33
|
+
``_save`` rewrites in that same shape. v0 in → v0 out (Goldens stay
|
|
34
|
+
byte-equal); v1 in → v1 out (future flows produced by the migration
|
|
35
|
+
tool or a fresh v1 init keep their envelope fields)."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
39
|
+
parser = argparse.ArgumentParser(
|
|
40
|
+
prog="implement-ticket",
|
|
41
|
+
description="Run one dispatch cycle of the /implement-ticket flow.",
|
|
42
|
+
)
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"--state-file",
|
|
45
|
+
type=Path,
|
|
46
|
+
default=DEFAULT_STATE_FILE,
|
|
47
|
+
help=f"Path to persisted state JSON (default: {DEFAULT_STATE_FILE}).",
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--ticket-file",
|
|
51
|
+
type=Path,
|
|
52
|
+
default=None,
|
|
53
|
+
help="JSON file carrying the ticket payload; used only when the "
|
|
54
|
+
"state file does not exist yet.",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--prompt-file",
|
|
58
|
+
type=Path,
|
|
59
|
+
default=None,
|
|
60
|
+
help="Plain-text file carrying the raw user prompt; builds an "
|
|
61
|
+
"input.kind='prompt' envelope. Mutually exclusive with "
|
|
62
|
+
"--ticket-file. Used only when the state file does not exist yet.",
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"--diff-file",
|
|
66
|
+
type=Path,
|
|
67
|
+
default=None,
|
|
68
|
+
help="Plain-text file carrying a unified diff payload; builds an "
|
|
69
|
+
"input.kind='diff' envelope routed through the UI-improve "
|
|
70
|
+
"directive set. Mutually exclusive with --ticket-file / "
|
|
71
|
+
"--prompt-file / --file-file. Used only when the state file does "
|
|
72
|
+
"not exist yet.",
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"--file-file",
|
|
76
|
+
type=Path,
|
|
77
|
+
default=None,
|
|
78
|
+
help="Plain-text file carrying a single path reference (one line); "
|
|
79
|
+
"builds an input.kind='file' envelope routed through the UI-improve "
|
|
80
|
+
"directive set. Mutually exclusive with --ticket-file / "
|
|
81
|
+
"--prompt-file / --diff-file. Used only when the state file does "
|
|
82
|
+
"not exist yet.",
|
|
83
|
+
)
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"--persona",
|
|
86
|
+
type=str,
|
|
87
|
+
default=None,
|
|
88
|
+
help="Persona name (senior-engineer | qa | advisory). Only honoured "
|
|
89
|
+
"when the state file does not exist yet; ignored on resume so a "
|
|
90
|
+
"mid-flight persona switch cannot silently change behaviour.",
|
|
91
|
+
)
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"--no-hooks",
|
|
94
|
+
action="store_true",
|
|
95
|
+
default=False,
|
|
96
|
+
help="Disable every lifecycle hook for this run. Use in golden-"
|
|
97
|
+
"replay test harnesses so a future settings change cannot "
|
|
98
|
+
"silently invalidate captured outputs.",
|
|
99
|
+
)
|
|
100
|
+
parser.add_argument(
|
|
101
|
+
"--hooks-config",
|
|
102
|
+
type=Path,
|
|
103
|
+
default=None,
|
|
104
|
+
help="Override the path to the agent-settings file used to resolve "
|
|
105
|
+
"the hooks.* block. Defaults to ./.agent-settings.yml.",
|
|
106
|
+
)
|
|
107
|
+
return parser
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
__all__ = [
|
|
111
|
+
"DEFAULT_STATE_FILE",
|
|
112
|
+
"LEGACY_STATE_FILE",
|
|
113
|
+
"_FMT_V0",
|
|
114
|
+
"_FMT_V1",
|
|
115
|
+
"_build_parser",
|
|
116
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""``DeliveryState`` — the only object shared between orchestrator steps.
|
|
2
2
|
|
|
3
|
-
The shape mirrors ``
|
|
3
|
+
The shape mirrors ``docs/contracts/implement-ticket-flow.md``. No step
|
|
4
4
|
may invent fields not declared here; extensions require a roadmap
|
|
5
5
|
amendment plus a flow-contract update.
|
|
6
6
|
|
|
@@ -59,7 +59,7 @@ class DeliveryState:
|
|
|
59
59
|
"""Canonical state passed between orchestrator steps.
|
|
60
60
|
|
|
61
61
|
Field order matches the table in
|
|
62
|
-
``
|
|
62
|
+
``docs/contracts/implement-ticket-flow.md``. Mutable defaults use
|
|
63
63
|
``field(default_factory=...)`` so every instance owns its own
|
|
64
64
|
containers — a single shared list across runs would be a
|
|
65
65
|
cross-run contamination hazard for the metrics pipeline.
|
|
@@ -75,6 +75,13 @@ class DeliveryState:
|
|
|
75
75
|
outcomes: dict[str, str] = field(default_factory=dict)
|
|
76
76
|
questions: list[str] = field(default_factory=list)
|
|
77
77
|
report: str = ""
|
|
78
|
+
ui_audit: dict[str, Any] | None = None
|
|
79
|
+
ui_design: dict[str, Any] | None = None
|
|
80
|
+
ui_review: dict[str, Any] | None = None
|
|
81
|
+
ui_polish: dict[str, Any] | None = None
|
|
82
|
+
contract: dict[str, Any] | None = None
|
|
83
|
+
stitch: dict[str, Any] | None = None
|
|
84
|
+
stack: dict[str, Any] | None = None
|
|
78
85
|
|
|
79
86
|
|
|
80
87
|
Step = Callable[[DeliveryState], StepResult]
|
|
@@ -96,7 +103,7 @@ skill; the user-facing numbered options follow on subsequent lines.
|
|
|
96
103
|
|
|
97
104
|
The prefix is public contract: changing it breaks every agent that
|
|
98
105
|
has learned to recognise it. See
|
|
99
|
-
``
|
|
106
|
+
``docs/contracts/implement-ticket-flow.md#agent-directives``.
|
|
100
107
|
"""
|
|
101
108
|
|
|
102
109
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Directive-set bundles consumed by the dispatcher.
|
|
2
|
+
|
|
3
|
+
A *directive set* is a coherent group of step handlers (refine,
|
|
4
|
+
memory, analyze, plan, implement, test, verify, report) tuned for a
|
|
5
|
+
particular kind of work — backend coding, UI work, mixed front+back
|
|
6
|
+
work, and so on. The dispatcher selects exactly one set per cycle
|
|
7
|
+
(see ``dispatcher.select_directive_set``) and walks its eight steps
|
|
8
|
+
in the canonical order.
|
|
9
|
+
|
|
10
|
+
Each set is a Python sub-package exposing a single function::
|
|
11
|
+
|
|
12
|
+
def get_steps() -> Mapping[str, Step]:
|
|
13
|
+
'''Return the {step_name: handler} mapping the dispatcher walks.'''
|
|
14
|
+
|
|
15
|
+
The mapping must cover every entry in :data:`dispatcher.STEP_ORDER`;
|
|
16
|
+
incomplete bundles raise ``KeyError`` at dispatch time.
|
|
17
|
+
|
|
18
|
+
Roadmap status (R1 Phase 4):
|
|
19
|
+
|
|
20
|
+
- ``backend`` — fully implemented; landing in Step 3 of this phase.
|
|
21
|
+
- ``ui`` — stub; lands in Roadmap 3 (``road-to-product-ui-track.md``).
|
|
22
|
+
- ``ui_trivial`` — stub; lands in Roadmap 3 V2.
|
|
23
|
+
- ``mixed`` — stub; lands in Roadmap 3.
|
|
24
|
+
|
|
25
|
+
The schema (``state.KNOWN_DIRECTIVE_SETS``) carries the *external*
|
|
26
|
+
names ``ui``, ``ui-trivial``, ``mixed``; the directory layout uses
|
|
27
|
+
underscores (``ui_trivial``) because Python packages cannot contain
|
|
28
|
+
hyphens. The dispatcher's loader is the single place that translates
|
|
29
|
+
between the two.
|
|
30
|
+
"""
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
__all__: list[str] = []
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Backend directive set — step handlers for the backend-coding flow.
|
|
2
|
+
|
|
3
|
+
Each module exposes a single ``run`` callable that matches the
|
|
4
|
+
``Step`` protocol defined in ``...delivery_state``. The dispatcher
|
|
5
|
+
wires them into the ``STEP_ORDER`` mapping at call time; nothing in
|
|
6
|
+
this package imports handlers eagerly, so a partial wiring during
|
|
7
|
+
development is caught by the dispatcher's missing-step check rather
|
|
8
|
+
than by an import-time failure.
|
|
9
|
+
|
|
10
|
+
This is the first concrete entry in the
|
|
11
|
+
:mod:`work_engine.directives` package. R1 Phase 4 Step 3 moved the
|
|
12
|
+
handlers here from the original ``work_engine.steps`` location so
|
|
13
|
+
the upcoming generalized dispatcher (Step 2) can select between
|
|
14
|
+
multiple directive sets uniformly via :func:`get_steps`. The
|
|
15
|
+
external behavior — flow order, ambiguity surfaces, halt-points —
|
|
16
|
+
is unchanged.
|
|
17
|
+
|
|
18
|
+
The deterministic gates (``refine``, ``memory``, ``analyze``)
|
|
19
|
+
validate upstream state; the delegation gates (``plan``,
|
|
20
|
+
``implement``, ``test``, ``verify``) halt with
|
|
21
|
+
``@agent-directive:`` markers so the orchestrator can invoke the
|
|
22
|
+
matching skill and resume. ``report`` renders the delivery Markdown
|
|
23
|
+
once everything else has succeeded. See
|
|
24
|
+
``agents/roadmaps/road-to-implement-ticket.md`` for the shipping
|
|
25
|
+
order and ``docs/contracts/implement-ticket-flow.md`` for the
|
|
26
|
+
slice contracts each handler writes to.
|
|
27
|
+
"""
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
from collections.abc import Mapping
|
|
31
|
+
|
|
32
|
+
from ...delivery_state import Step
|
|
33
|
+
from . import analyze, implement, memory, plan, refine, report, test, verify
|
|
34
|
+
|
|
35
|
+
DIRECTIVE_SET_NAME = "backend"
|
|
36
|
+
"""External name carried in ``state.directive_set`` for this set."""
|
|
37
|
+
|
|
38
|
+
SUPPORTED_KINDS: tuple[str, ...] = ("ticket", "prompt")
|
|
39
|
+
"""Input kinds this directive set knows how to handle.
|
|
40
|
+
|
|
41
|
+
Read by :func:`work_engine.dispatcher.assert_kind_supported` before the
|
|
42
|
+
loop starts. The schema's :data:`work_engine.state.KNOWN_INPUT_KINDS` is
|
|
43
|
+
the *envelope* whitelist (what is accepted on disk); ``SUPPORTED_KINDS``
|
|
44
|
+
is the *capability* whitelist (what this set can actually drive end to
|
|
45
|
+
end).
|
|
46
|
+
|
|
47
|
+
R1 only carried ``ticket``. R2 Phase 3 Step 3 added ``prompt`` once the
|
|
48
|
+
``refine`` step learned to detect prompt envelopes (presence of ``raw``
|
|
49
|
+
key in ``state.ticket``), delegate to the ``refine-prompt`` skill on
|
|
50
|
+
the first pass, and route the resulting confidence band into
|
|
51
|
+
``SUCCESS`` / ``PARTIAL`` / ``BLOCKED`` per
|
|
52
|
+
``agents/roadmaps/archive/road-to-prompt-driven-execution.md`` Phase 3."""
|
|
53
|
+
|
|
54
|
+
_STEPS = (refine, memory, analyze, plan, implement, test, verify, report)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def all_ambiguities() -> dict[str, tuple[dict[str, str], ...]]:
|
|
58
|
+
"""Return `{step_name: AMBIGUITIES}` for every step in flow order.
|
|
59
|
+
|
|
60
|
+
Used by documentation generators and the ``test_ambiguity_coverage``
|
|
61
|
+
suite to prove every step explicitly declares what can surface a
|
|
62
|
+
``BLOCKED`` outcome. Steps that always succeed (``memory``,
|
|
63
|
+
``report``) return an empty tuple — declared intent, not an
|
|
64
|
+
omission.
|
|
65
|
+
"""
|
|
66
|
+
return {step.__name__.rsplit(".", 1)[-1]: step.AMBIGUITIES for step in _STEPS}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_steps() -> Mapping[str, Step]:
|
|
70
|
+
"""Return the ``{step_name: handler}`` mapping the dispatcher walks.
|
|
71
|
+
|
|
72
|
+
Each value is the module-level ``run`` callable matching the
|
|
73
|
+
:data:`work_engine.delivery_state.Step` protocol —
|
|
74
|
+
``Callable[[DeliveryState], StepResult]`` — exactly what
|
|
75
|
+
:func:`work_engine.dispatcher.dispatch` calls. Order of insertion
|
|
76
|
+
matches the canonical backend flow (refine → memory → analyze →
|
|
77
|
+
plan → implement → test → verify → report); the dispatcher's own
|
|
78
|
+
``STEP_ORDER`` is the single source of truth for *which* steps
|
|
79
|
+
exist, but the directive set is the single source of truth for
|
|
80
|
+
*how* each one runs.
|
|
81
|
+
"""
|
|
82
|
+
return {step.__name__.rsplit(".", 1)[-1]: step.run for step in _STEPS}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
__all__ = [
|
|
86
|
+
"DIRECTIVE_SET_NAME",
|
|
87
|
+
"SUPPORTED_KINDS",
|
|
88
|
+
"all_ambiguities",
|
|
89
|
+
"analyze",
|
|
90
|
+
"get_steps",
|
|
91
|
+
"implement",
|
|
92
|
+
"memory",
|
|
93
|
+
"plan",
|
|
94
|
+
"refine",
|
|
95
|
+
"report",
|
|
96
|
+
"test",
|
|
97
|
+
"verify",
|
|
98
|
+
]
|