@mmerterden/multi-agent-pipeline 16.25.1 → 16.27.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +1 -1
  3. package/README.tr.md +1 -1
  4. package/install/templates/claude-hooks.json +32 -1
  5. package/package.json +1 -1
  6. package/pipeline/commands/multi-agent/help/SKILL.md +2 -0
  7. package/pipeline/commands/multi-agent/refactor/SKILL.md +23 -1
  8. package/pipeline/commands/multi-agent/search/SKILL.md +28 -0
  9. package/pipeline/commands/multi-agent/setup/SKILL.md +18 -44
  10. package/pipeline/commands/multi-agent/status/SKILL.md +9 -0
  11. package/pipeline/lib/credential-inventory.sh +142 -18
  12. package/pipeline/lib/fetch-crashlytics.sh +123 -28
  13. package/pipeline/multi-agent-refs/features/url-enrichment.md +1 -1
  14. package/pipeline/multi-agent-refs/keychain.md +65 -20
  15. package/pipeline/multi-agent-refs/knowledge.md +27 -0
  16. package/pipeline/multi-agent-refs/phases/operations.md +7 -1
  17. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +3 -1
  18. package/pipeline/multi-agent-refs/phases/phase-7-report.md +11 -21
  19. package/pipeline/multi-agent-refs/picker-contract.md +1 -1
  20. package/pipeline/multi-agent-refs/refactor/observations.md +81 -0
  21. package/pipeline/multi-agent-refs/setup/firebase.md +151 -0
  22. package/pipeline/schemas/learnings-ledger.schema.json +5 -0
  23. package/pipeline/schemas/prefs.schema.json +31 -3
  24. package/pipeline/schemas/skill-observation.schema.json +73 -0
  25. package/pipeline/scripts/capture-flush.sh +158 -0
  26. package/pipeline/scripts/capture-resume.sh +87 -0
  27. package/pipeline/scripts/crush-json.mjs +283 -0
  28. package/pipeline/scripts/firebase-app-discovery.sh +114 -0
  29. package/pipeline/scripts/keychain-save.sh +5 -8
  30. package/pipeline/scripts/keychain.py +76 -14
  31. package/pipeline/scripts/learn-from-transcripts.mjs +625 -0
  32. package/pipeline/scripts/learning-curve.mjs +22 -4
  33. package/pipeline/scripts/learnings-ledger.mjs +86 -12
  34. package/pipeline/scripts/note-session.sh +187 -0
  35. package/pipeline/scripts/observations.mjs +347 -0
  36. package/pipeline/scripts/offload-ref.sh +45 -2
  37. package/pipeline/scripts/pre-commit-check.sh +31 -1
  38. package/pipeline/scripts/scan-agent-config.sh +12 -3
  39. package/pipeline/scripts/skill-siblings.mjs +187 -0
  40. package/pipeline/scripts/triage-memory.mjs +73 -9
  41. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +23 -1
  42. package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +28 -0
  43. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +37 -6
  44. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +9 -0
package/CHANGELOG.md CHANGED
@@ -16,6 +16,73 @@ Internal file-layout changes that don't affect the slash-command surface are sti
16
16
 
17
17
  ## [Unreleased]
18
18
 
