@ijfw/memory-server 1.3.0 → 1.4.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/fixtures/team/book.json +47 -0
- package/fixtures/team/business.json +47 -0
- package/fixtures/team/content.json +47 -0
- package/fixtures/team/design.json +47 -0
- package/fixtures/team/mixed.json +59 -0
- package/fixtures/team/research.json +47 -0
- package/fixtures/team/software.json +47 -0
- package/package.json +1 -9
- package/src/active-extension-writer.js +116 -0
- package/src/blackboard.js +360 -0
- package/src/cli-run.js +91 -0
- package/src/codex-agents.js +177 -0
- package/src/compute/extract.js +3 -0
- package/src/compute/fts5.js +4 -4
- package/src/compute/graph-lock.js +0 -2
- package/src/compute/migrations/003-tier-semantic.js +3 -3
- package/src/compute/runner.js +44 -15
- package/src/compute/schema.sql +1 -1
- package/src/cross-orchestrator-cli.js +974 -13
- package/src/cross-orchestrator.js +9 -1
- package/src/dashboard-client.html +144 -1
- package/src/dashboard-server.js +75 -2
- package/src/design-intelligence.js +721 -0
- package/src/dispatch/colon-syntax.js +31 -3
- package/src/dispatch/domain-manifest.js +251 -0
- package/src/dispatch/extension.js +404 -0
- package/src/dispatch/override.js +221 -0
- package/src/dispatch-planner.js +1 -0
- package/src/dream/runner.mjs +3 -3
- package/src/extension-installer.js +1230 -0
- package/src/extension-manifest-schema.js +301 -0
- package/src/extension-signer.js +740 -0
- package/src/gate-result-formatter.js +95 -0
- package/src/gate-result-schema.js +274 -0
- package/src/gate-result.js +195 -0
- package/src/intent-router.js +2 -0
- package/src/lib/npm-view.js +1 -0
- package/src/memory/fts5.js +3 -3
- package/src/memory/migrations/002-tier-semantic.js +2 -2
- package/src/memory/staleness.js +1 -1
- package/src/memory/tier-promotion.js +6 -6
- package/src/memory/tokenize.js +1 -1
- package/src/memory-feedback.js +188 -0
- package/src/override-manifest-schema.js +146 -0
- package/src/override-resolver.js +699 -0
- package/src/override-use-registry.js +307 -0
- package/src/overrides/presets/academic.md +101 -0
- package/src/overrides/presets/book.md +87 -0
- package/src/overrides/presets/campaign.md +95 -0
- package/src/overrides/presets/screenplay.md +99 -0
- package/src/recovery/checkpoint.js +191 -0
- package/src/redactor.js +2 -0
- package/src/runtime-mediator.js +178 -0
- package/src/sandbox.js +17 -3
- package/src/server.js +94 -2
- package/src/swarm/dispatch-prompt.js +154 -0
- package/src/swarm/planner.js +399 -0
- package/src/swarm/review.js +136 -0
- package/src/swarm/worktree.js +239 -0
- package/src/team/generator.js +119 -0
- package/src/team/schemas.js +341 -0
- package/src/trident/dispatch.js +47 -0
- package/src/update-check.js +1 -1
- package/src/vectors.js +7 -8
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* override-use-registry.js
|
|
3
|
+
*
|
|
4
|
+
* IJFW v1.4.0 Wave 3 / t14 — Cross-Project Override-Use Registry
|
|
5
|
+
*
|
|
6
|
+
* Per F8: replace SHA256 fingerprint + BM25 search with a STRUCTURED
|
|
7
|
+
* registry. When a user has the same overrides active in N+ projects, the
|
|
8
|
+
* prelude can suggest promoting them to user defaults.
|
|
9
|
+
*
|
|
10
|
+
* Storage: ~/.ijfw/state/override-use.json (kept SEPARATE from
|
|
11
|
+
* active-overrides.json per R12 — different concerns. active-overrides.json
|
|
12
|
+
* tracks per-project state for the resolver; this registry tracks
|
|
13
|
+
* cross-project signal for promotion intelligence and can include
|
|
14
|
+
* project_type and other analytic fields the resolver doesn't need).
|
|
15
|
+
*
|
|
16
|
+
* Shape:
|
|
17
|
+
* {
|
|
18
|
+
* "schema_version": "1.0",
|
|
19
|
+
* "projects": {
|
|
20
|
+
* "/abs/path/to/project": {
|
|
21
|
+
* "project_type": "book",
|
|
22
|
+
* "active_overrides": [
|
|
23
|
+
* { "preset": "book", "scope": "project",
|
|
24
|
+
* "applied_at": "ISO-8601" }
|
|
25
|
+
* ]
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* Zero new prod deps. Built-in Node only.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import fs from 'node:fs/promises';
|
|
34
|
+
import path from 'node:path';
|
|
35
|
+
import os from 'node:os';
|
|
36
|
+
|
|
37
|
+
const SCHEMA_VERSION = '1.0';
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Path helpers — read os.homedir()/HOME at call time so tests can swap HOME
|
|
41
|
+
// via process.env between calls.
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
function homeDir() {
|
|
45
|
+
// os.homedir() honours process.env.HOME on POSIX, which is what the smoke
|
|
46
|
+
// test in the t14 brief assumes. Use os.homedir() to keep cross-platform
|
|
47
|
+
// semantics aligned with the rest of the codebase.
|
|
48
|
+
return os.homedir();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function registryPath() {
|
|
52
|
+
return path.join(homeDir(), '.ijfw', 'state', 'override-use.json');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function settingsPath() {
|
|
56
|
+
return path.join(homeDir(), '.ijfw', 'state', 'settings.json');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// IO
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
async function readRegistry() {
|
|
64
|
+
const p = registryPath();
|
|
65
|
+
try {
|
|
66
|
+
const raw = await fs.readFile(p, 'utf8');
|
|
67
|
+
const parsed = JSON.parse(raw);
|
|
68
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
69
|
+
return { schema_version: SCHEMA_VERSION, projects: {} };
|
|
70
|
+
}
|
|
71
|
+
if (!parsed.projects || typeof parsed.projects !== 'object') {
|
|
72
|
+
parsed.projects = {};
|
|
73
|
+
}
|
|
74
|
+
if (!parsed.schema_version) parsed.schema_version = SCHEMA_VERSION;
|
|
75
|
+
return parsed;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
if (err && err.code === 'ENOENT') {
|
|
78
|
+
return { schema_version: SCHEMA_VERSION, projects: {} };
|
|
79
|
+
}
|
|
80
|
+
if (err instanceof SyntaxError) {
|
|
81
|
+
return { schema_version: SCHEMA_VERSION, projects: {} };
|
|
82
|
+
}
|
|
83
|
+
throw err;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function writeRegistry(state) {
|
|
88
|
+
const p = registryPath();
|
|
89
|
+
await fs.mkdir(path.dirname(p), { recursive: true });
|
|
90
|
+
const tmp = `${p}.tmp`;
|
|
91
|
+
await fs.writeFile(tmp, JSON.stringify(state, null, 2), 'utf8');
|
|
92
|
+
await fs.rename(tmp, p);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function readSettings() {
|
|
96
|
+
try {
|
|
97
|
+
const raw = await fs.readFile(settingsPath(), 'utf8');
|
|
98
|
+
const parsed = JSON.parse(raw);
|
|
99
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
100
|
+
} catch {
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// Public API
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Record (or update) an active override for a project in the registry.
|
|
111
|
+
* Idempotent — re-recording the same (project, preset) updates applied_at
|
|
112
|
+
* rather than duplicating the entry.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} projectRoot
|
|
115
|
+
* @param {string} preset
|
|
116
|
+
* @param {string} scope 'base' | 'user' | 'org' | 'project'
|
|
117
|
+
* @param {string} [project_type] auto-detected project type, defaults to
|
|
118
|
+
* whatever is already on file or 'unknown'.
|
|
119
|
+
*/
|
|
120
|
+
export async function recordOverrideUse(projectRoot, preset, scope, project_type) {
|
|
121
|
+
if (typeof projectRoot !== 'string' || !projectRoot) {
|
|
122
|
+
throw new Error('recordOverrideUse: projectRoot must be a non-empty string');
|
|
123
|
+
}
|
|
124
|
+
if (typeof preset !== 'string' || !preset) {
|
|
125
|
+
throw new Error('recordOverrideUse: preset must be a non-empty string');
|
|
126
|
+
}
|
|
127
|
+
if (typeof scope !== 'string' || !scope) {
|
|
128
|
+
throw new Error('recordOverrideUse: scope must be a non-empty string');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const state = await readRegistry();
|
|
132
|
+
const proj = state.projects[projectRoot] || { active_overrides: [] };
|
|
133
|
+
if (!Array.isArray(proj.active_overrides)) proj.active_overrides = [];
|
|
134
|
+
if (project_type && typeof project_type === 'string') {
|
|
135
|
+
proj.project_type = project_type;
|
|
136
|
+
} else if (!proj.project_type) {
|
|
137
|
+
proj.project_type = 'unknown';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const appliedAt = new Date().toISOString();
|
|
141
|
+
const existingIdx = proj.active_overrides.findIndex(
|
|
142
|
+
(o) => o && o.preset === preset
|
|
143
|
+
);
|
|
144
|
+
if (existingIdx >= 0) {
|
|
145
|
+
proj.active_overrides[existingIdx] = {
|
|
146
|
+
...proj.active_overrides[existingIdx],
|
|
147
|
+
preset,
|
|
148
|
+
scope,
|
|
149
|
+
applied_at: appliedAt,
|
|
150
|
+
};
|
|
151
|
+
} else {
|
|
152
|
+
proj.active_overrides.push({ preset, scope, applied_at: appliedAt });
|
|
153
|
+
}
|
|
154
|
+
state.projects[projectRoot] = proj;
|
|
155
|
+
await writeRegistry(state);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Remove a project's record of having an override active. Leaves the project
|
|
160
|
+
* entry in place with an empty active_overrides array so project_type and
|
|
161
|
+
* any other analytic fields persist for future signal.
|
|
162
|
+
*
|
|
163
|
+
* @param {string} projectRoot
|
|
164
|
+
* @param {string} preset
|
|
165
|
+
*/
|
|
166
|
+
export async function removeOverrideUse(projectRoot, preset) {
|
|
167
|
+
const state = await readRegistry();
|
|
168
|
+
const proj = state.projects[projectRoot];
|
|
169
|
+
if (!proj || !Array.isArray(proj.active_overrides)) return;
|
|
170
|
+
proj.active_overrides = proj.active_overrides.filter(
|
|
171
|
+
(o) => !(o && o.preset === preset)
|
|
172
|
+
);
|
|
173
|
+
// Intentionally do NOT delete state.projects[projectRoot] — see jsdoc.
|
|
174
|
+
state.projects[projectRoot] = proj;
|
|
175
|
+
await writeRegistry(state);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Find every project that has `preset` recorded as active.
|
|
180
|
+
*
|
|
181
|
+
* @param {string} preset
|
|
182
|
+
* @returns {Promise<Array<{project: string, project_type: string, applied_at: string}>>}
|
|
183
|
+
*/
|
|
184
|
+
export async function findProjectsWithOverride(preset) {
|
|
185
|
+
const state = await readRegistry();
|
|
186
|
+
const out = [];
|
|
187
|
+
for (const [project, entry] of Object.entries(state.projects || {})) {
|
|
188
|
+
if (!entry || !Array.isArray(entry.active_overrides)) continue;
|
|
189
|
+
const hit = entry.active_overrides.find(
|
|
190
|
+
(o) => o && o.preset === preset
|
|
191
|
+
);
|
|
192
|
+
if (hit) {
|
|
193
|
+
out.push({
|
|
194
|
+
project,
|
|
195
|
+
project_type: entry.project_type || 'unknown',
|
|
196
|
+
applied_at: hit.applied_at,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return out;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Find projects whose recorded override SET is similar (Jaccard) to
|
|
205
|
+
* currentOverrides above threshold. Excludes opts.excludeProject if given.
|
|
206
|
+
*
|
|
207
|
+
* @param {string[]} currentOverrides preset names
|
|
208
|
+
* @param {number} [threshold=0.5]
|
|
209
|
+
* @param {{excludeProject?: string}} [opts]
|
|
210
|
+
* @returns {Promise<Array<{project: string, project_type: string, overrides: string[], similarity: number}>>}
|
|
211
|
+
*/
|
|
212
|
+
export async function findProjectsWithSimilarOverrideSet(
|
|
213
|
+
currentOverrides,
|
|
214
|
+
threshold = 0.5,
|
|
215
|
+
opts = {}
|
|
216
|
+
) {
|
|
217
|
+
if (!Array.isArray(currentOverrides) || currentOverrides.length === 0) {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
const exclude = opts && typeof opts.excludeProject === 'string'
|
|
221
|
+
? opts.excludeProject
|
|
222
|
+
: null;
|
|
223
|
+
const current = new Set(currentOverrides);
|
|
224
|
+
const state = await readRegistry();
|
|
225
|
+
const out = [];
|
|
226
|
+
for (const [project, entry] of Object.entries(state.projects || {})) {
|
|
227
|
+
if (exclude && project === exclude) continue;
|
|
228
|
+
if (!entry || !Array.isArray(entry.active_overrides)) continue;
|
|
229
|
+
const theirs = new Set(
|
|
230
|
+
entry.active_overrides
|
|
231
|
+
.filter((o) => o && typeof o.preset === 'string')
|
|
232
|
+
.map((o) => o.preset)
|
|
233
|
+
);
|
|
234
|
+
if (theirs.size === 0) continue;
|
|
235
|
+
let intersection = 0;
|
|
236
|
+
for (const p of current) if (theirs.has(p)) intersection += 1;
|
|
237
|
+
const union = new Set([...current, ...theirs]).size;
|
|
238
|
+
const similarity = union === 0 ? 0 : intersection / union;
|
|
239
|
+
if (similarity >= threshold) {
|
|
240
|
+
out.push({
|
|
241
|
+
project,
|
|
242
|
+
project_type: entry.project_type || 'unknown',
|
|
243
|
+
overrides: Array.from(theirs),
|
|
244
|
+
similarity,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Sort highest similarity first for deterministic prelude output.
|
|
249
|
+
out.sort((a, b) => b.similarity - a.similarity || a.project.localeCompare(b.project));
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Compose a promote-to-user-defaults suggestion when N+ projects share the
|
|
255
|
+
* current project's override set. Returns null if the threshold is not met.
|
|
256
|
+
*
|
|
257
|
+
* Threshold is configurable via ~/.ijfw/state/settings.json
|
|
258
|
+
* `override_promote_min_matches` (default 3) or opts.minMatches.
|
|
259
|
+
*
|
|
260
|
+
* @param {string} currentProjectRoot
|
|
261
|
+
* @param {string[]} currentOverrides
|
|
262
|
+
* @param {{minMatches?: number, threshold?: number}} [opts]
|
|
263
|
+
* @returns {Promise<null | {message: string, projects: string[], suggestion: string}>}
|
|
264
|
+
*/
|
|
265
|
+
export async function getPromoteSuggestion(currentProjectRoot, currentOverrides, opts = {}) {
|
|
266
|
+
if (!Array.isArray(currentOverrides) || currentOverrides.length === 0) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
const state = await readRegistry();
|
|
270
|
+
const projectCount = Object.keys(state.projects || {}).length;
|
|
271
|
+
if (projectCount < 2) return null;
|
|
272
|
+
|
|
273
|
+
const settings = await readSettings();
|
|
274
|
+
const configuredMin = Number.isInteger(settings.override_promote_min_matches)
|
|
275
|
+
? settings.override_promote_min_matches
|
|
276
|
+
: null;
|
|
277
|
+
const minMatches = Number.isInteger(opts.minMatches)
|
|
278
|
+
? opts.minMatches
|
|
279
|
+
: (configuredMin ?? 3);
|
|
280
|
+
const threshold = typeof opts.threshold === 'number' ? opts.threshold : 0.5;
|
|
281
|
+
|
|
282
|
+
const matches = await findProjectsWithSimilarOverrideSet(
|
|
283
|
+
currentOverrides,
|
|
284
|
+
threshold,
|
|
285
|
+
{ excludeProject: currentProjectRoot }
|
|
286
|
+
);
|
|
287
|
+
if (matches.length < minMatches) return null;
|
|
288
|
+
|
|
289
|
+
const presetList = currentOverrides.slice().sort().join(', ');
|
|
290
|
+
const presetArgs = currentOverrides.slice().sort().join(' ');
|
|
291
|
+
const message =
|
|
292
|
+
`You have [${presetList}] active in ${matches.length} other projects. ` +
|
|
293
|
+
`Consider promoting to user defaults so new projects pick them up automatically.`;
|
|
294
|
+
return {
|
|
295
|
+
message,
|
|
296
|
+
projects: matches.map((m) => m.project),
|
|
297
|
+
suggestion: `ijfw override promote --scope user ${presetArgs}`,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Test seam — internal-only, do not import in production code.
|
|
302
|
+
export const __test = {
|
|
303
|
+
registryPath,
|
|
304
|
+
settingsPath,
|
|
305
|
+
readRegistry,
|
|
306
|
+
writeRegistry,
|
|
307
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: []
|
|
3
|
+
scope: base
|
|
4
|
+
skill: ijfw-critique
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Academic / Research Writing Critique Preset
|
|
8
|
+
|
|
9
|
+
This preset adapts `ijfw-critique` for academic papers, dissertations,
|
|
10
|
+
literature reviews, conference submissions, and grant proposals. It
|
|
11
|
+
replaces the default rubric, evidence, and output-format sections so
|
|
12
|
+
the critique focuses on the standards of scholarly argument.
|
|
13
|
+
|
|
14
|
+
<!-- ijfw-override: rubric -->
|
|
15
|
+
Evaluate the manuscript against these criteria. Score each 1-5 and
|
|
16
|
+
write feedback at the level of detail a reviewer for a respectable
|
|
17
|
+
journal would expect.
|
|
18
|
+
|
|
19
|
+
1. **Argument structure** -- Is there a thesis the rest of the paper
|
|
20
|
+
visibly supports? Can you reconstruct the argument as a numbered
|
|
21
|
+
chain of claims, or does the paper drift between adjacent topics
|
|
22
|
+
without a load-bearing spine?
|
|
23
|
+
2. **Evidence sufficiency** -- For each major claim, is there enough
|
|
24
|
+
data, primary source, or prior result to carry the weight asked of
|
|
25
|
+
it? Distinguish claims that are demonstrated, claims that are
|
|
26
|
+
merely asserted, and claims that are smuggled past the reader.
|
|
27
|
+
3. **Citation density and relevance** -- Are sources cited where the
|
|
28
|
+
reader needs them, not just sprinkled in the introduction? Are
|
|
29
|
+
the cited works the canonical anchors for their claims, or are
|
|
30
|
+
they convenience citations that look right but do not say what is
|
|
31
|
+
implied?
|
|
32
|
+
4. **Definitional precision** -- Are key terms defined before they
|
|
33
|
+
are used, and used consistently after? Watch for slippage between
|
|
34
|
+
neighbouring concepts that the field treats as distinct.
|
|
35
|
+
5. **Methodological transparency** -- Could a reader of the same
|
|
36
|
+
discipline reproduce the analysis from what is on the page?
|
|
37
|
+
Sample size, instrument, coding scheme, inclusion criteria, and
|
|
38
|
+
procedure must be legible.
|
|
39
|
+
6. **Audience appropriate for field** -- Does the prose pitch itself
|
|
40
|
+
to readers of the named field at the named level, without either
|
|
41
|
+
over-explaining undergraduate fundamentals or omitting context a
|
|
42
|
+
sibling subfield would need?
|
|
43
|
+
|
|
44
|
+
The artifact is scholarship. Do not evaluate it as software or as
|
|
45
|
+
marketing; evaluate it as an argument that has to survive informed
|
|
46
|
+
peer scrutiny.
|
|
47
|
+
<!-- ijfw-override-end -->
|
|
48
|
+
|
|
49
|
+
<!-- ijfw-override: evidence -->
|
|
50
|
+
Quote the manuscript itself. For each observation, anchor with one
|
|
51
|
+
or more of these passage types:
|
|
52
|
+
|
|
53
|
+
- The **thesis statement** -- the sentence (often near the end of the
|
|
54
|
+
introduction) that names what the paper is arguing.
|
|
55
|
+
- A **citation pattern** -- two or three nearby in-text citations
|
|
56
|
+
that together reveal whether sourcing is load-bearing or decorative.
|
|
57
|
+
- A **gap-claim** -- a sentence asserting that the literature has
|
|
58
|
+
not yet addressed something. These deserve scrutiny: is the gap
|
|
59
|
+
real, or constructed by narrow framing?
|
|
60
|
+
|
|
61
|
+
Quote 1-2 sentences and give a locator the author can find: section
|
|
62
|
+
heading, paragraph position within the section, or page if the
|
|
63
|
+
manuscript is paginated. Never refer to source lines, files, or
|
|
64
|
+
other software locators; this is a paper.
|
|
65
|
+
<!-- ijfw-override-end -->
|
|
66
|
+
|
|
67
|
+
<!-- ijfw-override: output-format -->
|
|
68
|
+
Return the critique as markdown with these five sections, in this
|
|
69
|
+
order:
|
|
70
|
+
|
|
71
|
+
## Thesis
|
|
72
|
+
|
|
73
|
+
Quote the thesis as written, then restate the argument in your own
|
|
74
|
+
words. If the thesis cannot be located or cannot be paraphrased
|
|
75
|
+
without addition, say so.
|
|
76
|
+
|
|
77
|
+
## Evidence
|
|
78
|
+
|
|
79
|
+
For each major claim, name the evidence the paper offers and judge
|
|
80
|
+
whether it is sufficient. Flag claims that rest on a single source
|
|
81
|
+
where the field expects triangulation.
|
|
82
|
+
|
|
83
|
+
## Method
|
|
84
|
+
|
|
85
|
+
Summarise the method as a reader of the discipline would reconstruct
|
|
86
|
+
it from the page. Note every place a competent reader would still
|
|
87
|
+
have to guess.
|
|
88
|
+
|
|
89
|
+
## Limitations
|
|
90
|
+
|
|
91
|
+
What does the paper acknowledge, and what does it omit that a
|
|
92
|
+
reviewer would press on? Be specific about which population, scope,
|
|
93
|
+
or condition the conclusions cannot legitimately reach.
|
|
94
|
+
|
|
95
|
+
## Missing citations
|
|
96
|
+
|
|
97
|
+
List the works (or kinds of works) the argument needs but does not
|
|
98
|
+
cite. Where possible, name the author or paradigm by surname rather
|
|
99
|
+
than a placeholder; if you cannot, describe the work specifically
|
|
100
|
+
enough that the author can search for it.
|
|
101
|
+
<!-- ijfw-override-end -->
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: []
|
|
3
|
+
scope: base
|
|
4
|
+
skill: ijfw-critique
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Book / Long-form Prose Critique Preset
|
|
8
|
+
|
|
9
|
+
This preset adapts `ijfw-critique` for evaluating manuscripts, chapters,
|
|
10
|
+
short stories, and other long-form prose. It replaces the default
|
|
11
|
+
rubric, evidence, and output-format sections so the critique focuses
|
|
12
|
+
on craft of language rather than software artifacts.
|
|
13
|
+
|
|
14
|
+
<!-- ijfw-override: rubric -->
|
|
15
|
+
Evaluate the prose against these criteria. Score each 1-5 and explain
|
|
16
|
+
in plain language; the writer is not a programmer.
|
|
17
|
+
|
|
18
|
+
1. **Clarity of voice** -- Is the narrator's perspective consistent
|
|
19
|
+
from paragraph to paragraph? Does the voice feel like one mind
|
|
20
|
+
speaking, or does it drift between registers without intent?
|
|
21
|
+
2. **Pacing** -- Do scenes breathe where they should and compress
|
|
22
|
+
where they should? Flag pages where summary smothers scene, or
|
|
23
|
+
where scene drags past its emotional beat.
|
|
24
|
+
3. **Scene specificity** -- Are settings rendered through sensory
|
|
25
|
+
detail that only this scene could have, or does the prose lean on
|
|
26
|
+
generic furniture (a room, a street, a window)?
|
|
27
|
+
4. **Dialogue authenticity** -- Does each character sound distinct
|
|
28
|
+
when their attribution is removed? Are speech rhythms tied to
|
|
29
|
+
biography, mood, and stakes, or do they all sound like the author?
|
|
30
|
+
5. **Character motivation** -- Can the reader name what each
|
|
31
|
+
point-of-view character wants in this passage, and what is in the
|
|
32
|
+
way? If motivation is absent or interchangeable, call it out.
|
|
33
|
+
6. **Sentence variety** -- Are sentences shaped to the moment? Look
|
|
34
|
+
for monotony of length, repeated opening structures, and reliance
|
|
35
|
+
on the same conjunctions or verbs of being.
|
|
36
|
+
|
|
37
|
+
Do not evaluate code quality or technical correctness; the artifact
|
|
38
|
+
is prose. If the writer included code samples inside fiction (a
|
|
39
|
+
hacker character, a thriller subplot), treat them as narrative
|
|
40
|
+
texture, not as systems to audit.
|
|
41
|
+
<!-- ijfw-override-end -->
|
|
42
|
+
|
|
43
|
+
<!-- ijfw-override: evidence -->
|
|
44
|
+
Ground every observation in the manuscript itself. Quote a 1-2
|
|
45
|
+
sentence passage with a chapter and page reference (or section
|
|
46
|
+
heading where pages are absent). Example shape:
|
|
47
|
+
|
|
48
|
+
> Chapter 3, p. 47: "The kitchen smelled like onions and old rain."
|
|
49
|
+
|
|
50
|
+
Then say what the passage does well or fails to do. Never cite by
|
|
51
|
+
file path, function name, or line number; this is a manuscript, not a
|
|
52
|
+
codebase. Avoid bullet-only feedback that floats free of the page --
|
|
53
|
+
the writer needs to find the exact passage you mean.
|
|
54
|
+
|
|
55
|
+
When a pattern repeats across the manuscript, quote two or three
|
|
56
|
+
short examples from different chapters rather than one long block;
|
|
57
|
+
the spread itself is the evidence.
|
|
58
|
+
<!-- ijfw-override-end -->
|
|
59
|
+
|
|
60
|
+
<!-- ijfw-override: output-format -->
|
|
61
|
+
Return the critique as markdown with these four sections, in this
|
|
62
|
+
order:
|
|
63
|
+
|
|
64
|
+
## Voice
|
|
65
|
+
|
|
66
|
+
What does the narrator sound like, and where does that voice waver?
|
|
67
|
+
Quote the clearest example of the voice working, and the clearest
|
|
68
|
+
example of it slipping.
|
|
69
|
+
|
|
70
|
+
## Pacing
|
|
71
|
+
|
|
72
|
+
Map the energy of the passage. Where does it move, where does it
|
|
73
|
+
stall, and what should be cut or expanded? Reference chapters or
|
|
74
|
+
scenes by name.
|
|
75
|
+
|
|
76
|
+
## Specificity
|
|
77
|
+
|
|
78
|
+
Where does the prose earn its world through sensory detail, and where
|
|
79
|
+
does it rely on placeholders? Quote a strong line and a generic line
|
|
80
|
+
side by side.
|
|
81
|
+
|
|
82
|
+
## Suggested cuts
|
|
83
|
+
|
|
84
|
+
List 3-7 specific passages that could be deleted or compressed
|
|
85
|
+
without losing meaning. Quote the opening words of each so the writer
|
|
86
|
+
can find them quickly.
|
|
87
|
+
<!-- ijfw-override-end -->
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: []
|
|
3
|
+
scope: base
|
|
4
|
+
skill: ijfw-critique
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Campaign / Marketing Copy Critique Preset
|
|
8
|
+
|
|
9
|
+
This preset adapts `ijfw-critique` for marketing campaigns, product
|
|
10
|
+
launches, email sequences, sales pages, ad copy, and other
|
|
11
|
+
persuasion-driven artifacts. It replaces the default rubric,
|
|
12
|
+
evidence, and output-format sections so the critique focuses on
|
|
13
|
+
whether the copy moves the reader to act.
|
|
14
|
+
|
|
15
|
+
<!-- ijfw-override: rubric -->
|
|
16
|
+
Evaluate the campaign against these criteria. Score each 1-5 and
|
|
17
|
+
write in language a copywriter or founder will recognise -- not the
|
|
18
|
+
language of software engineering.
|
|
19
|
+
|
|
20
|
+
1. **Call-to-action clarity** -- After the reader finishes, do they
|
|
21
|
+
know exactly one next step? Is the CTA verb-led, specific, and
|
|
22
|
+
placed where momentum is highest, or is it buried, hedged, or
|
|
23
|
+
multi-headed?
|
|
24
|
+
2. **Audience fit** -- Does the copy speak to the named segment in
|
|
25
|
+
their own vocabulary, status concerns, and objections? Generic
|
|
26
|
+
"you" with no anchor is a fail; over-narrow jargon that excludes
|
|
27
|
+
the segment is also a fail.
|
|
28
|
+
3. **Hook strength** -- Does the opening earn the next sentence?
|
|
29
|
+
Test the first 1-2 lines: do they promise something specific
|
|
30
|
+
enough to make the reader stay, or do they warm up before saying
|
|
31
|
+
anything?
|
|
32
|
+
4. **Persuasion arc** -- Is there a recognisable shape (problem,
|
|
33
|
+
stakes, promise, proof, offer, close), and does each beat carry
|
|
34
|
+
weight? Flag missing beats and beats that repeat without adding.
|
|
35
|
+
5. **Channel-appropriate format** -- Email reads like email; a
|
|
36
|
+
landing page reads like a landing page; a paid ad reads like an
|
|
37
|
+
ad. Length, density, and rhythm should match the medium and
|
|
38
|
+
placement.
|
|
39
|
+
6. **Claim defensibility** -- Every superlative ("best", "only",
|
|
40
|
+
"guaranteed") and every number needs a believable source or a
|
|
41
|
+
concrete demonstration nearby. Unsupported claims cost trust.
|
|
42
|
+
|
|
43
|
+
The artifact is copy, not software. Do not evaluate it as if it were
|
|
44
|
+
a product or codebase; evaluate how it sells.
|
|
45
|
+
<!-- ijfw-override-end -->
|
|
46
|
+
|
|
47
|
+
<!-- ijfw-override: evidence -->
|
|
48
|
+
Quote the actual words on the page. Pull out three anchor passages
|
|
49
|
+
for almost every campaign you review:
|
|
50
|
+
|
|
51
|
+
1. The **headline** (or subject line, or ad hook).
|
|
52
|
+
2. The **CTA** in its surrounding sentence.
|
|
53
|
+
3. The **close** -- the final paragraph or sign-off before the CTA.
|
|
54
|
+
|
|
55
|
+
Quote them in full, then say what they do or fail to do. If the
|
|
56
|
+
campaign has multiple sections (hero, social proof, FAQ, footer), name
|
|
57
|
+
the section before the quote so the writer can navigate.
|
|
58
|
+
|
|
59
|
+
Never cite by line number, file path, or any technical locator. The
|
|
60
|
+
campaign is read top to bottom by a human; speak in those terms
|
|
61
|
+
("the second paragraph", "the testimonial block", "the P.S. line").
|
|
62
|
+
<!-- ijfw-override-end -->
|
|
63
|
+
|
|
64
|
+
<!-- ijfw-override: output-format -->
|
|
65
|
+
Return the critique as markdown with these five sections, in this
|
|
66
|
+
order:
|
|
67
|
+
|
|
68
|
+
## Hook
|
|
69
|
+
|
|
70
|
+
Quote the opening line(s). Does it earn the next sentence? What
|
|
71
|
+
would a sharper version look like?
|
|
72
|
+
|
|
73
|
+
## Promise
|
|
74
|
+
|
|
75
|
+
What is the campaign actually offering the reader, in plain language?
|
|
76
|
+
Is the promise specific, believable, and worth their attention?
|
|
77
|
+
|
|
78
|
+
## Proof
|
|
79
|
+
|
|
80
|
+
What proof does the copy bring -- testimonials, case studies,
|
|
81
|
+
numbers, demonstration, third-party validation? Where is proof
|
|
82
|
+
missing where it would land hardest?
|
|
83
|
+
|
|
84
|
+
## CTA
|
|
85
|
+
|
|
86
|
+
Quote every call-to-action verbatim. Are they consistent in
|
|
87
|
+
language? Is the primary CTA unambiguous? Where should it appear
|
|
88
|
+
that it currently does not?
|
|
89
|
+
|
|
90
|
+
## Friction points
|
|
91
|
+
|
|
92
|
+
List the moments the reader is most likely to stall, doubt, or close
|
|
93
|
+
the tab. Quote the exact phrase that creates the friction, and
|
|
94
|
+
suggest a replacement.
|
|
95
|
+
<!-- ijfw-override-end -->
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: []
|
|
3
|
+
scope: base
|
|
4
|
+
skill: ijfw-critique
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Screenplay / Script Critique Preset
|
|
8
|
+
|
|
9
|
+
This preset adapts `ijfw-critique` for film, television, and short-form
|
|
10
|
+
scripts -- features, pilots, episodes, shorts, and stage plays where
|
|
11
|
+
the conventions hold. It replaces the default rubric, evidence, and
|
|
12
|
+
output-format sections so the critique reads like coverage from a
|
|
13
|
+
working development executive, not like a code review.
|
|
14
|
+
|
|
15
|
+
<!-- ijfw-override: rubric -->
|
|
16
|
+
Evaluate the script against these criteria. Score each 1-5 and write
|
|
17
|
+
in the language of a story editor or showrunner.
|
|
18
|
+
|
|
19
|
+
1. **Scene-level conflict** -- Does every scene have a protagonist
|
|
20
|
+
pursuing a tangible want against a tangible obstacle, with the
|
|
21
|
+
scene ending in change (got it, denied, or got something worse)?
|
|
22
|
+
Flag scenes that exist only to deliver information.
|
|
23
|
+
2. **Character agency** -- Do the leads drive events through choices,
|
|
24
|
+
or are they reactive vehicles for the plot? When a character
|
|
25
|
+
acts, can you trace the want and the cost? Passive protagonists
|
|
26
|
+
should be called out, especially in the first and third acts.
|
|
27
|
+
3. **Pacing per act** -- Does each act do its structural work
|
|
28
|
+
(setup, escalation, crisis, climax) at roughly the page count the
|
|
29
|
+
format expects? Flag soggy middles, late inciting incidents, and
|
|
30
|
+
climaxes that arrive without setup paying off.
|
|
31
|
+
4. **Dialogue distinctness per character** -- Cover the character
|
|
32
|
+
names and read three pages aloud: can you still tell who is
|
|
33
|
+
speaking? Flag characters who share vocabulary, rhythm, or
|
|
34
|
+
posture without the script earning the resemblance.
|
|
35
|
+
5. **Visual storytelling** -- Are emotional beats rendered as images,
|
|
36
|
+
blocking, and behaviour, or do characters announce their feelings
|
|
37
|
+
in dialogue? Showing over telling is the rule; flag exposition
|
|
38
|
+
that should be on screen instead of in the mouth.
|
|
39
|
+
6. **Genre conventions** -- Does the script honour or deliberately
|
|
40
|
+
subvert the audience contract of its genre (thriller pace, comedy
|
|
41
|
+
beats, horror dread, procedural structure)? Subversion is fine;
|
|
42
|
+
accidental drift out of genre is not.
|
|
43
|
+
|
|
44
|
+
The artifact is a script. Do not treat it as code or as a marketing
|
|
45
|
+
deck; treat it as something a room will shoot.
|
|
46
|
+
<!-- ijfw-override-end -->
|
|
47
|
+
|
|
48
|
+
<!-- ijfw-override: evidence -->
|
|
49
|
+
Quote the script as it is written, in screenplay shorthand. Three
|
|
50
|
+
anchor types do most of the work:
|
|
51
|
+
|
|
52
|
+
- **Slug lines** -- e.g. `INT. WAREHOUSE -- NIGHT`. Quote the slug
|
|
53
|
+
when calling out scene economy, location bloat, or geography that
|
|
54
|
+
is impossible to shoot.
|
|
55
|
+
- **Action lines** -- the prose between slug and dialogue. Quote
|
|
56
|
+
short passages (one to four lines) to evaluate visual specificity,
|
|
57
|
+
overwriting, or unfilmable description (an internal feeling with
|
|
58
|
+
no behaviour attached).
|
|
59
|
+
- **Dialogue exchanges** -- quote a 2-6 line back-and-forth, with
|
|
60
|
+
character names, to evaluate distinctness, pace, or on-the-nose
|
|
61
|
+
exposition.
|
|
62
|
+
|
|
63
|
+
Anchor each quote with the scene number or slug ("the diner scene on
|
|
64
|
+
p. 22"). Never use software locators; this is industry-standard
|
|
65
|
+
formatted material and should be referenced as such.
|
|
66
|
+
<!-- ijfw-override-end -->
|
|
67
|
+
|
|
68
|
+
<!-- ijfw-override: output-format -->
|
|
69
|
+
Return the critique as markdown with these four sections, in this
|
|
70
|
+
order:
|
|
71
|
+
|
|
72
|
+
## Conflict per scene
|
|
73
|
+
|
|
74
|
+
Walk through the script scene by scene (or in clusters for longer
|
|
75
|
+
scripts) and name the want, obstacle, and change for each. Flag
|
|
76
|
+
every scene that fails this test and propose either a cut or a
|
|
77
|
+
reframe.
|
|
78
|
+
|
|
79
|
+
## Character voices
|
|
80
|
+
|
|
81
|
+
For each principal, characterise their voice in two or three traits
|
|
82
|
+
(diction, rhythm, what they will and will not say). Quote a passage
|
|
83
|
+
where the voice is clearest, and a passage where the character bleeds
|
|
84
|
+
into another. Suggest a fix for the bleed.
|
|
85
|
+
|
|
86
|
+
## Visual specificity
|
|
87
|
+
|
|
88
|
+
Pull the most cinematic moments the script already contains and
|
|
89
|
+
celebrate them. Then list the beats that are currently spoken or
|
|
90
|
+
narrated which should instead be shown. Quote the dialogue or action
|
|
91
|
+
line you would convert.
|
|
92
|
+
|
|
93
|
+
## Pacing
|
|
94
|
+
|
|
95
|
+
Note the page where each act break lands, where the inciting incident
|
|
96
|
+
appears, and where the climax begins. Compare against format
|
|
97
|
+
expectations and call out the lag or rush. Recommend two or three
|
|
98
|
+
specific compressions or expansions.
|
|
99
|
+
<!-- ijfw-override-end -->
|