@event4u/agent-config 1.13.0 → 1.14.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 +3 -0
- 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 +5 -1
- 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 +5 -0
- package/.agent-src/commands/chat-history-resume.md +5 -0
- package/.agent-src/commands/chat-history.md +5 -0
- package/.agent-src/commands/check-current-md.md +126 -0
- package/.agent-src/commands/commit-in-chunks.md +98 -0
- package/.agent-src/commands/commit.md +4 -0
- package/.agent-src/commands/compress.md +3 -0
- 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 +3 -0
- 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 +24 -0
- package/.agent-src/commands/optimize-agents.md +4 -0
- package/.agent-src/commands/optimize-augmentignore.md +3 -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 +4 -1
- package/.agent-src/commands/review-changes.md +4 -0
- package/.agent-src/commands/review-routing.md +4 -0
- package/.agent-src/commands/roadmap-create.md +7 -0
- package/.agent-src/commands/roadmap-execute.md +12 -1
- package/.agent-src/commands/rule-compliance-audit.md +4 -0
- package/.agent-src/commands/set-cost-profile.md +3 -0
- package/.agent-src/commands/sync-agent-settings.md +3 -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 +4 -0
- 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 +8 -0
- package/.agent-src/rules/autonomous-execution.md +158 -0
- package/.agent-src/rules/chat-history.md +147 -118
- package/.agent-src/rules/cli-output-handling.md +26 -3
- package/.agent-src/rules/command-suggestion.md +133 -0
- package/.agent-src/rules/commit-policy.md +99 -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 +81 -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 +103 -30
- package/.agent-src/rules/scope-control.md +42 -1
- package/.agent-src/rules/size-enforcement.md +1 -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 +82 -50
- package/.agent-src/scripts/update_roadmap_progress.py +17 -5
- package/.agent-src/skills/blade-ui/SKILL.md +30 -5
- package/.agent-src/skills/command-routing/SKILL.md +32 -0
- package/.agent-src/skills/command-writing/SKILL.md +41 -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 +187 -0
- package/.agent-src/skills/fe-design/SKILL.md +72 -60
- 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 +30 -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 +2 -4
- package/.agent-src/skills/roadmap-management/SKILL.md +10 -3
- package/.agent-src/skills/rule-writing/SKILL.md +23 -1
- package/.agent-src/skills/skill-writing/SKILL.md +1 -3
- package/.agent-src/skills/upstream-contribute/SKILL.md +1 -1
- 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 +8 -2
- 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/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 +592 -0
- package/.agent-src/templates/scripts/{implement_ticket → work_engine}/delivery_state.py +7 -0
- 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 +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/memory.py +1 -1
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/plan.py +1 -1
- 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 +36 -4
- 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/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/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 +199 -0
- 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/.claude-plugin/marketplace.json +105 -2
- package/AGENTS.md +36 -8
- package/CHANGELOG.md +534 -0
- package/README.md +125 -4
- package/config/agent-settings.template.yml +45 -0
- package/config/gitignore-block.txt +4 -0
- package/docs/architecture.md +28 -1
- package/docs/development.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/installation.md +86 -0
- package/docs/showcase.md +204 -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 +36 -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/migrate_command_suggestions.py +151 -0
- package/scripts/schemas/command.schema.json +41 -0
- package/scripts/skill_linter.py +67 -0
- package/scripts/sync_agent_settings.py +42 -12
- package/templates/consumer-settings/augment-cli-hooks.json +54 -0
- package/templates/consumer-settings/claude-settings.json +55 -1
- 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
- /package/.agent-src/templates/scripts/{implement_ticket → work_engine}/persona_policy.py +0 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
"""``design`` step — produces the design brief that locks microcopy.
|
|
2
|
+
|
|
3
|
+
Phase 3 Step 1 of ``agents/roadmaps/road-to-product-ui-track.md``: the
|
|
4
|
+
design step turns the audit findings into a structured design brief
|
|
5
|
+
that ``apply`` consumes verbatim. The brief is **the lock** — apply
|
|
6
|
+
writes the strings exactly as the brief specifies. Hallucinated
|
|
7
|
+
microcopy at apply time is the failure mode this step exists to
|
|
8
|
+
prevent.
|
|
9
|
+
|
|
10
|
+
Routes on ``state.ui_design`` shape:
|
|
11
|
+
|
|
12
|
+
- **Empty / None** — first pass. Emit ``@agent-directive: ui-design-brief``
|
|
13
|
+
delegating to a design skill / sub-prompt; on the rebound the brief
|
|
14
|
+
lands in ``state.ui_design``.
|
|
15
|
+
- **Populated, microcopy contains placeholders** — emit a re-write halt
|
|
16
|
+
listing the offending fields. Apply is gated against placeholder
|
|
17
|
+
patterns (see ``apply.py``) — failing fast here keeps the gate close
|
|
18
|
+
to the producer.
|
|
19
|
+
- **Populated, well-formed, ``design_confirmed`` is missing or False** —
|
|
20
|
+
halt with a numbered-options summary so the user signs off on the
|
|
21
|
+
brief before apply writes any code.
|
|
22
|
+
- **Populated, well-formed, ``design_confirmed`` is True** — return
|
|
23
|
+
``SUCCESS``; the dispatcher advances to ``plan`` (apply).
|
|
24
|
+
|
|
25
|
+
Idempotent: a re-entry with ``design_confirmed=True`` round-trips
|
|
26
|
+
through ``SUCCESS`` without re-emitting a halt the user already
|
|
27
|
+
answered.
|
|
28
|
+
"""
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
from typing import Any
|
|
32
|
+
|
|
33
|
+
from ...delivery_state import (
|
|
34
|
+
DeliveryState,
|
|
35
|
+
Outcome,
|
|
36
|
+
StepResult,
|
|
37
|
+
agent_directive,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
REQUIRED_BRIEF_KEYS: tuple[str, ...] = (
|
|
41
|
+
"layout",
|
|
42
|
+
"components",
|
|
43
|
+
"states",
|
|
44
|
+
"microcopy",
|
|
45
|
+
"a11y",
|
|
46
|
+
)
|
|
47
|
+
"""Top-level keys every well-formed design brief must carry.
|
|
48
|
+
|
|
49
|
+
``reused_from_audit`` is recommended but not required — a fully
|
|
50
|
+
greenfield brief may legitimately have nothing to reuse.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
REQUIRED_STATE_KEYS: tuple[str, ...] = (
|
|
54
|
+
"empty",
|
|
55
|
+
"loading",
|
|
56
|
+
"error",
|
|
57
|
+
"success",
|
|
58
|
+
"disabled",
|
|
59
|
+
)
|
|
60
|
+
"""States the brief must cover; missing entries surface as halt items."""
|
|
61
|
+
|
|
62
|
+
PLACEHOLDER_PATTERNS: tuple[str, ...] = (
|
|
63
|
+
"<placeholder>",
|
|
64
|
+
"lorem",
|
|
65
|
+
"todo:",
|
|
66
|
+
"tbd",
|
|
67
|
+
"xxx",
|
|
68
|
+
)
|
|
69
|
+
"""Lower-cased substrings that mark microcopy as unfinished.
|
|
70
|
+
|
|
71
|
+
Mirrored by :mod:`work_engine.directives.ui.apply` (Phase 3 Step 2):
|
|
72
|
+
apply rejects any component whose output text matches one of these
|
|
73
|
+
patterns. Catching them here keeps the lock close to the producer.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
AMBIGUITIES: tuple[dict[str, str], ...] = (
|
|
77
|
+
{
|
|
78
|
+
"code": "design_missing",
|
|
79
|
+
"trigger": "state.ui_design is None or empty — brief has not been produced",
|
|
80
|
+
"resolution": "agent directive `ui-design-brief` → skill/agent "
|
|
81
|
+
"writes the brief into state.ui_design",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"code": "design_placeholders",
|
|
85
|
+
"trigger": "microcopy contains placeholder patterns "
|
|
86
|
+
"(<placeholder>, Lorem, TODO:, TBD, XXX)",
|
|
87
|
+
"resolution": "agent re-runs the brief with final strings; "
|
|
88
|
+
"halt lists the offending microcopy keys",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"code": "design_unconfirmed",
|
|
92
|
+
"trigger": "brief is well-formed but design_confirmed is unset/False",
|
|
93
|
+
"resolution": "user reviews the brief summary and sets "
|
|
94
|
+
"state.ui_design.design_confirmed = True (or asks for "
|
|
95
|
+
"revisions, which loops back to ui-design-brief)",
|
|
96
|
+
},
|
|
97
|
+
)
|
|
98
|
+
"""Declared ambiguity surfaces for this step."""
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def run(state: DeliveryState) -> StepResult:
|
|
102
|
+
"""Apply the design-brief lock to ``state.ui_design``."""
|
|
103
|
+
design = state.ui_design
|
|
104
|
+
if not _is_populated(design):
|
|
105
|
+
return _delegate_to_design_skill(state)
|
|
106
|
+
|
|
107
|
+
missing = _missing_required_keys(design)
|
|
108
|
+
if missing:
|
|
109
|
+
return _halt_incomplete_brief(state, missing)
|
|
110
|
+
|
|
111
|
+
placeholders = _placeholder_violations(design)
|
|
112
|
+
if placeholders:
|
|
113
|
+
return _halt_placeholders(state, placeholders)
|
|
114
|
+
|
|
115
|
+
if design.get("design_confirmed") is True:
|
|
116
|
+
return StepResult(outcome=Outcome.SUCCESS)
|
|
117
|
+
|
|
118
|
+
return _halt_unconfirmed(state, design)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _is_populated(design: Any) -> bool:
|
|
122
|
+
"""True when ``design`` carries an actionable brief.
|
|
123
|
+
|
|
124
|
+
Non-dict and empty-dict shapes are treated as "skill has not run"
|
|
125
|
+
so the first-pass directive fires. Once the skill writes a brief,
|
|
126
|
+
the dict carries at least one of the required keys; from there
|
|
127
|
+
:func:`_missing_required_keys` decides whether the brief is
|
|
128
|
+
complete enough to advance.
|
|
129
|
+
"""
|
|
130
|
+
if not isinstance(design, dict):
|
|
131
|
+
return False
|
|
132
|
+
if not design:
|
|
133
|
+
return False
|
|
134
|
+
return any(key in design for key in REQUIRED_BRIEF_KEYS)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _missing_required_keys(design: dict[str, Any]) -> list[str]:
|
|
138
|
+
"""Return required top-level keys that are missing or empty."""
|
|
139
|
+
missing: list[str] = []
|
|
140
|
+
for key in REQUIRED_BRIEF_KEYS:
|
|
141
|
+
value = design.get(key)
|
|
142
|
+
if value is None or value == "" or value == [] or value == {}:
|
|
143
|
+
missing.append(key)
|
|
144
|
+
continue
|
|
145
|
+
if key == "states" and isinstance(value, dict):
|
|
146
|
+
for state_key in REQUIRED_STATE_KEYS:
|
|
147
|
+
if not value.get(state_key):
|
|
148
|
+
missing.append(f"states.{state_key}")
|
|
149
|
+
return missing
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _placeholder_violations(design: dict[str, Any]) -> list[str]:
|
|
153
|
+
"""Return microcopy paths whose values match a placeholder pattern.
|
|
154
|
+
|
|
155
|
+
Walks ``design["microcopy"]`` recursively (dict-of-strings or
|
|
156
|
+
dict-of-dict-of-strings) and reports each leaf whose lower-cased
|
|
157
|
+
value contains one of :data:`PLACEHOLDER_PATTERNS`. Path uses
|
|
158
|
+
dotted-key form (``"buttons.submit"``) so the halt can list the
|
|
159
|
+
exact fields the agent must rewrite.
|
|
160
|
+
"""
|
|
161
|
+
microcopy = design.get("microcopy")
|
|
162
|
+
if not isinstance(microcopy, dict):
|
|
163
|
+
return []
|
|
164
|
+
violations: list[str] = []
|
|
165
|
+
_walk_microcopy(microcopy, prefix="", violations=violations)
|
|
166
|
+
return violations
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _walk_microcopy(
|
|
170
|
+
node: dict[str, Any],
|
|
171
|
+
*,
|
|
172
|
+
prefix: str,
|
|
173
|
+
violations: list[str],
|
|
174
|
+
) -> None:
|
|
175
|
+
"""Recursive helper for :func:`_placeholder_violations`."""
|
|
176
|
+
for key, value in node.items():
|
|
177
|
+
path = f"{prefix}.{key}" if prefix else str(key)
|
|
178
|
+
if isinstance(value, dict):
|
|
179
|
+
_walk_microcopy(value, prefix=path, violations=violations)
|
|
180
|
+
continue
|
|
181
|
+
if not isinstance(value, str):
|
|
182
|
+
continue
|
|
183
|
+
lowered = value.lower()
|
|
184
|
+
for pattern in PLACEHOLDER_PATTERNS:
|
|
185
|
+
if pattern in lowered:
|
|
186
|
+
violations.append(path)
|
|
187
|
+
break
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _preview_input(state: DeliveryState) -> str:
|
|
191
|
+
"""Render a one-line preview of the input being designed."""
|
|
192
|
+
data = state.ticket or {}
|
|
193
|
+
raw = data.get("raw")
|
|
194
|
+
if isinstance(raw, str) and raw.strip():
|
|
195
|
+
text = " ".join(raw.split())
|
|
196
|
+
else:
|
|
197
|
+
title = data.get("title")
|
|
198
|
+
text = title if isinstance(title, str) else (data.get("id") or "(no title)")
|
|
199
|
+
if len(text) <= 80:
|
|
200
|
+
return text
|
|
201
|
+
return text[:79].rstrip() + "\u2026"
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _delegate_to_design_skill(state: DeliveryState) -> StepResult:
|
|
205
|
+
"""Halt with an agent directive so the orchestrator runs ``ui-design-brief``."""
|
|
206
|
+
preview = _preview_input(state)
|
|
207
|
+
return StepResult(
|
|
208
|
+
outcome=Outcome.BLOCKED,
|
|
209
|
+
questions=[
|
|
210
|
+
agent_directive("ui-design-brief"),
|
|
211
|
+
f"> Input: {preview}",
|
|
212
|
+
"> No design brief yet \u2014 producing one now. The brief locks "
|
|
213
|
+
"layout, components, states, microcopy, and a11y before any "
|
|
214
|
+
"code is written.",
|
|
215
|
+
"> 1. Continue \u2014 produce the brief from audit findings",
|
|
216
|
+
"> 2. Abort \u2014 drop this UI request",
|
|
217
|
+
],
|
|
218
|
+
message=(
|
|
219
|
+
"UI design brief missing; delegating to ui-design-brief skill."
|
|
220
|
+
),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _halt_incomplete_brief(
|
|
225
|
+
state: DeliveryState,
|
|
226
|
+
missing: list[str],
|
|
227
|
+
) -> StepResult:
|
|
228
|
+
"""BLOCKED halt \u2014 brief is missing required keys."""
|
|
229
|
+
preview = _preview_input(state)
|
|
230
|
+
lines = [
|
|
231
|
+
agent_directive("ui-design-brief"),
|
|
232
|
+
f"> Input: {preview}",
|
|
233
|
+
"> Design brief is incomplete. Missing required fields:",
|
|
234
|
+
]
|
|
235
|
+
for path in missing:
|
|
236
|
+
lines.append(f"> - `{path}`")
|
|
237
|
+
lines.append(
|
|
238
|
+
"> Re-run the brief skill so every required slot has a final "
|
|
239
|
+
"value before apply.",
|
|
240
|
+
)
|
|
241
|
+
return StepResult(
|
|
242
|
+
outcome=Outcome.BLOCKED,
|
|
243
|
+
questions=lines,
|
|
244
|
+
message=(
|
|
245
|
+
f"UI design brief incomplete; {len(missing)} required "
|
|
246
|
+
f"field(s) missing."
|
|
247
|
+
),
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _halt_placeholders(
|
|
252
|
+
state: DeliveryState,
|
|
253
|
+
violations: list[str],
|
|
254
|
+
) -> StepResult:
|
|
255
|
+
"""BLOCKED halt \u2014 microcopy still carries placeholder patterns."""
|
|
256
|
+
preview = _preview_input(state)
|
|
257
|
+
lines = [
|
|
258
|
+
agent_directive("ui-design-brief"),
|
|
259
|
+
f"> Input: {preview}",
|
|
260
|
+
"> Microcopy contains placeholder patterns. Apply rejects these "
|
|
261
|
+
"verbatim, so they have to be replaced with final strings now:",
|
|
262
|
+
]
|
|
263
|
+
for path in violations:
|
|
264
|
+
lines.append(f"> - `microcopy.{path}`")
|
|
265
|
+
lines.append(
|
|
266
|
+
"> Re-run the brief skill with finalised copy; the apply step "
|
|
267
|
+
"will write strings exactly as the brief specifies.",
|
|
268
|
+
)
|
|
269
|
+
return StepResult(
|
|
270
|
+
outcome=Outcome.BLOCKED,
|
|
271
|
+
questions=lines,
|
|
272
|
+
message=(
|
|
273
|
+
f"UI design brief carries {len(violations)} placeholder "
|
|
274
|
+
f"violation(s); halting for finalised microcopy."
|
|
275
|
+
),
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _halt_unconfirmed(
|
|
280
|
+
state: DeliveryState,
|
|
281
|
+
design: dict[str, Any],
|
|
282
|
+
) -> StepResult:
|
|
283
|
+
"""BLOCKED halt \u2014 brief is well-formed; user must sign off."""
|
|
284
|
+
preview = _preview_input(state)
|
|
285
|
+
components = design.get("components") or []
|
|
286
|
+
states = design.get("states") or {}
|
|
287
|
+
microcopy = design.get("microcopy") or {}
|
|
288
|
+
|
|
289
|
+
component_count = len(components) if isinstance(components, list) else 0
|
|
290
|
+
state_count = len(states) if isinstance(states, dict) else 0
|
|
291
|
+
microcopy_count = _count_microcopy(microcopy) if isinstance(microcopy, dict) else 0
|
|
292
|
+
|
|
293
|
+
lines = [
|
|
294
|
+
f"> Input: {preview}",
|
|
295
|
+
"> Design brief is ready. Summary:",
|
|
296
|
+
f"> - Components: {component_count}",
|
|
297
|
+
f"> - States covered: {state_count}",
|
|
298
|
+
f"> - Microcopy entries (locked): {microcopy_count}",
|
|
299
|
+
"> 1. Confirm \u2014 lock this brief and advance to apply",
|
|
300
|
+
"> 2. Revise \u2014 send feedback; loops back to ui-design-brief",
|
|
301
|
+
"> 3. Abort \u2014 drop this UI request",
|
|
302
|
+
"",
|
|
303
|
+
"**Recommendation: 1 \u2014 Confirm** \u2014 the brief covers all "
|
|
304
|
+
"required slots and microcopy is final. Caveat: flip to 2 only if "
|
|
305
|
+
"a string, state, or component is wrong; do not confirm strings "
|
|
306
|
+
"you have not read.",
|
|
307
|
+
]
|
|
308
|
+
return StepResult(
|
|
309
|
+
outcome=Outcome.BLOCKED,
|
|
310
|
+
questions=lines,
|
|
311
|
+
message=(
|
|
312
|
+
"UI design brief ready; halting for user confirmation "
|
|
313
|
+
"before apply."
|
|
314
|
+
),
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def _count_microcopy(microcopy: dict[str, Any]) -> int:
|
|
319
|
+
"""Count leaf string entries in ``microcopy`` (recursive)."""
|
|
320
|
+
total = 0
|
|
321
|
+
for value in microcopy.values():
|
|
322
|
+
if isinstance(value, dict):
|
|
323
|
+
total += _count_microcopy(value)
|
|
324
|
+
elif isinstance(value, str):
|
|
325
|
+
total += 1
|
|
326
|
+
return total
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
__all__ = [
|
|
330
|
+
"AMBIGUITIES",
|
|
331
|
+
"PLACEHOLDER_PATTERNS",
|
|
332
|
+
"REQUIRED_BRIEF_KEYS",
|
|
333
|
+
"REQUIRED_STATE_KEYS",
|
|
334
|
+
"run",
|
|
335
|
+
]
|