19
+ ## [16.27.0] - 2026-09-10
20
+
21
+ ### Added
22
+
23
+ - **A run that dies before Phase 7 keeps what it learned.** Every durable write - the triage ingest, the ledger distill - lived in Phase 7, and Phase 7 is the phase a run is LEAST likely to reach, as `features/code-graph.md` already admitted in passing. A run killed in Phase 3 threw away every finding it had established, and the next run on the same repo paid to rediscover it.
24
+
25
+ `capture-flush.sh` derives those writes from `triage-output.json` plus `agent-state.json` - no model, idempotent, exit 0 on every path. Phase boundaries call it, a new `SessionEnd` hook calls it with `--if-stale`, and Phase 7 is now the LAST flush rather than the only one. The trigger is deliberately mechanical: a phase transition and a process exit, neither of which needs an agent to notice that a moment qualifies. Measured on a synthetic kill at Phase 3 against the real stores: 3 corpus rows and 1 ledger entry, where before there were none.
26
+
27
+ - **Work done outside a pipeline run is no longer invisible.** `rules/outside-the-pipeline.md` actively sends the user to work outside a run, and nothing captured any of it. `note-session.sh` reads the session's own transcript on `SessionEnd` and keeps the mechanical shape: which tools ran, which commands failed, which calls the user refused. It keeps a command's first word and an exit code - never an argument, never any output - because a transcript is the least-redacted artefact on the machine.
28
+
29
+ - **The pipeline's own friction log** (`observations.mjs`, `refs/refactor/observations.md`, `/multi-agent:refactor backlog`). The learnings ledger records what a run learned about a REPO; nothing recorded what it learned about the PIPELINE, because `/multi-agent:refactor` re-derives every finding from scratch and a friction noticed mid-task is gone by the next run unless it was fixed within the hour.
30
+
31
+ One markdown file per observation; the directory listing is the index, since an index is a second copy of the truth and the second copy goes stale. `scan` reads frontmatter only. Two things it refuses: an empty `siblings_checked` (filled mechanically by the new `skill-siblings.mjs`, which resolves a command's five surfaces - authored, mirrored, and three host trees - because recollection is the faculty that produced the drift), and a `parked` status with no `parked_until`, which is a deferral wearing a friendlier word.
32
+
33
+ - **Lessons the model never noticed** (`learn-from-transcripts.mjs`). Phase 7 asks a subagent to read the run log, which is structurally blind to the repetitions worth catching. This correlates instead of interpreting: a failed read against the read that then worked, an identical invocation that kept failing, a search too narrow, a call refused twice, a file too big to read whole. Dry run by default; `--apply` writes to the ledger stamped `source: transcript-mining` and renders a marked block in `CLAUDE.local.md`.
34
+
35
+ The first version mined 23 candidates from 35 real transcripts and nearly all were noise - shell keywords read as program names, two ordinary failures presented as environment facts. Rebuilt on the exact command text with a threshold of three, it mines 0 from those same transcripts, and the output now reports `toolResultsExamined` alongside the count so "nothing to find" and "the read is broken" stop looking identical.
36
+
37
+ - **Neighbourhood retrieval** (`timeline --anchor` on both stores). Search answers "which rows match"; nothing answered "what else happened around this one", so the only way to ask was to fetch the whole corpus and nobody asked. Both files are append-only, so line adjacency IS chronological adjacency - no index, no timestamp arithmetic. The four retrieval layers and what each costs are now written into `/multi-agent:search` and `refs/knowledge.md`, because the order costs more than the query does.
38
+
39
+ - **Structural offload instead of truncation** (`crush-json.mjs`). `offload-ref.sh` left a pointer plus the last N lines. For a build log the tail is the right stub; for JSON it is the final element and some brackets. Now a JSON payload gets field shape, outliers, and every element carrying an error, with the repetition dropped. Measured on real payloads, single-sample: a `gh api` page 271133 -> 74961 bytes, a 22 MB code graph -> 1.85 MB, and an `npm ls` tree returned unchanged because there was nothing to win. Fail-open throughout: not JSON, code, too small, any error, or any saving under 15% returns the input byte-identical.
40
+
41
+ - **Two measurement columns** in `learning-curve.mjs`: mined lessons per task and offload bytes saved per task, emitted by the two features above. They are kept apart from the model-written lessons on purpose - a single "lessons learned" number can climb while the half that actually prevents a repeat stays flat. `null`, not `0`, when nothing was recorded: no data and a measured zero are different answers.
42
+
43
+ ### Fixed
44
+
45
+ - **A large read was being truncated at exactly 64 KB, silently, and only through a pipe.** `process.exit()` immediately after a `process.stdout.write()` cuts the write at the pipe buffer. Measured: `triage-memory.mjs query --json` returned 117651 bytes to a file and 65536 to a pipe; `learnings-ledger.mjs profile` returned 324056 against 65536. The profile block is injected at the HEAD of a phase prompt, so a large ledger was delivering a truncated, mid-JSON-line profile and nothing said so. 25 call sites now set `process.exitCode` and return, and a gate keeps them that way.
46
+
47
+ - **Concurrent observations shared one id.** Read-the-max-and-add-one gave eight simultaneous adds the same `0001`. The files did not collide, since their slugs differ, so nothing looked wrong - but `resolve --id` then picks whichever the listing returns first and resolves the wrong observation. The id is now claimed with an `O_EXCL` marker.
48
+
49
+ - **Setup merged one hook event and dropped the rest.** The instruction said to deep-merge `hooks.PreToolUse`, so the capture hooks would never have installed - the fix would have shipped inert.
50
+
51
+
52
+ ## [16.26.0] - 2026-09-09
53
+
54
+ ### Fixed
55
+
56
+ - **The credential store mangled every multi-line secret, and the failure surfaced three layers away.** `security` picks its output format from the *content* of the value: anything it deems non-printable - a newline included - comes back as bare hex with no marker, and the reader took that at face value. A Firebase service-account JSON went in and `7b0a2020...` came out, which is neither JSON nor base64, so the Crashlytics fetcher reported a token-exchange error for a credential that was stored perfectly. The write side had the mirror defect: `security -i` is line-oriented, so a newline inside `-w` terminated the command mid-value and the item was never written at all.
57
+
58
+ `keychain.py` now reads with `-g` and decodes on the explicit `0x` marker rather than guessing from shape, and writes with `-X <hex>` so no value can be cut at a newline. Lookup also walks all four attribute conventions (`-a`+`-l`, `-a`+`-s`, `-l`, `-s`) instead of one.
59
+
60
+ - **The base64 assumption that was never true.** `fetch-crashlytics.sh` tried a base64 decode before falling back to raw JSON. Neither branch could ever have fired for the real failure above, and the guess had spread into `keychain.md`, `features/url-enrichment.md` and the `keychainMapping.firebase` schema description, all of which told the reader to store an encoded blob. The store returns what was stored; encoding is its own business. With the decode step gone there is nothing to stage on disk either, so the temp file and its cleanup traps went with it - the service-account JSON now only ever exists in a shell variable.
61
+
62
+ The assumption had spread further than the reader: `keychain-save.sh` base64-encoded a JSON file on the way in and printed a `| base64 -d` hint on the way out, and both setup surfaces told the user to pipe the clipboard through `base64` - so the writer and the reader disagreed and a fresh onboarding produced a credential the fetcher could not use. Worse, two gates had pinned the wrong text: `smoke-url-enrichment.sh` asserted the literal "JSON (base64)" across three files and `smoke-fetchers-offline.sh` fed the fetcher a base64 stub, so the suite was defending the defect. All nine sites now say the same thing, and the gates assert that no surface asks the user to encode it.
63
+
64
+ - **Three ways the credential inventory could lie, all shipped at once.** The inventory prints three columns per credential and each came from a different place with nothing tying them together: `graylog_test` and `usage_ingest` were onboarded by setup and printed "(no capability recorded for this key)"; the `jenkins` probe read `global.hosts.jenkins`, which the schema does not declare and `additionalProperties: false` forbids, so a healthy token was permanently reported as `no-host-configured`; and `appstore_connect_private_key` carried both a probe and a capability line for a mapping that cannot exist, since the `.p8` is a file by design - as the schema says two keys over. Each file was internally consistent, which is why review kept passing them.
65
+
66
+ Capability lines now cover every mappable key including the deprecated aliases, `graylog_test` probes its own host, `hosts.jenkins` is declarable, and the dead `.p8` branch is gone.
67
+
68
+ ### Added
69
+
70
+ - **Crashlytics access is measured, not assumed - three tiers, and the probe says which one is live.** The inventory used to check that the Firebase credential parsed as JSON, call it `well-formed`, and on that basis announce it would pull stack frames. Shape was never the question. A freshly generated `firebase-adminsdk-*` account authenticates perfectly and reads nothing until an Owner grants it a Crashlytics role, which no shape check can see - so the inventory promised evidence the credential could not deliver, and the run that believed it asked the user to paste the trace by hand.
71
+
72
+ `fetch-crashlytics.sh --probe` now answers `tier-1-ready`, `tier-1-no-grant`, `malformed` or `unreachable` by asking IAM what the service account may actually do (`testIamPermissions`), not by calling Crashlytics and interpreting a 403 - a 403 also means a disabled API or an empty project, and those need different fixes. It lives in the fetcher so the JWT exchange has exactly one implementation; a copy in the inventory would be the one that drifts. The inventory adds `tier-2-ready` on top, measured from the host: an interactive `firebase login` session **and** a registered Firebase MCP server, since either half alone reaches nothing.
73
+
74
+ Tier 1 wins whenever both are ready, and that is structural rather than a preference: url-enrichment expands a Crashlytics link found in a Jira ticket with nobody watching, and autopilot has no terminal to log into. A tier needing a browser cannot serve those. `capability_of()` now reads the verdict and says what this credential buys **today** - down to "nothing yet, and here is the one line to send an Owner".
75
+
76
+ - **`refs/setup/firebase.md`** - the three tiers and how each fails, the exact role-request wording, why `firebase login` cannot run inside an agent harness, MCP registration with its three scopes (and why `project`, which commits the server for everyone who clones the repo, is never the default), appId discovery, and the v1alpha caveat written down so that when Google withdraws an undocumented surface the failure is diagnosable rather than mysterious. Setup gained a Step 3c in both surfaces that reads it.
77
+
78
+ - **`firebase-app-discovery.sh` - the repo already knew the appIds.** Every Crashlytics call needs the opaque `1:<n>:ios:<hex>`, and a console URL carries only the bundle id, so the fetcher spent a Management API round trip resolving it on every run. `GoogleService-Info*.plist` and `google-services.json` name both ids; the script reads every match (a repo with several targets has several plists, and they do not all point at one project), skips build outputs, and emits entries shaped for `prefs.global.firebase.accounts[].apps[]`. The fetcher prefers that when present and falls through to the API when absent, so an install that never ran discovery behaves exactly as before.
79
+
80
+ - **An encoding-regression gate.** `smoke-keychain.sh` stored a short ASCII word, which is exactly the value class that never reproduced the bug. It now round-trips a multi-line service-account JSON (and asserts it still *parses*, not merely compares equal), a hex-looking string, embedded quotes and backslashes, non-ASCII, and leading/trailing spaces.
81
+
82
+ - **A gate for the shipped-but-dead script.** `firebase-app-discovery.sh` was written, installed onto every machine by all three hosts, and invoked by nothing: its only mention sat inside a comment in another script. That is the declared-but-inert defect in its purest form - the docs describe a capability, the install carries the code, and nothing connects them. `smoke-consumer-smoke-surface.sh` now checks every shipped script for an actual invoker, and is deliberately picky about what counts: comment lines, JSON schema descriptions, CHANGELOG and ROADMAP entries all name a script without ever running it, and each of those, left in the corpus, made the check pass on the broken state while it was being built.
83
+
84
+ - **A promise/probe/schema consistency gate.** `smoke-credential-key-alignment.sh` now enforces what nothing enforced: every mappable key has a capability line, every probed key has one, no capability is promised for a key the schema cannot map, and every host the probe reads is declarable. It also pins the tier vocabulary across the three files that name it - probe, capability line and user-facing table - so a new tier cannot ship half-wired, no shape-only verdict can come back, and the JWT exchange cannot quietly acquire a second copy.
85
+
19
86
  ## [16.25.1] - 2026-09-09
20
87
 
21
88
  ### Fixed
package/README.md CHANGED
@@ -242,7 +242,7 @@ the one host whose panel spans two vendors, and the triage note says so.
242
242
  | `confluence` | publish analysis / wiki pages | 7 |
243
243
  | `figma` + `figma_mcp` | fetch design context | analysis only |
244
244
  | `fortify` | security-scan findings gate | 4 |
245
- | `firebase` | Firebase config (base64 JSON) for Firebase projects | as needed |
245
+ | `firebase` | Firebase service-account JSON for Firebase projects | as needed |
246
246
  | `jenkins` | CI trigger / status | build / deploy |
247
247
  | `npm` | package publish (mostly CI) | release |
248
248
  | `appstore_connect_*` | TestFlight / App Store pre-submission validation (optional, iOS) | `testflight-validation` |
package/README.tr.md CHANGED
@@ -243,7 +243,7 @@ triage notu bunu belirtir.
243
243
  | `confluence` | analiz / wiki sayfaları yayınla | 7 |
244
244
  | `figma` + `figma_mcp` | design context çek | yalnızca analiz |
245
245
  | `fortify` | security-scan bulgu kapısı | 4 |
246
- | `firebase` | Firebase projeleri için Firebase config (base64 JSON) | gerektiğinde |
246
+ | `firebase` | Firebase projeleri için servis hesabı JSON | gerektiğinde |
247
247
  | `jenkins` | CI tetikleme / durum | build / deploy |
248
248
  | `npm` | paket publish (çoğunlukla CI) | release |
249
249
  | `appstore_connect_*` | TestFlight / App Store pre-submission doğrulaması (opsiyonel, iOS) | `testflight-validation` |
@@ -1,5 +1,5 @@
1
1
  {
2
- "_readme": "Recommended Claude Code hooks for multi-agent-pipeline. Merge the `hooks` object into your ~/.claude/settings.json to make these deterministic, OS-enforced PreToolUse gates real (exit 2 blocks the tool call) rather than prompt-level hopes. Three gates ship here: (1) a staged-diff secret scan on git commit (pre-commit-check.sh); (2) an agent-guard on git commit + git push (agent-guard.sh) that blocks AI/assistant attribution in commit messages and force-push to a protected branch (main/master/develop); (3) a read-size gate on Read and Bash (check-read-size.sh), which inspects Read plus the shell commands that read a file whole (cat/head/tail/sed) and returns immediately for everything else, which routes an oversized read to a cheap worker instead of the caller's own rung. The first two inspect what a run WRITES; the third inspects what it pays to READ, and it is inert until `prefs.global.bulkRead.mode` is set to observe or enforce - so merging this block changes nothing until you opt in. All three are self-contained, fail-open on internal error, never execute the inspected command, and need no run-specific arguments, which is why they are naturally PreToolUse hooks. The other deterministic gates (evidence, consensus, intent, learnings) take run-specific arguments and are phase-enforced by the pipeline instead. multi-agent:setup offers to merge this block.",
2
+ "_readme": "Recommended Claude Code hooks for multi-agent-pipeline. Merge the `hooks` object into your ~/.claude/settings.json to make these deterministic, OS-enforced PreToolUse gates real (exit 2 blocks the tool call) rather than prompt-level hopes. Three PreToolUse gates ship here: (1) a staged-diff secret scan on git commit (pre-commit-check.sh); (2) an agent-guard on git commit + git push (agent-guard.sh) that blocks AI/assistant attribution in commit messages and force-push to a protected branch (main/master/develop); (3) a read-size gate on Read and Bash (check-read-size.sh), which inspects Read plus the shell commands that read a file whole (cat/head/tail/sed) and returns immediately for everything else, which routes an oversized read to a cheap worker instead of the caller's own rung. The first two inspect what a run WRITES; the third inspects what it pays to READ, and it is inert until `prefs.global.bulkRead.mode` is set to observe or enforce - so merging this block changes nothing until you opt in. All three are self-contained, fail-open on internal error, never execute the inspected command, and need no run-specific arguments, which is why they are naturally PreToolUse hooks. The other deterministic gates (evidence, consensus, intent, learnings) take run-specific arguments and are phase-enforced by the pipeline instead. Two capture hooks ship alongside them, and they are the reason a killed run no longer loses what it learned: (4) SessionEnd runs capture-flush.sh --if-stale, which writes a run's triage findings and durable learnings into the per-repo stores when the run never reached Phase 7 - previously every persistent write lived in Phase 7, the phase a run is LEAST likely to reach; the same hook runs note-session.sh, which records the mechanical shape of a NON-pipeline session (tools used, commands that failed, calls the user refused) so work done outside a run stops vanishing. (5) SessionStart runs capture-resume.sh, which prints at most two lines: an unfinished run and how to resume it, and a stale pipeline-observation queue. Neither capture hook calls a model, neither reads a payload - note-session.sh keeps a command's first word and an exit code, never an argument or any output - and both exit 0 on every path, because a hook that fails a session over bookkeeping is worse than the bookkeeping it protects. multi-agent:setup offers to merge this block.",
3
3
  "hooks": {
4
4
  "PreToolUse": [
5
5
  {
@@ -41,6 +41,37 @@
41
41
  }
42
42
  ]
43
43
  }
44
+ ],
45
+ "SessionEnd": [
46
+ {
47
+ "hooks": [
48
+ {
49
+ "type": "command",
50
+ "command": "bash $HOME/.claude/scripts/capture-flush.sh --if-stale --quiet",
51
+ "timeout": 20,
52
+ "statusMessage": "Persisting what this run learned..."
53
+ },
54
+ {
55
+ "type": "command",
56
+ "command": "bash $HOME/.claude/scripts/note-session.sh",
57
+ "timeout": 20,
58
+ "statusMessage": "Noting this session..."
59
+ }
60
+ ]
61
+ }
62
+ ],
63
+ "SessionStart": [
64
+ {
65
+ "matcher": "startup|resume|clear|compact",
66
+ "hooks": [
67
+ {
68
+ "type": "command",
69
+ "command": "bash $HOME/.claude/scripts/capture-resume.sh",
70
+ "timeout": 10,
71
+ "statusMessage": "Checking for unfinished runs..."
72
+ }
73
+ ]
74
+ }
44
75
  ]
45
76
  }
