@nurix/etna 0.15.6 → 0.15.8
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/bin/etna.js +64 -13
- package/data/harness-index.json +7 -5
- package/data/harnesses/code/CLAUDE.md +3 -7
- package/data/harnesses/code/agents/harness-manager.md +4 -4
- package/data/harnesses/code/agents/maintenance.md +1 -1
- package/data/harnesses/code/harness.json +4 -3
- package/data/harnesses/code/hooks/hooks.json +3 -17
- package/data/harnesses/code/hooks/prompt-recall.js +157 -0
- package/data/harnesses/code/hooks/session-reflect.js +283 -0
- package/data/harnesses/code/skills/distiller/SKILL.md +62 -60
- package/data/harnesses/code/skills/distiller/references/docs-mode.md +21 -21
- package/data/harnesses/code/skills/distiller/references/method.md +41 -41
- package/data/harnesses/code/skills/documentation/references/templates.md +20 -27
- package/data/harnesses/code-fable/CLAUDE.md +138 -0
- package/data/harnesses/code-fable/agents/brainstorm.md +35 -0
- package/data/harnesses/code-fable/agents/change-review.md +249 -0
- package/data/harnesses/code-fable/agents/harness-manager.md +193 -0
- package/data/harnesses/code-fable/agents/maintenance.md +123 -0
- package/data/harnesses/code-fable/agents/performance-review.md +218 -0
- package/data/harnesses/code-fable/agents/spec-mode.md +56 -0
- package/data/harnesses/code-fable/harness.json +7 -0
- package/data/harnesses/code-fable/hooks/hooks.json +27 -0
- package/data/harnesses/code-fable/hooks/lib/redact.js +37 -0
- package/data/harnesses/code-fable/hooks/prompt-recall.js +157 -0
- package/data/harnesses/code-fable/hooks/session-reflect.js +283 -0
- package/data/harnesses/code-fable/rules/general.md +96 -0
- package/data/harnesses/code-fable/rules/nomenclature.md +34 -0
- package/data/harnesses/code-fable/skills/boundary/SKILL.md +262 -0
- package/data/harnesses/code-fable/skills/boundary/references/boundary-taxonomy.md +734 -0
- package/data/harnesses/code-fable/skills/brainstorm/README.md +136 -0
- package/data/harnesses/code-fable/skills/brainstorm/SKILL.md +135 -0
- package/data/harnesses/code-fable/skills/brainstorm/harvest.md +26 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/backlog.md +39 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/build.md +37 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/decisions.md +29 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/doctrine.md +31 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/domain-model.md +25 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/glossary.md +19 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/milestones.md +43 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/non-goals.md +21 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/plan-doc.md +61 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/questions.md +35 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/references.md +28 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/rejected.md +29 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/state.md +8 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/tech.md +23 -0
- package/data/harnesses/code-fable/skills/brainstorm/templates/thesis.md +21 -0
- package/data/harnesses/code-fable/skills/distiller/SKILL.md +219 -0
- package/data/harnesses/code-fable/skills/distiller/references/docs-mode.md +526 -0
- package/data/harnesses/code-fable/skills/distiller/references/method.md +166 -0
- package/data/harnesses/code-fable/skills/documentation/SKILL.md +127 -0
- package/data/harnesses/code-fable/skills/documentation/references/examples.md +193 -0
- package/data/harnesses/code-fable/skills/documentation/references/style-guide.md +288 -0
- package/data/harnesses/code-fable/skills/documentation/references/templates.md +942 -0
- package/data/harnesses/code-fable/skills/workflow-mapper/SKILL.md +430 -0
- package/data/harnesses/code-fable/skills/workflow-mapper/references/patterns.md +214 -0
- package/data/harnesses/discover/CLAUDE.md +180 -0
- package/data/harnesses/{re → discover}/agents/api.md +3 -3
- package/data/harnesses/{re → discover}/agents/codebase.md +3 -3
- package/data/harnesses/{re → discover}/agents/community.md +3 -3
- package/data/harnesses/{re → discover}/agents/deployed-client-bundle.md +21 -15
- package/data/harnesses/{re → discover}/agents/distribution-artifacts.md +13 -12
- package/data/harnesses/{re → discover}/agents/docs.md +3 -3
- package/data/harnesses/{re → discover}/agents/infra-backend-fingerprint.md +3 -3
- package/data/harnesses/{re → discover}/agents/packages.md +3 -3
- package/data/harnesses/{re → discover}/agents/session.md +29 -11
- package/data/harnesses/{re → discover}/agents/website.md +3 -3
- package/data/harnesses/{re → discover}/agents/wire-capture.md +14 -10
- package/data/harnesses/discover/harness.json +7 -0
- package/data/harnesses/{re/rules/re-discovery.md → discover/rules/discovery.md} +86 -17
- package/data/harnesses/{re/rules/re-evaluation.md → discover/rules/evaluation.md} +40 -4
- package/data/harnesses/discover/rules/ingestion.md +551 -0
- package/data/harnesses/discover/rules/self-correction.md +177 -0
- package/data/harnesses/discover/rules/tradecraft.md +532 -0
- package/data/harnesses/hr/CLAUDE.md +91 -0
- package/data/harnesses/hr/harness.json +7 -0
- package/data/harnesses/hr/skills/interview-eval/SKILL.md +118 -0
- package/data/harnesses/hr/skills/interview-eval/TEMPLATE.md +124 -0
- package/data/harnesses/hr/skills/interview-eval/extract_session.py +418 -0
- package/data/harnesses/hr/skills/interview-eval/rubric.md +219 -0
- package/data/harnesses/kb-agi/harness.json +1 -0
- package/package.json +1 -1
- package/data/harnesses/code/hooks/post-commit.js +0 -136
- package/data/harnesses/code/hooks/post-tool-failure.js +0 -136
- package/data/harnesses/code/hooks/session-stop.js +0 -207
- package/data/harnesses/re/CLAUDE.md +0 -146
- package/data/harnesses/re/harness.json +0 -6
- package/data/harnesses/re/rules/re-ingestion.md +0 -327
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
// harness/code/hooks/session-stop.js — SessionEnd hook: append one cheap session-summary ledger entry.
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const fs = require("fs");
|
|
6
|
-
const path = require("path");
|
|
7
|
-
const os = require("os");
|
|
8
|
-
const { execFileSync } = require("child_process");
|
|
9
|
-
const { redact } = require("./lib/redact.js");
|
|
10
|
-
|
|
11
|
-
// Read all of stdin synchronously; returns "" if nothing is piped.
|
|
12
|
-
function readStdin() {
|
|
13
|
-
try {
|
|
14
|
-
return fs.readFileSync(0, "utf8");
|
|
15
|
-
} catch (e) {
|
|
16
|
-
return "";
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Resolve the project root: CLAUDE_PROJECT_DIR env, else payload cwd, else process cwd.
|
|
21
|
-
function resolveProjectDir(payload) {
|
|
22
|
-
return process.env.CLAUDE_PROJECT_DIR || (payload && payload.cwd) || process.cwd();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Run a git command in projectDir; returns trimmed stdout or fallback on any error.
|
|
26
|
-
function git(projectDir, args, fallback) {
|
|
27
|
-
try {
|
|
28
|
-
return execFileSync("git", ["-C", projectDir, ...args], {
|
|
29
|
-
encoding: "utf8",
|
|
30
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
31
|
-
}).trim() || fallback;
|
|
32
|
-
} catch (e) {
|
|
33
|
-
return fallback;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Slug a raw actor name into kebab-case ASCII.
|
|
38
|
-
function slugActor(name) {
|
|
39
|
-
return String(name || "")
|
|
40
|
-
.toLowerCase()
|
|
41
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
42
|
-
.replace(/^-+|-+$/g, "");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Determine the actor: git user.name (slugged) → $USER → "agent".
|
|
46
|
-
function resolveActor(projectDir) {
|
|
47
|
-
const fromGit = slugActor(git(projectDir, ["config", "user.name"], ""));
|
|
48
|
-
if (fromGit) return fromGit;
|
|
49
|
-
const fromEnv = slugActor(process.env.USER || "");
|
|
50
|
-
if (fromEnv) return fromEnv;
|
|
51
|
-
return "agent";
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Truncate a single line to n chars with an ellipsis marker.
|
|
55
|
-
function truncate(text, n) {
|
|
56
|
-
const clean = String(text || "").replace(/\s+/g, " ").trim();
|
|
57
|
-
return clean.length > n ? clean.slice(0, n) + "…" : clean;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Parse the JSONL transcript into a cheap mechanical summary.
|
|
61
|
-
function summarizeTranscript(transcriptPath) {
|
|
62
|
-
const summary = { firstPrompt: "", assistantTurns: 0, files: new Set(), lastAssistant: "", sawCommit: false };
|
|
63
|
-
try {
|
|
64
|
-
if (!transcriptPath || !fs.existsSync(transcriptPath)) return summary;
|
|
65
|
-
const lines = fs.readFileSync(transcriptPath, "utf8").split("\n");
|
|
66
|
-
for (const line of lines) {
|
|
67
|
-
if (!line.trim()) continue;
|
|
68
|
-
let row;
|
|
69
|
-
try {
|
|
70
|
-
row = JSON.parse(line);
|
|
71
|
-
} catch (e) {
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
const msg = row && row.message ? row.message : row;
|
|
75
|
-
const role = (msg && msg.role) || row.type;
|
|
76
|
-
if (role === "user" && !summary.firstPrompt) {
|
|
77
|
-
summary.firstPrompt = extractText(msg);
|
|
78
|
-
}
|
|
79
|
-
if (role === "assistant") {
|
|
80
|
-
summary.assistantTurns += 1;
|
|
81
|
-
const text = extractText(msg);
|
|
82
|
-
if (text) summary.lastAssistant = text;
|
|
83
|
-
collectToolUse(msg, summary);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
} catch (e) {
|
|
87
|
-
// Best-effort summary; ignore parse issues.
|
|
88
|
-
}
|
|
89
|
-
return summary;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Extract plain text from a message whose content is a string or content-block array.
|
|
93
|
-
function extractText(msg) {
|
|
94
|
-
if (!msg || !msg.content) return "";
|
|
95
|
-
if (typeof msg.content === "string") return msg.content;
|
|
96
|
-
if (Array.isArray(msg.content)) {
|
|
97
|
-
return msg.content
|
|
98
|
-
.filter((b) => b && b.type === "text" && typeof b.text === "string")
|
|
99
|
-
.map((b) => b.text)
|
|
100
|
-
.join(" ");
|
|
101
|
-
}
|
|
102
|
-
return "";
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Scan an assistant message's tool_use blocks for edited files and git commits.
|
|
106
|
-
function collectToolUse(msg, summary) {
|
|
107
|
-
if (!msg || !Array.isArray(msg.content)) return;
|
|
108
|
-
for (const block of msg.content) {
|
|
109
|
-
if (!block || block.type !== "tool_use") continue;
|
|
110
|
-
const name = block.name || "";
|
|
111
|
-
const input = block.input || {};
|
|
112
|
-
if (/^(Edit|Write|MultiEdit|NotebookEdit)$/.test(name) && input.file_path) {
|
|
113
|
-
summary.files.add(input.file_path);
|
|
114
|
-
}
|
|
115
|
-
if (name === "Bash" && typeof input.command === "string" && /\bgit\s+commit\b/.test(input.command)) {
|
|
116
|
-
summary.sawCommit = true;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Compute the ledger day-file path for a given actor and date.
|
|
122
|
-
function ledgerPath(projectDir, date, actor) {
|
|
123
|
-
const dir = path.join(projectDir, "docs", "memory", "ledger");
|
|
124
|
-
return { dir, file: path.join(dir, `${date}--${actor}.md`) };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Build the day-file header block.
|
|
128
|
-
function header(date, actor) {
|
|
129
|
-
return `# Ledger — ${date} — ${actor}\nAppend-only event ledger. Raw input to distillation — see docs/memory/.\n`;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Skip if the day-file's last entry was written by this session within the current minute.
|
|
133
|
-
function isDuplicate(file, sessionId, hhmm) {
|
|
134
|
-
try {
|
|
135
|
-
if (!sessionId || !fs.existsSync(file)) return false;
|
|
136
|
-
const text = fs.readFileSync(file, "utf8");
|
|
137
|
-
const idx = text.lastIndexOf("\n## ");
|
|
138
|
-
const tail = idx >= 0 ? text.slice(idx) : text;
|
|
139
|
-
return tail.includes(`session ${sessionId}`) && tail.includes(`## ${hhmm} `);
|
|
140
|
-
} catch (e) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Main: assemble and append one session-summary entry, never blocking.
|
|
146
|
-
function main() {
|
|
147
|
-
const raw = readStdin();
|
|
148
|
-
let payload = {};
|
|
149
|
-
try {
|
|
150
|
-
payload = raw ? JSON.parse(raw) : {};
|
|
151
|
-
} catch (e) {
|
|
152
|
-
payload = {};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const projectDir = resolveProjectDir(payload);
|
|
156
|
-
const actor = resolveActor(projectDir);
|
|
157
|
-
const repo = path.basename(projectDir);
|
|
158
|
-
const branch = git(projectDir, ["rev-parse", "--abbrev-ref", "HEAD"], "-");
|
|
159
|
-
|
|
160
|
-
const now = new Date();
|
|
161
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
162
|
-
const date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
163
|
-
const hhmm = `${pad(now.getHours())}:${pad(now.getMinutes())}`;
|
|
164
|
-
|
|
165
|
-
const summary = summarizeTranscript(payload.transcript_path);
|
|
166
|
-
const sessionId = payload.session_id || "";
|
|
167
|
-
|
|
168
|
-
// Nothing meaningful to record (garbage/empty payload, unreadable transcript) → silent no-op.
|
|
169
|
-
if (summary.assistantTurns === 0 && !summary.firstPrompt) return;
|
|
170
|
-
|
|
171
|
-
const { dir, file } = ledgerPath(projectDir, date, actor);
|
|
172
|
-
if (isDuplicate(file, sessionId, hhmm)) return;
|
|
173
|
-
|
|
174
|
-
const type = summary.sawCommit ? "decision" : summary.assistantTurns > 0 ? "action" : "observation";
|
|
175
|
-
const fileCount = summary.files.size;
|
|
176
|
-
const whatBits = [];
|
|
177
|
-
if (summary.firstPrompt) whatBits.push(`task "${truncate(redact(summary.firstPrompt), 100)}"`);
|
|
178
|
-
whatBits.push(`${summary.assistantTurns} turns`);
|
|
179
|
-
if (fileCount) whatBits.push(`${fileCount} file${fileCount === 1 ? "" : "s"} edited`);
|
|
180
|
-
const what = whatBits.join(", ") || "session ended";
|
|
181
|
-
|
|
182
|
-
const lines = [`## ${hhmm} · ${actor} · ${repo}@${branch}`, `- type: ${type}`, `- what: ${redact(what)}`];
|
|
183
|
-
if (summary.lastAssistant) {
|
|
184
|
-
lines.push(`- why: ${truncate(redact(summary.lastAssistant), 100)}`);
|
|
185
|
-
}
|
|
186
|
-
const refs = [];
|
|
187
|
-
if (sessionId) refs.push(`session ${sessionId}`);
|
|
188
|
-
if (fileCount) refs.push(`${fileCount} files`);
|
|
189
|
-
if (refs.length) lines.push(`- refs: ${redact(refs.join(" · "))}`);
|
|
190
|
-
|
|
191
|
-
const exists = fs.existsSync(file);
|
|
192
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
193
|
-
const block = (exists ? "\n" : header(date, actor) + "\n") + lines.join("\n") + "\n";
|
|
194
|
-
fs.appendFileSync(file, block, "utf8");
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
try {
|
|
198
|
-
main();
|
|
199
|
-
} catch (e) {
|
|
200
|
-
try {
|
|
201
|
-
process.stderr.write(`session-stop hook: ${e && e.message ? e.message : e}\n`);
|
|
202
|
-
} catch (e2) {
|
|
203
|
-
// Nothing more we can do.
|
|
204
|
-
}
|
|
205
|
-
} finally {
|
|
206
|
-
process.exit(0);
|
|
207
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# Product Reverse-Engineering — Orchestrator
|
|
2
|
-
|
|
3
|
-
This is the **policy** half of the `re` harness. The plugin ships the capabilities (11
|
|
4
|
-
dimension-dumper agents + 3 `re-*` rules, one per pipeline phase); this file drives them. Together they reverse-engineer a
|
|
5
|
-
product across every surface it exposes and dump a structured, provenance-tracked corpus into
|
|
6
|
-
`research/<target>/`.
|
|
7
|
-
|
|
8
|
-
A run is four modes, in order: **Discovery → Ingestion → Evaluation → Self-correction.** The main
|
|
9
|
-
session drives all four — Ingestion and Evaluation fan out parallel sub-agents, and a sub-agent
|
|
10
|
-
cannot spawn further sub-agents.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Access is a capability vector (the front gate)
|
|
15
|
-
|
|
16
|
-
A target's access is four orthogonal axes, each `{value, confidence, evidence}` — and the vector
|
|
17
|
-
decides which dimensions are reachable and which extraction method each uses:
|
|
18
|
-
|
|
19
|
-
| Axis | Values | Unlocks | Case |
|
|
20
|
-
|------|--------|---------|------|
|
|
21
|
-
| **source** | full · partial · none | codebase, packages | open-source repo |
|
|
22
|
-
| **runtime** | reachable · gated · none | deployed-client-bundle, api, infra-backend-fingerprint, wire-capture | deployed, no source |
|
|
23
|
-
| **auth** | have-login · none | session | logged-in SaaS |
|
|
24
|
-
| **presence** | rich · thin · none | docs, website, community | — |
|
|
25
|
-
|
|
26
|
-
Targets light several axes at once. The full model + grade→method mapping is in
|
|
27
|
-
`.claude/rules/re-discovery.md`.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## The eleven dimensions → agents
|
|
32
|
-
|
|
33
|
-
| Dimension / agent | | Dimension / agent |
|
|
34
|
-
|---|--|---|
|
|
35
|
-
| `codebase` | | `session` ⚠ |
|
|
36
|
-
| `docs` | | `deployed-client-bundle` |
|
|
37
|
-
| `packages` | | `infra-backend-fingerprint` |
|
|
38
|
-
| `api` (+MCP) | | `wire-capture` ⚠ |
|
|
39
|
-
| `website` | | `distribution-artifacts` |
|
|
40
|
-
| `community` | | |
|
|
41
|
-
|
|
42
|
-
Agent name = dimension name. ⚠ = gated (needs user authorization before dispatch). The catalog —
|
|
43
|
-
detection signals + strategy + per-dimension artifacts — is in `.claude/rules/re-discovery.md`.
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Mode 1 — Discovery
|
|
48
|
-
|
|
49
|
-
Cheap, read-only. Scope the target, grade its access, detect which dimensions it exposes.
|
|
50
|
-
|
|
51
|
-
1. **Scope-feasibility gate** — run the `.claude/rules/re-discovery.md` Part A (scope gate) algorithm: resolve
|
|
52
|
-
identity → ambiguity → ethics → suite-size → primitive → reachability. If the verdict isn't
|
|
53
|
-
`accept`, **halt** (present the narrowing/redirect prompt, or refuse). Write
|
|
54
|
-
`research/<target>/00-scope-verdict.md`.
|
|
55
|
-
2. **Grade the access vector** (the four axes, with evidence) per `re-discovery` (Part B).
|
|
56
|
-
3. **Probe each of the 11 dimensions** (cheap signals only); mark ✅ available / ⚠️ partial /
|
|
57
|
-
❌ absent with evidence. An absent dimension is a finding.
|
|
58
|
-
4. Write `research/<target>/00-recon-plan.md` — frontmatter carries `scope:` + the `access_grade`
|
|
59
|
-
vector; the body is the dimension-availability table + the per-dimension dump plan (warm entry
|
|
60
|
-
points) + the gating/ethics flags.
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Mode 2 — Ingestion
|
|
65
|
-
|
|
66
|
-
Dispatch one dumper per available dimension; dump exhaustively before context is lost. Every dumper
|
|
67
|
-
writes `research/<target>/dimensions/<dim>/_summary.md` (with the **provenance frontmatter** —
|
|
68
|
-
method · confidence · completeness · gaps) + `raw/`, obeying `.claude/rules/re-ingestion.md`.
|
|
69
|
-
|
|
70
|
-
- **Run independents in parallel** — dispatch `docs`, `packages`, `api`, `website`, `community`,
|
|
71
|
-
`deployed-client-bundle`, `infra-backend-fingerprint`, `distribution-artifacts` together
|
|
72
|
-
(`subagent_type='<dimension>'`, one message, multiple Agent calls). Seed each dumper with **warm
|
|
73
|
-
entry points (URLs / repos / hosts), not claimed facts** — any fact carried from Discovery (a price,
|
|
74
|
-
a tier name, a version) is tagged `verify:may-be-stale` so the dumper re-derives it instead of
|
|
75
|
-
anchoring on a possibly-stale value. Only one dimension may drive the browser at a time (see
|
|
76
|
-
`re-ingestion` §7 rule 9): the parallel dumpers use WebFetch/curl, leaving Chrome to `session`.
|
|
77
|
-
- **Codebase fan-out** — dispatch `codebase`; it clones + maps + returns a per-package work-list;
|
|
78
|
-
then the main session fans out one reader per substantial package.
|
|
79
|
-
- **Gated dimensions** — `session` and `wire-capture` (rung ≥2) need explicit user authorization
|
|
80
|
-
first (see `re-ingestion` §7). `session` follows `.claude/rules/re-ingestion.md` §9. When `session`
|
|
81
|
-
is authorized, **dispatch the non-browser dumpers in the background (`run_in_background`) and drive
|
|
82
|
-
the gated browser session in the main session concurrently** — they don't contend (Chrome belongs to
|
|
83
|
-
the main session; the dumpers use WebFetch/curl), so the whole of Ingestion runs in parallel.
|
|
84
|
-
- **Shared seam** — bundle/session/wire each contribute to the canonical `raw/api-path-catalog.md`
|
|
85
|
-
with a `source:` column; don't triplicate.
|
|
86
|
-
|
|
87
|
-
Validate each return (`_summary.md` + provenance present). A `blocked`/`partial` return is recorded,
|
|
88
|
-
not blindly re-run.
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## Mode 3 — Evaluation
|
|
93
|
-
|
|
94
|
-
Reconcile the dumps into four cross-dimension rollups under `research/<target>/evaluation/`, plus
|
|
95
|
-
the run `README.md`, **weighting every claim by how it was obtained**. Follow
|
|
96
|
-
`.claude/rules/re-evaluation.md`: read each dimension's provenance frontmatter first; anchor +
|
|
97
|
-
provenance-tag every claim `(api: raw/endpoint-catalog.md · openapi-verbatim · high)`; weight
|
|
98
|
-
(max-of-sources, promote one band only on ≥2 *independent* dimensions, never average); present
|
|
99
|
-
high→fact, low/single-source→tentative, conflict→flagged. The four rollups: `technology-architecture`,
|
|
100
|
-
`product-features`, `data-model-api-surface`, `competitive-positioning`.
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## Mode 4 — Self-correction (the harness improves itself, never silently)
|
|
105
|
-
|
|
106
|
-
Read the finished run (scope verdict, plan, every dimension `_summary.md`, the rollups) and detect
|
|
107
|
-
where the harness under-delivered (method ≠ planned, missing artifacts, low completeness, blocked
|
|
108
|
-
where predicted available). Write **one** file — `research/<target>/04-self-correction-proposal.md`
|
|
109
|
-
— an ordered table of proposed fixes, each routed to its target file (`re-discovery` /
|
|
110
|
-
`re-ingestion` / `re-evaluation` / an agent), with severity, an
|
|
111
|
-
additive/structural flag, and a `research/<target>/…` evidence anchor.
|
|
112
|
-
|
|
113
|
-
**Approval gate:** present the table and STOP — nothing is applied. The user accepts / rejects /
|
|
114
|
-
defers per item. Then the **main session** (not a sub-agent) applies accepted items, flips each row
|
|
115
|
-
to APPLIED, and logs the change. Promote only what the *next, different* target would also hit;
|
|
116
|
-
prefer additive edits; structural edits are flagged, never auto-applied.
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Ethics (non-negotiable)
|
|
121
|
-
|
|
122
|
-
For spec-writing, integration planning, and competitive analysis — **not** credential theft,
|
|
123
|
-
rate-limit bypass, or scraping. Full rules: `.claude/rules/re-ingestion.md` §7.
|
|
124
|
-
|
|
125
|
-
- **Never enter credentials.** The user logs in; `session` and `wire-capture` rung 3 are opt-in.
|
|
126
|
-
- **Redact every secret before writing `raw/`.** Cookies/tokens/JWT-signatures/API-keys never hit disk.
|
|
127
|
-
- **wire-capture** climbs the 3-rung ladder (browser-tap → HAR → mitmproxy); rung 3 is user-run,
|
|
128
|
-
first-party traffic only. Wireshark is not used (TLS ciphertext).
|
|
129
|
-
- **Confirm before any state change or cost.** **No destructive actions, no exfiltration.** Respect TOS/robots.
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## Output contract
|
|
134
|
-
|
|
135
|
-
```
|
|
136
|
-
research/<target>/
|
|
137
|
-
├── 00-scope-verdict.md ← Discovery: accept/narrow/redirect/refuse
|
|
138
|
-
├── 00-recon-plan.md ← Discovery: access_grade + scope + dimension plan
|
|
139
|
-
├── dimensions/<dim>/{_summary.md, raw/} ← Ingestion (session & wire-capture also: captures/, curls.md)
|
|
140
|
-
├── evaluation/{technology-architecture, product-features, data-model-api-surface, competitive-positioning}.md
|
|
141
|
-
├── README.md ← Evaluation: run story + headline findings
|
|
142
|
-
└── 04-self-correction-proposal.md ← Self-correction: proposed harness fixes (approval-gated)
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Cloned repos live in `source/<target>/`. Provenance is the "self-aware" layer: each dump records
|
|
146
|
-
*how* it was obtained; Evaluation weights claims by it. Detailed shapes live in the `re-*` rules.
|