@mmerterden/multi-agent-pipeline 13.0.0 → 13.2.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/CHANGELOG.md +111 -0
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/dev/SKILL.md +21 -0
- package/pipeline/commands/multi-agent/dev-local/SKILL.md +21 -0
- package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +257 -0
- package/pipeline/commands/multi-agent/sync/SKILL.md +4 -4
- package/pipeline/multi-agent-refs/component-dispatch.md +40 -7
- package/pipeline/multi-agent-refs/cross-cli-contract.md +3 -3
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +29 -0
- package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +24 -1
- package/pipeline/multi-agent-refs/phases/phase-3-dev.md +32 -0
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +26 -0
- package/pipeline/scripts/phase0-exit-gate.mjs +185 -0
- package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +21 -0
- package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +21 -0
- package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +258 -0
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +4 -4
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +78 -0
- package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +445 -0
- package/pipeline/skills/shared/external/ios-coding-standard/references/lint-local.sh +160 -0
- package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +1163 -0
- package/pipeline/skills/shared/external/ios-coding-standard/references/swiftlint.draft.yml +371 -0
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,117 @@ Internal file-layout changes that don't affect the slash-command surface are sti
|
|
|
16
16
|
|
|
17
17
|
## [Unreleased]
|
|
18
18
|
|
|
19
|
+
## [13.2.0] - 2026-07-28
|
|
20
|
+
|
|
21
|
+
The iOS coding standard reaches all three hosts, and works outside the pipeline.
|
|
22
|
+
|
|
23
|
+
The 95-rule registry lived as a pipeline-local routine. Two consequences, both
|
|
24
|
+
measured: only Claude Code could reach it, because `local-only` commands are
|
|
25
|
+
deliberately never synced (verified absent on Copilot CLI and Codex CLI), and it
|
|
26
|
+
applied only when the routine was invoked explicitly - nothing pulled the rules in
|
|
27
|
+
while Swift was being written. The plugin's own `reference/code-style` skill is 154
|
|
28
|
+
lines of prose with zero rule IDs, so the registry was not reachable that way either.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **`ios-coding-standard` skill**, authored once in `pipeline/skills/shared/external`
|
|
33
|
+
and routed into the iOS stack plugin's `knowledge/` by the existing generator. That
|
|
34
|
+
one source now lands as a skill on Claude Code and Copilot CLI (description-matched,
|
|
35
|
+
so the rules are present while code is being written) and ships inside the plugin for
|
|
36
|
+
Codex. `references/` carries the registry, the teaching doc, a SwiftLint config for
|
|
37
|
+
the mechanically-enforceable subset, and a module-scoped lint runner with a baseline
|
|
38
|
+
mode.
|
|
39
|
+
- **`/multi-agent:ios-coding-standard`** promoted out of `local-only` into the command
|
|
40
|
+
inventory (43 → 44), with its Copilot twin, so the module-wide audit procedure exists
|
|
41
|
+
on every host. It reads its rules from the skill rather than carrying a copy.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- The registry was generalised before promotion: company hostnames, an internal URL
|
|
46
|
+
scheme, internal model and endpoint names, and repo-specific module paths were
|
|
47
|
+
replaced. `smoke-personal-data.sh` is clean across all six promoted files. Rule
|
|
48
|
+
bodies describe shapes (a mapper doing arithmetic, a logger interpolating a token)
|
|
49
|
+
rather than named modules, so the registry applies unchanged to any SwiftUI codebase;
|
|
50
|
+
a project layers its own vocabulary through a `modules/<Module>.yml` overlay.
|
|
51
|
+
- Four over-long skill descriptions trimmed (`ios-simulator` 839→578,
|
|
52
|
+
`swift-api-design-guidelines` 738→468, `swiftlint` 725→473, and the three new ones).
|
|
53
|
+
The always-on description surface was at 78,079 of 78,000 bytes before this change;
|
|
54
|
+
adding a 44th command and a new skill needed 859 bytes it did not have. Each trim
|
|
55
|
+
removed duplication between a description's "covers" enumeration and its trigger
|
|
56
|
+
clause, which is where the routing value actually is. Surface is now 77,734.
|
|
57
|
+
|
|
58
|
+
### Notes
|
|
59
|
+
|
|
60
|
+
- **Codex lists plugin skills by name only.** Measured: all 76 plugin-provided skills
|
|
61
|
+
render with an empty description in Codex's skills block, while the 5 system skills
|
|
62
|
+
render theirs. So on Codex a plugin skill is invoked explicitly rather than matched
|
|
63
|
+
on description. That is the reason the registry is authored in `shared/external`
|
|
64
|
+
instead of hand-placed in the plugin: the pipeline install path gives Claude Code and
|
|
65
|
+
Copilot CLI a description-matched skill, and the plugin copy covers Codex.
|
|
66
|
+
- The iOS plugin now declares 143 skills and Codex surfaces about half. That overflow
|
|
67
|
+
predates this change and `tools/validate.py` warns on it; routing `knowledge/` behind
|
|
68
|
+
the plugin's `index` skill is the fix and is separate work.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## [13.1.0] - 2026-07-27
|
|
72
|
+
|
|
73
|
+
Six gates, from one branch that spent half its commits on rework.
|
|
74
|
+
|
|
75
|
+
A Figma-driven screen task was built through the generic development path. The cause
|
|
76
|
+
chain, measured from the run's own artefacts: Phase 0 reported `completed` having
|
|
77
|
+
written only `tracker-state.json`, so `agent-state.json` and its `taskType` never
|
|
78
|
+
existed, so Phase 3's component dispatch could not fire. The stack plugin already
|
|
79
|
+
ships `create-screen`, `figma-validate` (7 criteria including design-token compliance
|
|
80
|
+
and Code Connect strategy) and `figma-review` (14-item checklist) - none of them ran.
|
|
81
|
+
Padding came out 16 where the frame said `Spacing/12`. Three of six commits were fixes,
|
|
82
|
+
the last a full sheet rebuild.
|
|
83
|
+
|
|
84
|
+
Nothing here is a new capability. Every gate enforces a rule that already existed or
|
|
85
|
+
invokes a skill that was already written but never called.
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **`phase0-exit-gate.mjs`, blocking.** Phase 0 may not be marked completed until
|
|
90
|
+
`agent-state.json` exists with a `taskType`, and a Figma reference forces
|
|
91
|
+
`taskType: "component"` plus a recorded `figmaAccess.tier`. A phase that reports
|
|
92
|
+
success without its output is worse than one that fails: every later phase then
|
|
93
|
+
reasons from a field that is not there. The evaluator is pure and exported, so the
|
|
94
|
+
gate is testable without reproducing a run.
|
|
95
|
+
- **Phase 4 Step 2.8, visual conformance gate.** Runs `figma-review` and
|
|
96
|
+
`/multi-agent:design-check` for component/screen work, with the coverage gate, and
|
|
97
|
+
asserts Code Connect was **published** rather than merely written - a
|
|
98
|
+
`*.figma.swift` on disk with "Not published" in Figma is a binding that exists for
|
|
99
|
+
nobody. `design-check` had been a command with no phase invoking it, so the only
|
|
100
|
+
thing standing between a build and visual drift was the user opening the app.
|
|
101
|
+
- **Phase 1 Step 1.45, reuse discovery, blocking.** Search for an existing wrapper,
|
|
102
|
+
entity, mapper or screen before proposing a new one. One run wrote a repository over
|
|
103
|
+
an endpoint a sibling domain already wrapped **with its country parameter**, called
|
|
104
|
+
the generated method without it, and re-invented an entity the module already had.
|
|
105
|
+
"Copy X and rename it" is the reuse answer, not a hint.
|
|
106
|
+
- **`smoke-component-dispatch-gates.sh`** (12 assertions) pins all six.
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
|
|
110
|
+
- **Component dispatch halts instead of degrading.** The contract used to send an
|
|
111
|
+
incomplete-state component task down the generic TDD path while the next sentence
|
|
112
|
+
said "never silently skip the Figma work" - taking the generic path *is* skipping
|
|
113
|
+
it. That wording authorised the exact failure above.
|
|
114
|
+
- **Dispatch routes on scope, not just platform.** A screen and a component are
|
|
115
|
+
different jobs and the plugin ships a skill for each; routing a screen to the
|
|
116
|
+
component skill is why one run produced entities and a mapper but left the screen
|
|
117
|
+
half-wired. `figma-validate` now runs before the create skill.
|
|
118
|
+
- **Phase 1 captures spacing by token name, per atom.** Phase 3 is forbidden from
|
|
119
|
+
calling Figma, so a pixel number - or a missing entry - is unrecoverable later. A
|
|
120
|
+
UI frame with no spacing entries is a capture failure, not an empty frame.
|
|
121
|
+
- **Phase 3 records that generated trees are not editable.** A mock fixture went into
|
|
122
|
+
the generated tree; the fix moved it to the custom tree and registered the scenario
|
|
123
|
+
in the generated index. Same content, wrong side of the generator, and the Debug menu
|
|
124
|
+
never showed it.
|
|
125
|
+
- **Fast modes warn when handed an analysis document.** `--dev` skips Analysis and
|
|
126
|
+
Planning by design, so there is no phase that turns a document into a plan. The doc
|
|
127
|
+
becomes context for one pass and work lands in whatever order it was read.
|
|
128
|
+
|
|
129
|
+
|
|
19
130
|
## [13.0.0] - 2026-07-27
|
|
20
131
|
|
|
21
132
|
> **Why major and not minor.** The additions here are additive, but two defaults
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmerterden/multi-agent-pipeline",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.2.0",
|
|
4
4
|
"description": "8-phase AI development pipeline with full orchestration on Claude Code, Copilot CLI and Codex CLI. Analysis, planning, TDD, CLI-aware parallel review with consensus surfacing + Fable triage, default-FAIL evidence gates, secret + intent guards, per-phase cost ledger, persistent learnings memory, wiki generation, commit automation. Token-preserving uninstall.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -270,3 +270,24 @@ bash $HOME/.claude/scripts/phase-tracker.sh render
|
|
|
270
270
|
```
|
|
271
271
|
|
|
272
272
|
Do NOT call TaskCreate on these CLIs - the tool does not exist and the call fails.
|
|
273
|
+
|
|
274
|
+
## Analysis doc supplied to a fast mode (warn before starting)
|
|
275
|
+
|
|
276
|
+
The `--dev` family skips Phase 1 (Analysis) and Phase 2 (Planning) by design. So when
|
|
277
|
+
the input references an analysis document - a Confluence URL, a local analysis file,
|
|
278
|
+
or the user says "I ran analysis for this" - there is **no phase that turns it into a
|
|
279
|
+
plan**. The doc becomes raw context for one Dev pass, and work comes out ordered by
|
|
280
|
+
whatever the model read first: the bottom of the dependency chain lands, the screen
|
|
281
|
+
wiring does not.
|
|
282
|
+
|
|
283
|
+
Say so before starting, once, and offer the choice:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
This mode skips Analysis and Planning, so the analysis document will not be turned
|
|
287
|
+
into a task breakdown. For analysis-driven screen work, /multi-agent or
|
|
288
|
+
/multi-agent:local run both phases.
|
|
289
|
+
1. Continue with --dev (doc as context only)
|
|
290
|
+
2. Switch to the full pipeline
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Autopilot picks 1 and logs the warning rather than asking.
|
|
@@ -109,3 +109,24 @@ Routes to the orchestrator with `--dev --local` flags. Apply the `$HOME/.claude/
|
|
|
109
109
|
/multi-agent:dev-local "PROJ-12345" # Jira
|
|
110
110
|
/multi-agent:dev-local "Bug: LoginView dark mode" # Free-text
|
|
111
111
|
```
|
|
112
|
+
|
|
113
|
+
## Analysis doc supplied to a fast mode (warn before starting)
|
|
114
|
+
|
|
115
|
+
The `--dev` family skips Phase 1 (Analysis) and Phase 2 (Planning) by design. So when
|
|
116
|
+
the input references an analysis document - a Confluence URL, a local analysis file,
|
|
117
|
+
or the user says "I ran analysis for this" - there is **no phase that turns it into a
|
|
118
|
+
plan**. The doc becomes raw context for one Dev pass, and work comes out ordered by
|
|
119
|
+
whatever the model read first: the bottom of the dependency chain lands, the screen
|
|
120
|
+
wiring does not.
|
|
121
|
+
|
|
122
|
+
Say so before starting, once, and offer the choice:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
This mode skips Analysis and Planning, so the analysis document will not be turned
|
|
126
|
+
into a task breakdown. For analysis-driven screen work, /multi-agent or
|
|
127
|
+
/multi-agent:local run both phases.
|
|
128
|
+
1. Continue with --dev (doc as context only)
|
|
129
|
+
2. Switch to the full pipeline
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Autopilot picks 1 and logs the warning rather than asking.
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Audit an iOS module against the shared coding-standard registry (95 stable-ID rules), produce a remediation plan, then hand off to dev/dev-local. Use for a standards pass on a module, or when a review needs rule IDs rather than opinions."
|
|
3
|
+
description-tr: "Bir iOS modulunu paylasilan kodlama-standardi registry'sine (95 sabit-ID kural) gore denetler, duzeltme plani cikarir, sonra dev/dev-local'e devreder. Bir modulde standart gecisi icin, ya da bir review'un gorus yerine kural ID'si istedigi durumda kullan."
|
|
4
|
+
argument-hint: "[module name or path]"
|
|
5
|
+
allowed-tools: Skill, Bash, Read, Edit, Write, AskUserQuestion
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# multi-agent ios-coding-standard — Module audit → plan → dev handoff
|
|
9
|
+
|
|
10
|
+
**Input**: $ARGUMENTS — optionally a module name or path. When absent, Phase 1 discovers and asks.
|
|
11
|
+
|
|
12
|
+
This routine is the **procedure**. The rules live in the `ios-coding-standard` skill, whose registry is
|
|
13
|
+
`references/rules.yml` and whose teaching doc is `references/STANDARD.md`. Load that
|
|
14
|
+
skill first; it is installed on every host and carried by the iOS stack plugin, so
|
|
15
|
+
there is one registry rather than a copy per CLI. Never restate a rule here — cite its ID. A rule that is not in the
|
|
16
|
+
registry is not a rule; if the audit needs one, propose it as `status: proposed` and say so.
|
|
17
|
+
|
|
18
|
+
Read-only + planning. This routine never edits source — the dev pipeline does.
|
|
19
|
+
|
|
20
|
+
**Goal.** A developer new to the repo can open any file in the module and understand it without a
|
|
21
|
+
guided tour, and nothing sensitive leaks on the way. Rank every finding by "does fixing this
|
|
22
|
+
shorten the time to first productive PR, or close a real risk?"
|
|
23
|
+
|
|
24
|
+
Render assistant-facing prose in `outputLanguage`. External payloads (branch names, plan file,
|
|
25
|
+
dev task) stay English.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Phase 1 — Discover and pick the module
|
|
30
|
+
|
|
31
|
+
1. Repo root via `git rev-parse --show-toplevel`.
|
|
32
|
+
2. **Discover module roots** — any directory with a `Package.swift`, a `Sources/` subtree or an
|
|
33
|
+
`.xcodeproj`. Sweep the container dirs that exist (`Domains/`, `Packages/`, `Modules/`,
|
|
34
|
+
`Features/`, `Core/`, `Common/`, top-level module dirs) one level deep, then two if empty.
|
|
35
|
+
3. Record per module: name · path · Swift files · lines · governance docs present · SPM targets.
|
|
36
|
+
Keep this **module registry** for the whole run — `MOD-*` greps every import against it.
|
|
37
|
+
Classify each module's role, because the role decides which dependency edges are legal:
|
|
38
|
+
**feature** · **core/common** · **seam** (cross-module contracts/bridges/navigation) ·
|
|
39
|
+
**composition root** (legitimately knows every module).
|
|
40
|
+
4. If `$ARGUMENTS` resolves to a module, skip the prompt. Otherwise `AskUserQuestion`
|
|
41
|
+
(single-select, `outputLanguage`), documented modules first, each option showing file/line
|
|
42
|
+
counts and `docs: yes/no`. If the list exceeds the question limit, group the smallest into an
|
|
43
|
+
"other" option and ask again — never truncate silently.
|
|
44
|
+
5. Scope = the whole module's sources across all its targets, unless the user narrows it.
|
|
45
|
+
|
|
46
|
+
## Phase 2 — Resolve what applies to THIS module
|
|
47
|
+
|
|
48
|
+
### 2a. The registry is the standard — in-module prose docs are NOT consulted
|
|
49
|
+
|
|
50
|
+
The skill's `references/rules.yml` (+ a project `modules/<Module>.yml` overlay) is the single source of truth. **Do not read, cite, or
|
|
51
|
+
derive rules from a module's own `*-CLAUDE.md`, `docs/` set or any other in-repo prose.** They are
|
|
52
|
+
being retired precisely so there is one place a rule can live; consulting them re-creates the
|
|
53
|
+
split this command exists to remove. If such a file exists and contradicts the registry, that is a
|
|
54
|
+
finding against the file, not against the code.
|
|
55
|
+
|
|
56
|
+
The only in-repo inputs are **code and manifests**: sources, tests, `Package.swift`, `Info.plist`,
|
|
57
|
+
the specs the generator reads, and the module registry from Phase 1.
|
|
58
|
+
|
|
59
|
+
### 2b. Per-module overlay, then inference
|
|
60
|
+
|
|
61
|
+
1. **`modules/<Module>.yml`** beside the project's own config carries what code cannot state: the vocabulary
|
|
62
|
+
bindings, the module's role, prohibitions that currently have **zero** instances, deliberate
|
|
63
|
+
carve-outs, name locks, and the real verification command. Registry-backed, so its findings may
|
|
64
|
+
be `blocking`.
|
|
65
|
+
*Why prohibitions need to be written down:* inference reads dominant patterns, and a rule
|
|
66
|
+
obeyed everywhere has no counter-example to infer from. A ban at 100% compliance is invisible
|
|
67
|
+
to a scan — it survives only if the overlay states it.
|
|
68
|
+
2. **Repo-level rules** (root `CLAUDE.md`, contributing docs) apply to every module.
|
|
69
|
+
3. **The module's own dominant pattern is its de-facto convention.** Count variants per dimension;
|
|
70
|
+
the minority instances are the finding. Internal consistency beats conformity to a sibling.
|
|
71
|
+
4. No majority (even split, single instance) → not a finding. Record an Open Question.
|
|
72
|
+
|
|
73
|
+
Findings from step 3 are tagged `inferred` and capped at **suggestion**. Only registry- or
|
|
74
|
+
overlay-backed rules may be `blocking`.
|
|
75
|
+
|
|
76
|
+
**When the overlay is missing**, generate a draft from code evidence, print it for confirmation,
|
|
77
|
+
and mark every slot it could not derive — a frozen UI target, a name lock, a carve-out and an
|
|
78
|
+
operational constraint all look like ordinary code from the outside. Do not guess them; list them
|
|
79
|
+
as Open Questions.
|
|
80
|
+
|
|
81
|
+
### 2c. Vocabulary
|
|
82
|
+
|
|
83
|
+
Bind each slot to a real symbol by grepping the module, then the reference module. **An unbound
|
|
84
|
+
slot disables its rules** — never invent a name, never import a sibling's.
|
|
85
|
+
|
|
86
|
+
`HandlerName` · `EventParam` · `CoordinatorType` · `ResultType` / `ErrorType` / `ErrorFactory` ·
|
|
87
|
+
`DIResolver` / `DIConfigurator` · `RequestModelSuffix` / `ResponseModelSuffix` / `TransportSuffix` ·
|
|
88
|
+
`MapperShape` · `SafeEnumProtocol` / `UnknownCase` · `CopySurface` · `AnalyticsSurface` ·
|
|
89
|
+
`A11yIdentifierSource` · `GeneratedServiceRoot` · `SharedComponentsDir` / `SharedEntitiesDir` ·
|
|
90
|
+
`MicroComponentLibrary` · `FrozenUITarget` · `DesignTokenNamespaces` · `CalendarDayHelper` ·
|
|
91
|
+
`LoggerAPI` · `FileHeaderShape` · `ScreenRoot` · `ScreenRoleSuffixes` · `AsyncStyle` ·
|
|
92
|
+
`CompositionRoot` · `SeamLayer` · `ModuleEntrySurface` · `ConcurrencyPosture` · `LintToolchain` ·
|
|
93
|
+
`CredentialStore` (the module's Keychain wrapper, if any).
|
|
94
|
+
|
|
95
|
+
Print the resolved table before scanning so a wrong binding is caught early.
|
|
96
|
+
|
|
97
|
+
### 2d. Sensitive-data inventory — required before any SEC rule runs
|
|
98
|
+
|
|
99
|
+
The `SEC-*` rules are written against the **data classes** in `references/rules.yml →
|
|
100
|
+
sensitive_data_classes`, never against one module's field names. Resolve the module's concrete
|
|
101
|
+
instances of each class: grep entities, request/response models, storage calls and analytics
|
|
102
|
+
events for the values the module actually handles, and map each to its class.
|
|
103
|
+
|
|
104
|
+
Produce the inventory as a table — **class · concrete symbols · where it enters · required
|
|
105
|
+
lifetime (transient / survives-restart / survives-reinstall) · where it is actually stored ·
|
|
106
|
+
where it is logged · where it leaves (network, analytics, pasteboard, another module)**.
|
|
107
|
+
|
|
108
|
+
The **lifetime column is the one that decides SEC-01**, and it is filled by walking
|
|
109
|
+
`references/rules.yml → persistence_decision`, not by looking at what the code currently does. Compare it
|
|
110
|
+
against the storage column and report both mismatches:
|
|
111
|
+
- required transient but persisted anywhere (including the Keychain) → **over-persistence**;
|
|
112
|
+
- required to survive a restart but stored outside the Keychain → **under-protection**.
|
|
113
|
+
|
|
114
|
+
Then generate the SEC lint patterns *from this inventory*, so the checks match this module's real
|
|
115
|
+
vocabulary. A class with no instance here yields no finding; a symbol you cannot classify, or one
|
|
116
|
+
whose required lifetime nobody can state, is an Open Question, not a silent pass.
|
|
117
|
+
|
|
118
|
+
This table is a deliverable in its own right, independent of whether any violation is found.
|
|
119
|
+
|
|
120
|
+
## Phase 3 — Scan
|
|
121
|
+
|
|
122
|
+
Apply the rules in `references/rules.yml` that survived Phase 2 binding, plus the module's own `validation`
|
|
123
|
+
gate. Tag every finding: **rule ID · severity · source (`registry` / `doc` / `inferred`) ·
|
|
124
|
+
onboarding impact (high/medium/low)**.
|
|
125
|
+
|
|
126
|
+
### Coverage gate — on disk, not in memory
|
|
127
|
+
|
|
128
|
+
Before scanning, write `.<module>-audit-coverage.tsv` to the scratch dir: one row per target
|
|
129
|
+
(every screen under `ScreenRoot`, every shared component, every entity, every file in every
|
|
130
|
+
target) with columns `path · status · rules-applied`. Mark rows as you go.
|
|
131
|
+
|
|
132
|
+
- Each target is **audited** or **explicitly skipped with a reason** (generated, fixture,
|
|
133
|
+
vendored). No third state.
|
|
134
|
+
- **The run is incomplete while any row is unmarked** — and the file, not a claim, is the proof.
|
|
135
|
+
Chunk the module if it is too large for one pass; the checklist survives a context reset.
|
|
136
|
+
- No sampling. A partial audit reported as complete certifies the unscanned screens as clean.
|
|
137
|
+
|
|
138
|
+
### Grep hygiene
|
|
139
|
+
|
|
140
|
+
Registry `mechanism` patterns are line-based and match doc comments. Filter
|
|
141
|
+
`^[[:space:]]*//` — BSD grep does not understand `\s`, so a `\s*//` filter silently lets `/// …`
|
|
142
|
+
through — then open each surviving hit and confirm it is real code. Report pre-filter and
|
|
143
|
+
post-verification counts separately; a table padded with comment matches destroys trust.
|
|
144
|
+
|
|
145
|
+
### Judgement rules need evidence, not assertion
|
|
146
|
+
|
|
147
|
+
For any rule marked `enforcement: judgement`, a finding must carry the measurement its `check`
|
|
148
|
+
names — a reference count, a call-site count, a consumer count, a file list. **No count, no
|
|
149
|
+
finding.** This is what keeps a subjective rule from becoming an opinion.
|
|
150
|
+
|
|
151
|
+
Every judgement rule has a worked ✗/✓ pair in `EXAMPLES.md`, keyed by ID. Cite it in the finding's
|
|
152
|
+
proposed fix rather than re-describing the shape — the developer applying the fix should be
|
|
153
|
+
reading the same picture the audit used.
|
|
154
|
+
|
|
155
|
+
### Module-specific overrides
|
|
156
|
+
|
|
157
|
+
The module's own docs win over the registry, including where they contradict a sibling module.
|
|
158
|
+
Never apply one module's dialect to another. List every override honoured, so the reader sees why
|
|
159
|
+
a registry rule was not raised.
|
|
160
|
+
|
|
161
|
+
## Phase 4 — Produce the plan
|
|
162
|
+
|
|
163
|
+
No findings → report compliant and stop. Otherwise write
|
|
164
|
+
`<ModulePath>/ios-coding-standard-plan-<module>.md` (or the repo's scratch/docs dir if the module
|
|
165
|
+
tree must stay clean), containing, in order:
|
|
166
|
+
|
|
167
|
+
1. **Coverage ledger** — total targets · audited · skipped with reasons. Not 100% accounted for
|
|
168
|
+
means the plan is not deliverable.
|
|
169
|
+
2. **Summary** — counts by severity and source, resolved vocabulary, branch to create.
|
|
170
|
+
3. **Sensitive-data inventory** (Phase 2d) — first, because it is the highest-risk content.
|
|
171
|
+
4. **Screen × role matrix** `[STRUCT-02]` — screens as rows, manifest roles as columns, cells
|
|
172
|
+
`✓ / missing / misplaced`. The structural map a newcomer reads first.
|
|
173
|
+
5. **Type placement table** `[STRUCT-05]` — type · location · consumer count · correct tier ·
|
|
174
|
+
move required. Paired with the nested-type list `[STRUCT-01]`: owner · nested type · kind ·
|
|
175
|
+
reference count · verdict.
|
|
176
|
+
6. **Visibility report** `[VIS-01, VIS-02]` — over-exposed declarations per file, non-final
|
|
177
|
+
classes with no subclass.
|
|
178
|
+
7. **Boundary report** `[MOD-*]` — import graph (allowed vs forbidden, with coupling depth) ·
|
|
179
|
+
manifest graph (declared vs legal for the role, plus dead edges) · **removability delta**
|
|
180
|
+
("removing X touches N files: …") · inbound test (tests compile with no sibling present).
|
|
181
|
+
8. **Testability seam report** `[TEST-*]` — types reaching for the environment, logic requiring a
|
|
182
|
+
view to execute, doubles whose signatures have drifted.
|
|
183
|
+
9. **Change-cost probe** `[FLEX-*]` — pick two plausible upcoming changes (a new variant of an
|
|
184
|
+
existing screen; a new field on a shared entity) and state what each costs in files today.
|
|
185
|
+
10. **Findings table** — rule ID · `file:line` · current state · proposed fix · severity · source ·
|
|
186
|
+
onboarding impact.
|
|
187
|
+
11. **Per-file work** — grouped per file, blocking → important → suggestion; within a severity,
|
|
188
|
+
highest onboarding impact first.
|
|
189
|
+
12. **Behaviour-preservation guard** — splitting files, adding MARKs, extracting extensions and
|
|
190
|
+
moving types must not change behaviour. Anything requiring a behaviour change (a missing
|
|
191
|
+
analytics event, a wrong result type, a timezone fix, a storage migration) goes in a
|
|
192
|
+
**separate group**, reviewed and tested on its own, never inside a mechanical split commit.
|
|
193
|
+
13. **Tooling delegation & the ratchet** — the section that decides whether any of this survives.
|
|
194
|
+
- Classify each applied rule by its registry `enforcement`. For every `lint` / `format` /
|
|
195
|
+
`scan` rule, state the concrete mechanism and whether that toolchain exists in the repo
|
|
196
|
+
(`LintToolchain`). **When it does not exist, saying so is a finding**, ranked above most
|
|
197
|
+
individual violations it would have caught.
|
|
198
|
+
- Recommend **baseline-and-ratchet, never big-bang**: grandfather existing violations, surface
|
|
199
|
+
only new ones, drain the backlog behind a green build. Order the plan the same way — stop
|
|
200
|
+
the bleeding, then clean up.
|
|
201
|
+
- Custom lint rule identifiers **are** the registry IDs (`sec_01_no_plaintext_persistence`,
|
|
202
|
+
`mod_01_no_sibling_import`) so a violation points straight at the rule entry.
|
|
203
|
+
- **Linting is local-only by decision** — the skill's `references/lint-local.sh` with `references/swiftlint.draft.yml`, config
|
|
204
|
+
and baseline kept outside the repository; no committed config, no build phase, no CI job.
|
|
205
|
+
State this honestly in the plan rather than describing a gate that does not exist: a
|
|
206
|
+
pre-PR habit catches less than a wall, so the residual risk is real and belongs in the
|
|
207
|
+
report. Adopting it project-wide remains an open decision — record it as one so it stays
|
|
208
|
+
visible instead of quietly lapsing.
|
|
209
|
+
- Never imply the audit substitutes for the linter, or the linter for a gate. The audit finds
|
|
210
|
+
the debt once; the linter keeps a developer honest; only a gate stops it returning.
|
|
211
|
+
14. **Numeric exit criteria** — target and today's measured value side by side: lint violations
|
|
212
|
+
per 1k lines (<1) · public-surface ratio, public declarations ÷ externally consumed symbols
|
|
213
|
+
(≈1) · forbidden cross-module imports (0) · removability delta · files over threshold and
|
|
214
|
+
files >120 lines with no sectioning (0) · screens missing a manifest role (0) · escape-hatch
|
|
215
|
+
count `[CONC-03]` (flat or falling) · exception-marker count (flat or falling) · dead code (0)
|
|
216
|
+
· screens with logic and no mirrored tests (0) · unclassified sensitive symbols (0).
|
|
217
|
+
15. **Exception ledger** — every `// standard:exception(<ID>)` in the module: rule · reason ·
|
|
218
|
+
expiry · expired yes/no.
|
|
219
|
+
16. **Open Questions** — Phase 2b dimensions with no majority, and unclassifiable symbols.
|
|
220
|
+
17. **Suggested commit slicing** — one commit per file-group / concern.
|
|
221
|
+
18. **Scope guard** — only this module is touched; definition of done is the module's own
|
|
222
|
+
verification path.
|
|
223
|
+
|
|
224
|
+
Then write a **separate one-page onboarding summary** beside the plan, aimed at a developer
|
|
225
|
+
joining next week rather than at whoever does the remediation: the ten always/never lines
|
|
226
|
+
specialised to this module, the screen file manifest, the placement ladder, the sensitive-data
|
|
227
|
+
classes in play, and the verification command. Nobody learns a codebase from a 40-finding audit —
|
|
228
|
+
this page is the actual deliverable, and the audit is how you earn the right to write it
|
|
229
|
+
accurately. Derive it from `references/STANDARD.md § 0`, do not re-invent it.
|
|
230
|
+
|
|
231
|
+
Show a concise version of the plan to the user too.
|
|
232
|
+
|
|
233
|
+
## Phase 5 — Hand off
|
|
234
|
+
|
|
235
|
+
`AskUserQuestion` (single-select, `outputLanguage`):
|
|
236
|
+
|
|
237
|
+
| Option | What it does |
|
|
238
|
+
|---|---|
|
|
239
|
+
| `/multi-agent:dev-local` | No worktree; branches from the main development branch, fixes on the current checkout |
|
|
240
|
+
| `/multi-agent:dev` | Opens a worktree; Opus fixes on a fresh branch + PR |
|
|
241
|
+
|
|
242
|
+
Invoke the chosen command with the plan file as the task input, branching off the repo's main
|
|
243
|
+
development branch (e.g. `chore/<module>-coding-standard`). The dev pipeline applies the fixes,
|
|
244
|
+
verifies, and commits only when asked. This routine ends at the handoff.
|
|
245
|
+
|
|
246
|
+
## Notes
|
|
247
|
+
|
|
248
|
+
- **Verification reality is per-module — establish it, do not assume it.** Some targets cannot be
|
|
249
|
+
compiled from the CLI (asset symbol generation, UIKit-dependent packages, a dependency failing
|
|
250
|
+
earlier in the graph); there, verification is Xcode and a manifest dump validates the manifest
|
|
251
|
+
only. Never trust a piped build's exit code — a pipe reports the tail's status. Record the
|
|
252
|
+
module's actual verification command in the plan.
|
|
253
|
+
- One module per run. Several modules means several runs and several plans, never one
|
|
254
|
+
cross-module churn commit.
|
|
255
|
+
- If the audit wants a rule the registry lacks, add it to the skill's `references/rules.yml` as `status: proposed` with a
|
|
256
|
+
rationale and surface it in Open Questions. Do not enforce an unregistered rule.
|
|
257
|
+
- No AI attribution anywhere (code, commits, PRs). Author = git identity.
|
|
@@ -59,8 +59,8 @@ Run every step automatically:
|
|
|
59
59
|
```
|
|
60
60
|
Step 1: PLATFORM Detect macOS / Linux / Windows (Git Bash / WSL); export PLATFORM env
|
|
61
61
|
Step 1.5: DETECT Compare timestamps, find stale targets
|
|
62
|
-
Step 2: COPILOT Claude Code -> Copilot CLI (instructions +
|
|
63
|
-
Step 2b: CODEX Claude Code -> Codex CLI (1 router skill +
|
|
62
|
+
Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 44 sub-command skills)
|
|
63
|
+
Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 44 specs as refs + 8 agent TOML)
|
|
64
64
|
Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub, bash -n on all sh)
|
|
65
65
|
Step 3c: PLUGINS pipeline shared/external -> multi-agent-plugins marketplace (rebuild knowledge/,
|
|
66
66
|
bump changed plugins' patch version, commit + push the plugins repo)
|
|
@@ -486,12 +486,12 @@ same 43 specs as reference files rather than as peer skills, via Step 2b - see
|
|
|
486
486
|
|-------------|-------------|
|
|
487
487
|
| `~/.claude/commands/multi-agent/{cmd}/SKILL.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
|
|
488
488
|
|
|
489
|
-
**
|
|
489
|
+
**44 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
|
|
490
490
|
|
|
491
491
|
```
|
|
492
492
|
analysis, analysis-resolve, autopilot, build-optimize, channels, create-jira, design-check, dev,
|
|
493
493
|
dev-autopilot, dev-local, dev-local-autopilot, diff-explain, finish, forget, garbage-collect,
|
|
494
|
-
help, issue, jira, kill, language, local,
|
|
494
|
+
help, ios-coding-standard, issue, jira, kill, language, local,
|
|
495
495
|
local-autopilot, log, manual-test, prune-logs, purge, refactor, resume, review, review-issue, review-jira,
|
|
496
496
|
routines, save, scan, search, setup, stack, status, sync, test, testflight-validation, uninstall, update
|
|
497
497
|
```
|
|
@@ -11,20 +11,53 @@ Phase 3 checks, in order:
|
|
|
11
11
|
1. `agent-state.json` has `taskType: "component"` (set by Phase 0 Step 7).
|
|
12
12
|
2. `agent-state.json` has a non-null `figmaUrl`.
|
|
13
13
|
|
|
14
|
-
Either missing →
|
|
14
|
+
Either missing → **HALT.** Log the anomaly to `agent-log.md` ("component dispatch
|
|
15
|
+
expected but state incomplete: <which field>") and stop with a user-visible error
|
|
16
|
+
naming the missing field and pointing at `phase0-exit-gate.mjs`.
|
|
17
|
+
|
|
18
|
+
> Earlier wording sent an incomplete-state component task down the generic TDD path,
|
|
19
|
+
> which contradicted the sentence that followed it: taking the generic path **is**
|
|
20
|
+
> skipping the Figma work.
|
|
21
|
+
> It also authorised the exact degradation that broke a real run - Phase 0 never
|
|
22
|
+
> wrote `agent-state.json`, so `taskType` was absent, so a Figma-driven screen was
|
|
23
|
+
> built through the generic path with no token-compliance check, no Code Connect
|
|
24
|
+
> publish and no component review. Spacing came out `16` where the frame said
|
|
25
|
+
> `Spacing/12`, and half the branch's commits were rework.
|
|
26
|
+
>
|
|
27
|
+
> The Phase 0 exit gate now prevents reaching Phase 3 in that state at all; this
|
|
28
|
+
> halt is the second line of defence. A component task that cannot be dispatched as
|
|
29
|
+
> one must fail loudly, because the generic path produces artefacts that look
|
|
30
|
+
> finished and are not.
|
|
15
31
|
|
|
16
32
|
## Plugin skill resolution
|
|
17
33
|
|
|
34
|
+
Scope first, then platform. A screen and a single component are different jobs and
|
|
35
|
+
the plugin ships a skill for each; routing a screen to the component skill is why one
|
|
36
|
+
run produced entities and a mapper but left the screen half-wired.
|
|
37
|
+
|
|
38
|
+
| `state.componentScope` | Meaning | iOS skill | Android skill |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `screen` (default when the frame is a full screen, or the task names a screen) | Full clean-architecture vertical: Entity → Repository → Mapper → UseCase → LocalizedText → AnalyticsTracking → CoordinatorEvent → ViewModel → Scene → Preview, then verify | `ai-ios-engineering-toolkit:create-screen` | `ai-android-engineering-toolkit:create-screen` |
|
|
41
|
+
| `component` | One reusable UI component (Configuration / View / +Modifiers / Code Connect) | `ai-ios-engineering-toolkit:create-component` (fallback `create-ui-component`) | `ai-android-engineering-toolkit:create-component` (fallback `create-ui-component`) |
|
|
42
|
+
| `evolve` | Change an existing component | `evolve-component` (fallback `evolve-ui-component`) | same |
|
|
43
|
+
|
|
18
44
|
```
|
|
19
|
-
project.platform → component skill (enabled marketplace plugin, Claude Code)
|
|
20
|
-
──────────────────────────────────────────────────────────────────────────────
|
|
21
|
-
ios → Skill: ai-ios-engineering-toolkit:create-component
|
|
22
|
-
(fallback: ai-ios-engineering-toolkit:create-ui-component)
|
|
23
|
-
android → Skill: ai-android-engineering-toolkit:create-component
|
|
24
|
-
(fallback: ai-android-engineering-toolkit:create-ui-component)
|
|
25
45
|
web, multi-* → HALT with clear error (no web target)
|
|
26
46
|
```
|
|
27
47
|
|
|
48
|
+
Phase 0 Step 7 sets `state.componentScope` alongside `taskType`: a Figma frame that
|
|
49
|
+
is a full screen, or a task whose title names a screen, is `screen`; a frame that is
|
|
50
|
+
a single atom is `component`. When it cannot be decided, ask - do not default to
|
|
51
|
+
`component`, because the screen path is a superset and the component path silently
|
|
52
|
+
omits the wiring.
|
|
53
|
+
|
|
54
|
+
**Pre-implementation validation is not optional on iOS.** Before the create skill
|
|
55
|
+
runs, dispatch `ai-ios-engineering-toolkit:figma-validate` for the frame. It checks
|
|
56
|
+
registry presence, Code Connect strategy, **design token compliance**, dependency
|
|
57
|
+
readiness, atomic scope and already-implemented status in about ten seconds. Those
|
|
58
|
+
are precisely the checks whose absence produced guessed spacing and an unpublished
|
|
59
|
+
Code Connect binding. A `figma-validate` failure halts the dispatch.
|
|
60
|
+
|
|
28
61
|
**Dual-name resolution.** The public (`multi-agent-plugins`) and a corporate/private marketplace named the same skill differently - `create-component` vs `create-ui-component`. Dispatch tries `create-component` first; if it is not available in the current repo, tries `create-ui-component`. (Same dual-name rule applies when `taskType` maps to evolve → `evolve-component`/`evolve-ui-component`, or fix → `fix-bug`.)
|
|
29
62
|
|
|
30
63
|
If **neither** resolves, the platform's `ai-<platform>-engineering-toolkit` plugin is not enabled in this repo. **Halt with a user-visible error**: "component task requires the ai-<platform>-engineering-toolkit plugin enabled in this repo (`.claude/settings.local.json`)." Do not silently fall back to TDD - a component task ran through the bugfix path would produce wrong artefacts.
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## 1. Command Inventory (
|
|
9
|
+
## 1. Command Inventory (44 commands)
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
analysis, analysis-resolve, autopilot, build-optimize, channels, create-jira, design-check, dev,
|
|
13
13
|
dev-autopilot, dev-local, dev-local-autopilot, diff-explain, finish, forget, garbage-collect,
|
|
14
|
-
help, issue, jira, kill, language, local,
|
|
14
|
+
help, ios-coding-standard, issue, jira, kill, language, local,
|
|
15
15
|
local-autopilot, log, manual-test, prune-logs, purge, refactor, resume, review, review-issue, review-jira,
|
|
16
16
|
routines, save, scan, search, setup, stack, status, sync, test, testflight-validation, uninstall, update
|
|
17
17
|
```
|
|
@@ -24,7 +24,7 @@ Categories:
|
|
|
24
24
|
- **Fast modes** (Init -> Dev(Opus) -> Commit -> Report): `dev`, `dev-autopilot`, `dev-local`, `dev-local-autopilot`
|
|
25
25
|
- **Tail modes** (run the pipeline tail over already-done local work): `finish`
|
|
26
26
|
- **Ops commands** (one-shot, no worktree): `status`, `log`, `kill`, `purge`, `uninstall`, `resume`, `review`, `review-jira`, `review-issue`, `analysis`, `analysis-resolve`, `build-optimize`, `channels`, `scan`, `search`, `diff-explain`, `garbage-collect`, `prune-logs`
|
|
27
|
-
- **Local audits** (worktree only to build; no commit, push, PR or channels): `design-check`, `testflight-validation`. `testflight-validation` additionally never invokes `altool --upload-app` - a validation run must not be able to ship a build by accident.
|
|
27
|
+
- **Local audits** (worktree only to build; no commit, push, PR or channels): `design-check`, `testflight-validation`, `ios-coding-standard`. `testflight-validation` additionally never invokes `altool --upload-app` - a validation run must not be able to ship a build by accident.
|
|
28
28
|
- **Meta-ops**: `setup`, `sync`, `update`, `help`, `refactor`, `test`, `stack`, `manual-test`, `language`
|
|
29
29
|
- **Routines** (user-defined routine registry; the routines they create are local-only and never synced): `save`, `routines`, `forget`
|
|
30
30
|
|
|
@@ -531,3 +531,32 @@ Phase 7 cost rollup carries this as a `phase 0` line item so the user sees ambig
|
|
|
531
531
|
**Progress (per `$HOME/.claude/multi-agent-refs/progress-contract.md`):** emit one `→ <verb> <object>` line for each of: `→ parsing input`, `→ checking token <service>`, `→ scanning project <root>`, `→ creating worktree <repo>`, `→ binding identity <name>`, `→ writing state`. When `clarifyAmbiguous.enabled`, also emit `→ scoring task ambiguity` before Step 8 and `→ asking clarifying questions <N>` when `stopAndAsk` fires.
|
|
532
532
|
|
|
533
533
|
**Save preferences**: Write updated prefs to `$HOME/.claude/multi-agent-preferences.json` with all Phase 0 selections.
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
#### Phase 0 exit gate (BLOCKING - run before marking the phase completed)
|
|
538
|
+
|
|
539
|
+
Phase 0 owns `agent-state.json`. Do not call
|
|
540
|
+
`phase-tracker.sh update 0 completed` until this gate passes:
|
|
541
|
+
|
|
542
|
+
```bash
|
|
543
|
+
node "$HOME/.claude/scripts/phase0-exit-gate.mjs" "$TASK_ID" --input "$ORIGINAL_INPUT"
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
It asserts three things, each of which has failed silently in a real run:
|
|
547
|
+
|
|
548
|
+
1. **`agent-state.json` exists.** A run once reported Phase 0 `completed` with only
|
|
549
|
+
`tracker-state.json` on disk. Every later phase then reasons from fields that are
|
|
550
|
+
not there.
|
|
551
|
+
2. **`taskType` is set.** Phase 3 branches on it (Step 7). Absent, a Figma-driven
|
|
552
|
+
screen is dispatched as generic development, skipping the stack plugin's
|
|
553
|
+
token-compliance check, Code Connect publish and component review. That run
|
|
554
|
+
guessed `16` where the frame said `Spacing/12`, and half its commits were rework.
|
|
555
|
+
3. **A Figma reference forces `taskType: "component"`, and `figmaAccess.tier` is
|
|
556
|
+
recorded.** Without the tier, a later phase cannot tell "the design was confirmed"
|
|
557
|
+
from "the design was never fetched" - which is exactly when spacing gets guessed.
|
|
558
|
+
|
|
559
|
+
A failure is a halt, not a warning. Fix the state and re-run the gate; the phase
|
|
560
|
+
stays `in_progress` until it passes. **Never** mark Phase 0 completed on the grounds
|
|
561
|
+
that its steps ran - the gate checks the output, and the output is what Phase 3
|
|
562
|
+
consumes.
|
|
@@ -63,7 +63,14 @@ When `state.contextLinks[]` or the task description contains a Figma reference,
|
|
|
63
63
|
| 2 (REST) | `GET /v1/files/{fileKey}/nodes?ids={nodeId}` + `GET /v1/images/{fileKey}?ids={nodeId}&format=png&scale=2`, PAT via `~/.claude/lib/credential-store.sh get <logical-key>` (logical key = `prefs.global.keychainMapping.figma_pat`); canonical component resolved from repo `*.figma.swift` / `*.figma.kt` mapping keyed by `fileKey` + `nodeId` | same shape, but `codeConnectSnippets[]` is empty when repo mapping is absent (record an Open Question), `tier: 2` |
|
|
64
64
|
| 3 (screenshot) | User-attached screenshot stored alongside task evidence | degraded record: `codeConnectSnippets: []`, forced Open Question, `tier: 3` |
|
|
65
65
|
|
|
66
|
-
Persist results under `state.evidence.figma[]`. Halt the run if all three tiers fail; never substitute primitives or invent layout from prose.
|
|
66
|
+
Persist results under `state.evidence.figma[]`. Halt the run if all three tiers fail; never substitute primitives or invent layout from prose.
|
|
67
|
+
|
|
68
|
+
**Spacing goes in by token NAME, per atom - never a pixel number.** `tokens[]` must
|
|
69
|
+
carry each frame's spacing/padding as Figma names them (`Spacing/12`, edge `4`), keyed
|
|
70
|
+
to the atom. Phase 3 cannot call Figma, so what is missed here is gone: one run guessed
|
|
71
|
+
`16` where the frame said `Spacing/12` and the sheet was rebuilt. A pixel number also
|
|
72
|
+
cannot map back to a token. No spacing entries on a UI frame is a **capture failure**,
|
|
73
|
+
not an empty frame - Open Question and halt. Canonical chain reference: `pipeline/rules/figma-pipeline.md` "MUST: Figma access - 3-tier fallback chain".
|
|
67
74
|
|
|
68
75
|
**Telemetry (required for the no-MCP gate):** Tier 1 uses `mcp__claude_ai_Figma__*` tools. Every such MCP invocation MUST append an entry to `state.telemetry.mcpCalls[]` as `{ "tool": "<full mcp tool name>", "phase": 1, "timestamp": "<ISO-8601>" }`. This is the only phase permitted to record `phase: 1` (or `0`) entries; `smoke-no-mcp-in-dev-phases.sh` fails the run if any entry carries `phase >= 2`. Recording is what makes that BLOCKING contract enforceable - an MCP call left unrecorded defeats the gate, so record every one.
|
|
69
76
|
|
|
@@ -73,6 +80,22 @@ Progress lines:
|
|
|
73
80
|
→ figma evidence: <N> frames captured (tier=<n>, code-connect=<M>, open-questions=<K>)
|
|
74
81
|
```
|
|
75
82
|
|
|
83
|
+
#### Step 1.45 - Reuse discovery (BLOCKING for new services, entities, mappers)
|
|
84
|
+
|
|
85
|
+
Before proposing any new service call, entity or mapper, search for what already
|
|
86
|
+
covers it. Record hits under `state.reuse[]` and cite them in the doc; proposing new
|
|
87
|
+
code over a hit needs a one-line reason.
|
|
88
|
+
|
|
89
|
+
Search for: a **wrapper** over the same endpoint (especially one supplying parameters
|
|
90
|
+
the generated call leaves optional); an **entity** for the same concept (module's
|
|
91
|
+
shared entities first, then siblings); a **mapper** over the same response; a **screen**
|
|
92
|
+
doing the same interaction.
|
|
93
|
+
|
|
94
|
+
Why blocking: one run proposed a new repository over an endpoint a sibling already
|
|
95
|
+
wrapped **with its country parameter**, called the generated method without it, and
|
|
96
|
+
re-invented an entity the module had. Half that branch's commits went to converging
|
|
97
|
+
back. "Copy X and rename it" is the reuse answer, not a hint - name X's files.
|
|
98
|
+
|
|
76
99
|
#### Step 1.5 - External Context Injection (`state.contextLinks[]`)
|
|
77
100
|
|
|
78
101
|
Phase 0 Step 1b catalogued every typed external link from the task description into `state.contextLinks[]`. Phase 1 dispatches each entry to its matching fetcher (crashlytics, fortify, graylog, swagger, confluence, figma, generic-doc) and prepends results under a **Referenced External Sources** section in the analysis prompt - so the agent doesn't re-discover what the ticket already pointed at. `state.graylogContext` is injected there too, as diagnostic context (advisory only). Failures never fatal (a non-zero fetcher exit is marked skipped and the analysis still runs, exactly as for crashlytics); pending refs are advisories. Full dispatch table, exit-code handling, prompt injection shape, log line shape: `$HOME/.claude/multi-agent-refs/features/external-context-injection.md`.
|