@mmerterden/multi-agent-pipeline 16.25.0 → 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.
- package/CHANGELOG.md +77 -0
- package/README.md +1 -1
- package/README.tr.md +1 -1
- package/install/templates/claude-hooks.json +32 -1
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/help/SKILL.md +2 -0
- package/pipeline/commands/multi-agent/refactor/SKILL.md +23 -1
- package/pipeline/commands/multi-agent/search/SKILL.md +28 -0
- package/pipeline/commands/multi-agent/setup/SKILL.md +18 -44
- package/pipeline/commands/multi-agent/status/SKILL.md +9 -0
- package/pipeline/lib/credential-inventory.sh +142 -18
- package/pipeline/lib/fetch-crashlytics.sh +123 -28
- package/pipeline/multi-agent-refs/features/url-enrichment.md +1 -1
- package/pipeline/multi-agent-refs/features/visual-evidence.md +5 -0
- package/pipeline/multi-agent-refs/keychain.md +65 -20
- package/pipeline/multi-agent-refs/knowledge.md +27 -0
- package/pipeline/multi-agent-refs/phases/operations.md +7 -1
- package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +3 -1
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +1 -8
- package/pipeline/multi-agent-refs/phases/phase-7-report.md +11 -21
- package/pipeline/multi-agent-refs/picker-contract.md +1 -1
- package/pipeline/multi-agent-refs/refactor/observations.md +81 -0
- package/pipeline/multi-agent-refs/setup/firebase.md +151 -0
- package/pipeline/schemas/learnings-ledger.schema.json +5 -0
- package/pipeline/schemas/prefs.schema.json +31 -3
- package/pipeline/schemas/skill-observation.schema.json +73 -0
- package/pipeline/scripts/capture-flush.sh +158 -0
- package/pipeline/scripts/capture-resume.sh +87 -0
- package/pipeline/scripts/crush-json.mjs +283 -0
- package/pipeline/scripts/firebase-app-discovery.sh +114 -0
- package/pipeline/scripts/keychain-save.sh +5 -8
- package/pipeline/scripts/keychain.py +76 -14
- package/pipeline/scripts/learn-from-transcripts.mjs +625 -0
- package/pipeline/scripts/learning-curve.mjs +22 -4
- package/pipeline/scripts/learnings-ledger.mjs +86 -12
- package/pipeline/scripts/note-session.sh +187 -0
- package/pipeline/scripts/observations.mjs +347 -0
- package/pipeline/scripts/offload-ref.sh +45 -2
- package/pipeline/scripts/pre-commit-check.sh +31 -1
- package/pipeline/scripts/scan-agent-config.sh +12 -3
- package/pipeline/scripts/skill-siblings.mjs +187 -0
- package/pipeline/scripts/triage-memory.mjs +73 -9
- package/pipeline/skills/.skill-manifest.json +1 -1
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +23 -1
- package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +28 -0
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +37 -6
- package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +9 -0
|
@@ -129,6 +129,64 @@ def _ensure_backend() -> str:
|
|
|
129
129
|
return info["platform"]
|
|
130
130
|
|
|
131
131
|
|
|
132
|
+
def _decode_security_password(stderr: bytes) -> Optional[str]:
|
|
133
|
+
"""Pull the secret out of `security ... -g` stderr and decode it.
|
|
134
|
+
|
|
135
|
+
`-w` cannot be used to read a secret this store may hold. It prints any value
|
|
136
|
+
containing a byte outside plain printable ASCII as BARE HEX with no marker,
|
|
137
|
+
which is indistinguishable from a secret that is itself hex - and 40-character
|
|
138
|
+
hex API tokens are exactly what lives here. Guessing from the shape would
|
|
139
|
+
corrupt them. `-g` marks the encoded form with an `0x` prefix, so the decision
|
|
140
|
+
is read off the output instead of inferred:
|
|
141
|
+
|
|
142
|
+
multi-line value -> password: 0x6C696E65310A6C696E6532 "line1\\012line2"
|
|
143
|
+
hex-looking value -> password: "deadbeefcafe1234"
|
|
144
|
+
|
|
145
|
+
Two shapes, measured rather than assumed:
|
|
146
|
+
- `0x<HEX>` present -> the hex is authoritative; a quoted trailer may follow
|
|
147
|
+
or may be absent entirely (an all-non-ASCII value prints hex only).
|
|
148
|
+
- no `0x` -> the value sits between the first and last double quote. Inner
|
|
149
|
+
quotes are NOT escaped by `security` (`he"llo` prints as `"he"llo"`), so
|
|
150
|
+
first-to-last is the correct span and unescaping would be wrong.
|
|
151
|
+
|
|
152
|
+
The secret is parsed in-process and returned to the caller. It is never
|
|
153
|
+
logged, never placed in an exception message, and never passed as an argv
|
|
154
|
+
element.
|
|
155
|
+
"""
|
|
156
|
+
for raw in stderr.split(b"\n"):
|
|
157
|
+
if not raw.startswith(b"password: "):
|
|
158
|
+
continue
|
|
159
|
+
body = raw[len(b"password: "):].rstrip(b"\r")
|
|
160
|
+
if body.startswith(b"0x"):
|
|
161
|
+
hex_digits = body[2:].split(b" ", 1)[0]
|
|
162
|
+
try:
|
|
163
|
+
return bytes.fromhex(hex_digits.decode("ascii")).decode("utf-8", errors="replace")
|
|
164
|
+
except ValueError:
|
|
165
|
+
return None
|
|
166
|
+
first = body.find(b'"')
|
|
167
|
+
last = body.rfind(b'"')
|
|
168
|
+
if first != -1 and last > first:
|
|
169
|
+
return body[first + 1:last].decode("utf-8", errors="replace")
|
|
170
|
+
return body.decode("utf-8", errors="replace")
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _macos_find(args: list[str]) -> Optional[str]:
|
|
175
|
+
"""One `find-generic-password -g` lookup; None when the item is absent.
|
|
176
|
+
|
|
177
|
+
Trailing newlines are stripped, which is what the `-w` path did before and
|
|
178
|
+
what every consumer already assumes: a newline on the end of a token is an
|
|
179
|
+
artifact of pasting it, and it breaks an HTTP header the moment it survives.
|
|
180
|
+
A value whose trailing newline is meaningful is not something this store has
|
|
181
|
+
ever been able to return.
|
|
182
|
+
"""
|
|
183
|
+
rc, _, err = _run(["/usr/bin/security", "find-generic-password", *args, "-g"])
|
|
184
|
+
if rc != 0:
|
|
185
|
+
return None
|
|
186
|
+
value = _decode_security_password(err)
|
|
187
|
+
return None if value is None else value.rstrip("\n")
|
|
188
|
+
|
|
189
|
+
|
|
132
190
|
def get(label: str, account: Optional[str] = None) -> Optional[str]:
|
|
133
191
|
"""Lookup by label first, then by service name. Two coexisting conventions:
|
|
134
192
|
- User's manually-added tokens (e.g. mmerterden_Vercel_Access_Token) use -l (label).
|
|
@@ -137,19 +195,16 @@ def get(label: str, account: Optional[str] = None) -> Optional[str]:
|
|
|
137
195
|
pf = _ensure_backend()
|
|
138
196
|
acct = _account_default(account)
|
|
139
197
|
if pf == "macos":
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
rc, out, _ = _run(["/usr/bin/security", "find-generic-password", "-s", label, "-w"])
|
|
151
|
-
if rc == 0:
|
|
152
|
-
return out.decode("utf-8", errors="replace").rstrip("\n")
|
|
198
|
+
for args in (
|
|
199
|
+
["-a", acct, "-l", label],
|
|
200
|
+
["-a", acct, "-s", label],
|
|
201
|
+
# account-agnostic last resort - some entries were written without -a
|
|
202
|
+
["-l", label],
|
|
203
|
+
["-s", label],
|
|
204
|
+
):
|
|
205
|
+
value = _macos_find(args)
|
|
206
|
+
if value is not None:
|
|
207
|
+
return value
|
|
153
208
|
return None
|
|
154
209
|
# linux / secret-tool - store under both `label` and `service` schema attrs
|
|
155
210
|
rc, out, _ = _run(["secret-tool", "lookup", "label", label, "account", acct])
|
|
@@ -173,9 +228,16 @@ def set_(label: str, value: str, account: Optional[str] = None) -> None:
|
|
|
173
228
|
def quote(text: str) -> str:
|
|
174
229
|
return text.replace("\\", "\\\\").replace('"', '\\"')
|
|
175
230
|
|
|
231
|
+
# The secret goes in as `-X <hex>`, not `-w "<text>"`. `security -i`
|
|
232
|
+
# tokenizes ONE command per line, so a newline inside the value ends the
|
|
233
|
+
# command and the remainder is read as further commands - which is how a
|
|
234
|
+
# service-account JSON turned into "security: unknown command" instead of
|
|
235
|
+
# a stored credential. Hex is single-line by construction and byte-exact,
|
|
236
|
+
# and it stays on stdin, so the argv exposure this branch exists to avoid
|
|
237
|
+
# is still avoided.
|
|
176
238
|
command = (
|
|
177
239
|
f'add-generic-password -U -a "{quote(acct)}" -l "{quote(label)}" '
|
|
178
|
-
f'-s "{quote(label)}" -
|
|
240
|
+
f'-s "{quote(label)}" -X {value.encode("utf-8").hex()}\n'
|
|
179
241
|
)
|
|
180
242
|
rc, _, err = _run(["/usr/bin/security", "-i"], input_value=command.encode("utf-8"))
|
|
181
243
|
if rc != 0:
|