46
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "16.25.1",
3
+ "version": "16.27.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",
@@ -127,6 +127,7 @@ Post-Hoc & Side-Channel:
127
127
  /multi-agent:search Cross-task log search with smart ranking; --semantic queries triage corpus
128
128
  /multi-agent:scan Skill security scan against tiered pattern catalog
129
129
  /multi-agent:refactor Best practices + bug hunt + upstream drift + toolkit MCP research -> one plan, approval, dev + sync
130
+ /multi-agent:refactor backlog Decide the friction already recorded about the pipeline itself, nothing re-derived
130
131
  /multi-agent:store-ready [repo] [--archive=|--ipa=|--aab=|--apk=] [--skip-sweep] Pre-submission store readiness, iOS + Android, local-only: three symmetric gates per platform plus the running-app sweep. A skipped gate is never a pass. Validates only, never uploads.
131
132
  /multi-agent:testflight-validation [repo] [--ipa=|--archive=] iOS-pinned alias of :store-ready. Same three gates, one implementation.
132
133
  /multi-agent:ios-coding-standard [module] Audit an iOS module against the 99-rule coding-standard registry -> remediation
@@ -399,6 +400,7 @@ Post-Hoc & Side-Channel:
399
400
  /multi-agent:search Task log'larında akıllı arama; --semantic triage corpus'unu sorgular
400
401
  /multi-agent:scan Skill güvenlik taraması (tiered pattern catalog)
401
402
  /multi-agent:refactor Uyarlanmış best-practice + bug avı + upstream-drift + multi-agent-toolkit MCP araştırması -> tek plan, onay, dev + sync
403
+ /multi-agent:refactor backlog Pipeline'ın kendisi hakkında kaydedilmiş sürtünmeyi karara bağlar, sıfırdan türetmez
402
404
  /multi-agent:store-ready [repo] [--archive=|--ipa=|--aab=|--apk=] [--skip-sweep] Yükleme öncesi store hazırlığı, iOS + Android, yalnızca lokal: platform başına 3 simetrik kapı artı çalışan-app sweep'i. Atlanan kapı asla pass sayılmaz. Sadece doğrular, asla yüklemez.
403
405
  /multi-agent:testflight-validation [repo] [--ipa=|--archive=] :store-ready'nin iOS alias'ı. Aynı 3 kapı, tek implementasyon.
404
406
  /multi-agent:ios-coding-standard [modül] Bir iOS modülünü 99 kurallık kodlama-standardı registry'sine göre denetler -> düzeltme
@@ -10,7 +10,7 @@ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, AskUserQuestion, WebF
10
10
 
11
11
  Deep-analyses the current project, extracts the global best-practices worth adopting (adapted to our stack), hunts real bugs and improvement areas, checks whether any skills we derived from an upstream source have drifted, researches the companion multi-agent-toolkit MCP server against current MCP practice, scores everything, drafts a single prioritized plan, asks the user for approval, applies the approved items, and asks about sync at the end.
12
12
 
13
- **Input**: $ARGUMENTS (optional - area to focus on: "security", "performance", "tests", "bugs", "best-practices", "drift", "multi-agent-toolkit", etc.)
13
+ **Input**: $ARGUMENTS (optional - `backlog` runs Step 0e alone; otherwise an area to focus on: "security", "performance", "tests", "bugs", "best-practices", "drift", "multi-agent-toolkit", etc.)
14
14
 
15
15
  ## Flow
16
16
 
@@ -132,6 +132,14 @@ Each line is one run: `{ t, id, u, c, rp, ph, v, errs[] }`. The `errs[]` entries
132
132
 
133
133
  This band mirrors the admin dashboard's "Gelişim alanları" panel, but reads the local ledger so it needs no auth and works offline. If `$ARGUMENTS` names a focus area, still read the ledger - a recurring run error in that area is the strongest possible signal.
134
134
 
135
+ Then read what the transcripts themselves record, which is the half no model noticed:
136
+
137
+ ```bash
138
+ node "$HOME/.claude/scripts/learn-from-transcripts.mjs" --json
139
+ ```
140
+
141
+ It correlates rather than interprets - a failed read against the read that then worked, an identical invocation that kept failing, a search that was too narrow, a call the user refused twice, a file too big to read whole. Dry run by default; `--apply` writes them to the learnings ledger as `source: transcript-mining` and renders a marked block in `CLAUDE.local.md`. Zero candidates alongside a non-zero `toolResultsExamined` means there was nothing to find; zero of both means the read is broken.
142
+
135
143
  Output (plan band F):
136
144
 
137
145
  ```
@@ -147,6 +155,20 @@ Rules for this band:
147
155
  - Never quote a user's identity as blame. The `u` field is for counting distinct affected users, not for naming anyone in the plan.
148
156
  - If the ledger is empty or absent, skip band F silently - it is additive signal, never a gate.
149
157
 
158
+ ## Step 0e: BACKLOG - friction this pipeline already noticed
159
+
160
+ Every other band in this command derives its findings from scratch, which is right for a sweep and has one consequence nobody chose: a friction noticed mid-task is gone by the next run unless it was fixed within the hour. Most are not, because stopping mid-task to fix them is the wrong call. So they are written down when noticed and decided here.
161
+
162
+ ```bash
163
+ node "$HOME/.claude/scripts/observations.mjs" scan --status open --json
164
+ ```
165
+
166
+ Exit 3 is `SCAN BROKEN` - files on disk, none parsed. That is a broken reader, not an empty queue: halt the band and say so rather than reporting "0 open".
167
+
168
+ Split every open observation into actionable / sibling-propagation / to-decline, and resolve the sibling surfaces mechanically with `skill-siblings.mjs`, never from memory - a command is authored in `commands/`, mirrored into `skills/shared/core/`, and installed again into three host trees, so a fix applied to one copy drifts from the rest with every gate still green. Output as plan band G, same table shape as the other bands.
169
+
170
+ `/multi-agent:refactor backlog` runs this band alone. The full sweep is unchanged and still includes it. Buckets, the status vocabulary, why `parked` needs a named unblocking event, and how to write an observation: `$HOME/.claude/multi-agent-refs/refactor/observations.md`.
171
+
150
172
  ## Step 1: SCAN
151
173
 
152
174
  ```
@@ -75,6 +75,34 @@ JSON mode - for embedded automation:
75
75
  }
76
76
  ```
77
77
 
78
+ ## Four layers, and what each one costs
79
+
80
+ Retrieval is cheap or expensive depending on which layer answers, and the order
81
+ matters more than the query does. Filter first, fetch second - inverting these
82
+ is how a single lookup eats a phase's whole context budget.
83
+
84
+ | # | Call | Returns | Rough cost per hit |
85
+ |---|---|---|---|
86
+ | 1 | `search` / `--semantic` | pointers: id, file, one-line issue | ~50-100 tokens |
87
+ | 2 | `timeline --anchor <id>` | the rows recorded around one hit | ~50-100 tokens each |
88
+ | 3 | `show --id <id>` | one full row | ~500-1000 tokens |
89
+ | 4 | the offloaded artefact behind a `[[ref:<id>]]` | the raw payload | thousands |
90
+
91
+ Never start at layer 3 or 4. Narrow at layer 1, widen at layer 2 only around the
92
+ hits that survived, and fetch full rows only for the handful that are actually
93
+ going to be read. A `show` on twenty ids costs as much as the entire search that
94
+ found them and answers a question nobody asked.
95
+
96
+ Layer 2 is the one that gets forgotten. A finding rarely stands alone: the same
97
+ review pass produced its neighbours, and those are usually what makes an old row
98
+ legible. Both stores answer it, and the corpus is append-only so line adjacency
99
+ IS chronological adjacency:
100
+
101
+ ```bash
102
+ node "$HOME/.claude/scripts/triage-memory.mjs" timeline --anchor T:<id> --before 3 --after 3
103
+ node "$HOME/.claude/scripts/learnings-ledger.mjs" timeline --anchor L:<id> --before 3 --after 3
104
+ ```
105
+
78
106
  ## Steps
79
107
 
80
108
  1. **Run the script:**
@@ -119,6 +119,8 @@ Standard key names - the ones to use when creating a NEW key - live in `$HOM
119
119
 
120
120
  > The four App Store Connect entries are **iOS-only and optional** - skipping them all reports Gate 2 of `/multi-agent:store-ready` as `SKIPPED`, never as a pass. Two hold identifiers rather than secrets and one holds a keychain ITEM NAME, yet all four go through the mapping layer so every credential is read the same way. Tiers, the role constraint that decides which to offer first, and the onboarding mechanics: Step 3b and `$HOME/.claude/multi-agent-refs/setup/app-store-connect.md`.
121
121
 
122
+ > The `firebase` entry is **optional and any-platform**. Discovery maps a stored service-account JSON like any other credential but cannot see what decides whether Crashlytics is readable: a fresh `firebase-adminsdk-*` account authenticates perfectly and holds no Crashlytics role. Step 3c measures the tier rather than assuming it.
123
+
122
124
  **1c. Resolution logic (per service):**
123
125
 
124
126
  For each service in the table above, follow this order:
@@ -344,20 +346,20 @@ For JSON file (Firebase) - same clipboard flow, JSON content never lands in ar
344
346
  ```
345
347
  Open the Service Account JSON, copy its FULL contents to your clipboard,
346
348
  then press Enter.
347
- (Contents will be base64-encoded and saved to Keychain automatically)
349
+ (Contents are saved to the Keychain exactly as issued)
348
350
 
349
351
  Press Enter when ready...
350
352
  ```
351
353
 
352
354
  Pipeline runs silently:
353
355
  ```bash
354
- pbpaste | base64 | ~/.claude/lib/credential-store.sh set "<KEY_NAME>" "$(cat)"
356
+ pbpaste | ~/.claude/lib/credential-store.sh set "<KEY_NAME>" "$(cat)"
355
357
  pbcopy < /dev/null # clear clipboard
356
358
  ```
357
359
 
358
360
  Linux substitutes: `xclip -selection clipboard -o` or `wl-paste` for `pbpaste`; matching clear command for `pbcopy < /dev/null`. The shell driver detects platform and routes accordingly (see `~/.claude/lib/credential-store.sh`).
359
361
 
360
- **Firebase repeats per project.** Teams own several Firebase projects (legacy plus redesign, staging plus prod), each with its own key, and a crash URL from the second one used to fail the `project_id` check as if it were misconfigured. After each saved key, read `project_id` from the decoded JSON (never ask) and offer another round: `Saved: <project_id>. Add another Firebase project? [y/N]`.
362
+ **Firebase repeats per project.** Teams own several Firebase projects (legacy plus redesign, staging plus prod), each with its own key, and a crash URL from the second one used to fail the `project_id` check as if it were misconfigured. After each saved key, read `project_id` from the stored JSON (never ask) and offer another round: `Saved: <project_id>. Add another Firebase project? [y/N]`.
361
363
 
362
364
  - Every key appends `{projectId, keychainKey, label?}` to `prefs.global.firebase.accounts`; the first one also fills `keychainMapping.firebase`, so a one-project setup is unchanged.
363
365
  - Keys after the first are named `${USER}_Firebase_Access_Json_<projectId>` so they cannot collide.
@@ -421,6 +423,10 @@ This builds `platformIdentityRouting` incrementally - no separate Step 7 neede
421
423
 
422
424
  Runs inside Step 3 alongside the other missing credentials. The four `appstore_connect_*` entries, their non-secret handling (three hold identifiers / a keychain item name, not pasteable secrets), the API-key vs Apple-ID tier picker, and the verification probes live in `$HOME/.claude/multi-agent-refs/setup/app-store-connect.md`. Read that file when the user opts into App Store Connect onboarding; on Skip, nothing is written.
423
425
 
426
+ ### Step 3c - Firebase / Crashlytics onboarding (optional)
427
+
428
+ Runs inside Step 3. Measure first - `bash "$HOME/.claude/lib/fetch-crashlytics.sh" --probe` answers `tier-1-ready` / `tier-1-no-grant` / `malformed` / `unreachable` - then ask by that answer, never blind. Store the JSON as issued; never base64 it. Skip writes nothing. Then offer appId discovery: `bash "$HOME/.claude/scripts/firebase-app-discovery.sh" <repo> --json` reads the pairs the repo already carries, for `firebase.accounts[].apps[]` - it saves a round trip per run; skipping costs nothing. The picker, both tiers, the role-request wording and the v1alpha caveat: `$HOME/.claude/multi-agent-refs/setup/firebase.md`.
429
+
424
430
  ### Step 3.5 - Host Prompt (embedded in Token Save Flow)
425
431
 
426
432
  **Not a standalone step** - runs inline at the end of the Token Save Flow whenever the saved token belongs to a **hosted service** (Jira, Confluence, Bitbucket, Fortify, Graylog) AND the host is not yet in `prefs.global.hosts`. Firebase tokens skip this step - Crashlytics is always on Google's fixed domains and `project_id` is embedded in the service-account JSON.
@@ -685,40 +691,11 @@ Glob matching semantics (Phase 0 implementation):
685
691
 
686
692
  ### Cross-Platform Notes (Step 1-9)
687
693
 
688
- The credential store is platform-agnostic - every read/write goes through `~/.claude/lib/credential-store.sh`, which dispatches to the right backend (`security` on macOS, `secret-tool` on Linux, PowerShell `CredentialManager` on Windows). On macOS / Linux the shell driver delegates to `~/.claude/scripts/keychain.py` for deterministic behaviour. You almost never need the platform-native commands directly.
689
-
690
- Clipboard helpers (`pbpaste`, `pbcopy`) are macOS-specific - for Copilot CLI on Linux substitute:
691
-
692
- | macOS command | Linux equivalent | Notes |
693
- |---|---|---|
694
- | `pbpaste` | `xclip -selection clipboard -o` (X11) or `wl-paste` (Wayland) | Install with `apt install xclip` or `apt install wl-clipboard` |
695
- | `pbcopy < /dev/null` | `xclip -selection clipboard < /dev/null` or `wl-copy --clear` | Same intent: clear clipboard after token paste |
696
-
697
- If you need to bypass the helper (debugging, raw inspection), the underlying platform commands are documented at the top of `$HOME/.claude/lib/credential-store.sh`. Otherwise stay on the helper - it keeps secrets off argv (stdin sentinel `-`) and writes both `-l` and `-s` attributes on macOS.
698
-
699
- If no backend is available, setup falls back to a plain-text prompt + a warning that the token is **not persisted** - pipeline phases will re-ask each session.
694
+ Every read and write goes through `~/.claude/lib/credential-store.sh`, which dispatches to the right backend per platform; stay on the helper rather than the native commands. The backend table, the Linux clipboard substitutes for `pbpaste` / `pbcopy`, and what happens when no backend exists: `$HOME/.claude/multi-agent-refs/keychain.md` "Cross-platform mechanics".
700
695
 
701
696
  ### Token -> Source Mapping
702
697
 
703
- Standard key names (used when creating NEW tokens). Discovery may find existing keys under different names - that's fine, the mapping in preferences handles it.
704
-
705
- Standard key names and token types: `$HOME/.claude/multi-agent-refs/keychain.md` "Standard key names". Where to generate each one:
706
-
707
- | Service ID | Where to Get |
708
- |------------|---------------|
709
- | `jira` | Jira -> Profile -> Personal Access Tokens (VPN required) |
710
- | `bitbucket_token` | Bitbucket -> Personal settings -> App passwords |
711
- | `bitbucket_user` | Bitbucket profile username (plain text, not a PAT) |
712
- | `github` | GitHub Settings -> Tokens (scopes: repo, read:org, project) |
713
- | `confluence` | Confluence -> Profile -> Personal Access Tokens (VPN required) |
714
- | `figma` | Figma Developer Settings (max 90 days). Tier 2 / REST. Prompt copy: "Figma Personal Access Token (for Tier 2)". |
715
- | `figma_mcp` | Automatic via Claude Code Figma MCP remote auth. Tier 1 / MCP. Prompt copy: "Figma MCP token (for Tier 1)". |
716
- | `fortify` | Fortify SSC -> Token Management (VPN required) |
717
- | `graylog` | Graylog -> System -> Users and Teams -> Edit Tokens (VPN required) |
718
- | `graylog_test` | Same page on the TEST instance; optional |
719
- | `firebase` | Firebase Console -> Project settings -> Service accounts -> Generate new private key. One key per Firebase project; `project_id` is parsed from the decoded JSON, never asked. |
720
- | `jenkins` | Jenkins -> User -> Configure -> API Token |
721
- | Git Identities | Stored in `$HOME/.claude/multi-agent-preferences.json`, not Keychain |
698
+ Standard key names are a convention for NEW tokens; discovery may find existing keys under other names, and the mapping in preferences handles that. The key names, the token types and where to generate each one all live in one table: `$HOME/.claude/multi-agent-refs/keychain.md` "Standard key names". Git identities are stored in preferences, never in the credential store.
722
699
 
723
700
  ### Inline Token Save Pattern
724
701
 
@@ -733,17 +710,14 @@ pbcopy < /dev/null # clear clipboard
733
710
  ~/.claude/lib/credential-store.sh set "<SERVICE_NAME>" "<VALUE>"
734
711
 
735
712
  # JSON file from clipboard (preferred - no file path leaks into history)
736
- pbpaste | base64 | ~/.claude/lib/credential-store.sh set "<SERVICE_NAME>" "$(cat)"
713
+ pbpaste | ~/.claude/lib/credential-store.sh set "<SERVICE_NAME>" "$(cat)"
737
714
  pbcopy < /dev/null
738
715
 
739
716
  # JSON file from disk (fallback when clipboard backend unavailable)
740
- ~/.claude/lib/credential-store.sh set "<SERVICE_NAME>" "$(base64 < /path/to/file.json)"
717
+ ~/.claude/lib/credential-store.sh set "<SERVICE_NAME>" "$(cat /path/to/file.json)"
741
718
 
742
- # Read
719
+ # Read - a JSON value comes back exactly as it was stored, newlines included
743
720
  ~/.claude/lib/credential-store.sh get "<SERVICE_NAME>"
744
-
745
- # Decode JSON
746
- ~/.claude/lib/credential-store.sh get "<SERVICE_NAME>" | base64 -d
747
721
  ```
748
722
 
749
723
  For maximum stdin hygiene (the secret never lands on argv / shell history), use the Python helper directly with the `-` sentinel:
@@ -815,11 +789,11 @@ All tokens are optional in the sense that every service can be answered with Ski
815
789
 
816
790
  ### Step 8 - Enforcement hooks (optional, Claude Code)
817
791
 
818
- Offer to make the three hookable gates HARD (a non-zero exit blocks the tool call). The block ships at `install/templates/claude-hooks.json`: secret scan, agent-guard, read-size gate.
792
+ Offer to merge `install/templates/claude-hooks.json`: three `PreToolUse` gates that block on a non-zero exit (secret scan, agent-guard, read-size) plus two capture hooks that block nothing (`SessionEnd`, `SessionStart`). What each does: `$HOME/.claude/multi-agent-refs/picker-contract.md`.
819
793
 
820
- - Ask (picker): "Install the pipeline's PreToolUse gates into `~/.claude/settings.json`?" Default Yes.
821
- - On Yes, deep-merge the template's `hooks.PreToolUse` (preserve existing hooks; never duplicate a matcher already calling the same script).
822
- - Say what the merge does NOT cover: only these three need no run-specific arguments, so only these three are hookable; the rest are phase-enforced.
794
+ - Ask (picker): "Install the pipeline's hooks into `~/.claude/settings.json`?" Default Yes.
795
+ - On Yes, deep-merge EVERY event in the template's `hooks` object, not `PreToolUse` alone - merging one event silently drops the capture hooks, and a run killed before Phase 7 then loses its findings exactly as it did before they existed. Preserve existing hooks; never duplicate a matcher already calling the same script.
796
+ - Say what the merge does NOT cover: only the three gates need no run-specific arguments, so only they are hookable; the rest are phase-enforced.
823
797
  - Say what it does not turn on: the read-size gate is inert until `prefs.global.bulkRead.mode` is set. Recommend `observe` first. Why, and the Phase 3 exemption: `$HOME/.claude/multi-agent-refs/picker-contract.md`.
824
798
 
825
799
  ### Step 9 - Default stack plugin enablement
@@ -34,6 +34,15 @@ Show every active and completed task as a table.
34
34
  💡 log #1 | resume #N | kill #N
35
35
  ```
36
36
 
37
+ 6. **What is waiting to be learned** (one line, only when non-zero):
38
+
39
+ ```bash
40
+ node "$HOME/.claude/scripts/learn-from-transcripts.mjs" --json 2>/dev/null
41
+ node "$HOME/.claude/scripts/observations.mjs" scan --status open --json 2>/dev/null
42
+ ```
43
+
44
+ Report `N lesson(s) minable from transcripts - /multi-agent:refactor to review` and `N open pipeline observation(s)` when either count is above zero, and print nothing when both are zero. Neither runs a model and neither writes anything: the miner is dry-run by default. Zero candidates alongside a non-zero `toolResultsExamined` means there is nothing to find; zero of both means the read is broken, and that is worth saying rather than reporting a clean queue.
45
+
37
46
  5. **Quick command hints** - based on state:
38
47
  - Paused task → suggest `resume #N`
39
48
  - Done task → suggest `log #N`