@ericrisco/rsc 0.1.15 → 0.1.17
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/README.md +2 -2
- package/manifest.json +1 -1
- package/package.json +4 -4
- package/skills/author-skill/references/rsc-conventions.md +8 -4
- package/skills/harness/references/wiki-protocol.md +2 -1
- package/targets/claude.js +29 -22
- package/targets/index.js +13 -7
- package/targets/session-start.mjs +49 -0
- package/targets/worklog-checkpoint.mjs +26 -0
- package/targets/session-start.sh +0 -43
- package/targets/worklog-checkpoint.sh +0 -27
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ Run it inside any project and describe what you want. Working on the catalog
|
|
|
71
71
|
itself? Clone and link:
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
git clone https://github.com/ericrisco/
|
|
74
|
+
git clone https://github.com/ericrisco/rsc-harness.git ~/rsc-skills
|
|
75
75
|
cd ~/rsc-skills && npm install && npm link
|
|
76
76
|
```
|
|
77
77
|
|
|
@@ -273,7 +273,7 @@ duplicated. The wizard asks which ones; `--target a,b` does it non-interactively
|
|
|
273
273
|
|
|
274
274
|
| Target | Skill destination (→ `.rsc/skills/<id>/`) | Always-on detector |
|
|
275
275
|
| --- | --- | --- |
|
|
276
|
-
| `claude` | `.claude/skills
|
|
276
|
+
| `claude` | `.claude/skills/<id>/` → symlink (copy on Windows) | SessionStart hook in `.claude/settings.json` |
|
|
277
277
|
| `codex` | `.codex/rsc/<id>/` → symlink | block in `AGENTS.md` |
|
|
278
278
|
| `copilot` | `.github/rsc/<id>/` → symlink | block in `.github/copilot-instructions.md` |
|
|
279
279
|
| `cursor` | `.cursor/rules/<id>.mdc` (converted) | always-apply rule |
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ericrisco/rsc",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "Eric Risco's agent-skills catalog as a granular, self-recommending CLI installer.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
],
|
|
48
48
|
"license": "MIT",
|
|
49
49
|
"author": "Eric Risco",
|
|
50
|
-
"homepage": "https://github.com/ericrisco/
|
|
50
|
+
"homepage": "https://github.com/ericrisco/rsc-harness#readme",
|
|
51
51
|
"repository": {
|
|
52
52
|
"type": "git",
|
|
53
|
-
"url": "git+https://github.com/ericrisco/
|
|
53
|
+
"url": "git+https://github.com/ericrisco/rsc-harness.git"
|
|
54
54
|
},
|
|
55
55
|
"bugs": {
|
|
56
|
-
"url": "https://github.com/ericrisco/
|
|
56
|
+
"url": "https://github.com/ericrisco/rsc-harness/issues"
|
|
57
57
|
},
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"access": "public"
|
|
@@ -49,10 +49,14 @@ profiles: [core, full] # optional: named-profile membership
|
|
|
49
49
|
|
|
50
50
|
## Invocation
|
|
51
51
|
|
|
52
|
-
There are no bundles and no `/<bundle>:<id>` namespacing.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
There are no bundles and no `/<bundle>:<id>` namespacing. Most targets install a
|
|
53
|
+
skill under their own rsc folder (e.g. `.codex/rsc/<id>/`), reached from that
|
|
54
|
+
assistant's instructions file. **Claude is the exception:** Claude Code only
|
|
55
|
+
discovers project skills one level under `.claude/skills/`, so rsc skills install
|
|
56
|
+
**flat** at `.claude/skills/<id>/SKILL.md` (a nested `.claude/skills/rsc/<id>/`
|
|
57
|
+
is never discovered). A skill is invoked by its `name`. The `suggest` detector is
|
|
58
|
+
always installed (the floor) and proposes installing any skill a task needs via
|
|
59
|
+
`npx @ericrisco/rsc add <id>`.
|
|
56
60
|
|
|
57
61
|
## Wiring steps for a new skill
|
|
58
62
|
|
|
@@ -388,7 +388,8 @@ generalizes the SDD session-summary convention to *any* work.
|
|
|
388
388
|
|
|
389
389
|
- **Hook — `PreCompact` / `SessionEnd`** (Claude Code): fires right before context
|
|
390
390
|
is lost or the session ends. The hook only *reminds*; the agent writes the
|
|
391
|
-
worklog (Karpathy: the LLM writes). Wired by `targets/` → `.rsc/worklog-checkpoint.
|
|
391
|
+
worklog (Karpathy: the LLM writes). Wired by `targets/` → `.rsc/worklog-checkpoint.mjs`
|
|
392
|
+
(run via `node`, so it works on Windows too).
|
|
392
393
|
- **Explicit milestone**: after a commit or a shipped feature, capture a worklog.
|
|
393
394
|
- **Daily curation automation**: distills any pending worklog raw on a timer (see
|
|
394
395
|
Continuous Improvement and `daily-curation-automation.md`).
|
package/targets/claude.js
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync,
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, rmSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { linkOrCopy } from './index.js';
|
|
5
5
|
|
|
6
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
6
8
|
export function writeSkill(id, fromDir, toPath) {
|
|
9
|
+
// Migrate away from the legacy nested layout (.claude/skills/rsc/<id>) that
|
|
10
|
+
// Claude Code never discovered — it only reads .claude/skills/<name>/SKILL.md.
|
|
11
|
+
// toPath is now .claude/skills/<id>; drop the stale rsc/ sibling if present.
|
|
12
|
+
const legacy = join(dirname(toPath), 'rsc');
|
|
13
|
+
if (existsSync(legacy)) rmSync(legacy, { recursive: true, force: true });
|
|
7
14
|
return linkOrCopy(fromDir, toPath);
|
|
8
15
|
}
|
|
9
16
|
|
|
10
|
-
// SessionStart runs a project-local session-start.
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
+
// SessionStart runs a project-local session-start.mjs via `node`: it prints
|
|
18
|
+
// suggest's always-on body, an onboarding banner when the workspace has no harness
|
|
19
|
+
// profile yet, and an auto-ingest nudge when the inbox has un-ingested material. We
|
|
20
|
+
// invoke with `node` (not bash) so the hook runs on Windows too. We materialize the
|
|
21
|
+
// script next to the shared base and point the hook at it. Any prior rsc SessionStart
|
|
22
|
+
// entry (the old `cat …/suggest/SKILL.md` form, or a previous `.sh`/`.mjs` script
|
|
23
|
+
// form) is dropped before we add the current one — idempotent, migrating legacy and
|
|
24
|
+
// bash-era hooks in place. Other (non-rsc) SessionStart hooks are preserved.
|
|
17
25
|
export function wireHook(paths) {
|
|
18
|
-
const scriptDest = join(paths.projectRoot, '.rsc', 'session-start.
|
|
26
|
+
const scriptDest = join(paths.projectRoot, '.rsc', 'session-start.mjs');
|
|
19
27
|
mkdirSync(dirname(scriptDest), { recursive: true });
|
|
20
|
-
copyFileSync(join(
|
|
21
|
-
chmodSync(scriptDest, 0o755);
|
|
28
|
+
copyFileSync(join(HERE, 'session-start.mjs'), scriptDest);
|
|
22
29
|
|
|
23
30
|
const suggestMd = `${paths.skillDir('suggest')}/SKILL.md`;
|
|
24
|
-
const cmd = `
|
|
31
|
+
const cmd = `node "${scriptDest}" "${suggestMd}" "${paths.projectRoot}"`;
|
|
25
32
|
|
|
26
33
|
const file = paths.hookTarget;
|
|
27
34
|
const settings = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : {};
|
|
@@ -29,23 +36,23 @@ export function wireHook(paths) {
|
|
|
29
36
|
settings.hooks.SessionStart ||= [];
|
|
30
37
|
settings.hooks.SessionStart = settings.hooks.SessionStart.filter((e) => {
|
|
31
38
|
const s = JSON.stringify(e);
|
|
32
|
-
|
|
39
|
+
// drop legacy cat-form and any prior session-start script (.sh from the bash era, or .mjs)
|
|
40
|
+
return !s.includes('skills/rsc/suggest') && !s.includes('.rsc/session-start.');
|
|
33
41
|
});
|
|
34
42
|
settings.hooks.SessionStart.push({ hooks: [{ type: 'command', command: cmd }] });
|
|
35
43
|
|
|
36
44
|
// Worklog checkpoint: PreCompact + SessionEnd run a project-local
|
|
37
|
-
// worklog-checkpoint.
|
|
38
|
-
// session into 02-DOCS/raw/worklog/ (the work-driven on-ramp). Silent when
|
|
39
|
-
// workspace has no harness wiki. Registered idempotently on both events, with
|
|
40
|
-
// any prior rsc worklog-checkpoint entry dropped first.
|
|
41
|
-
const wlDest = join(paths.projectRoot, '.rsc', 'worklog-checkpoint.
|
|
42
|
-
copyFileSync(join(
|
|
43
|
-
|
|
44
|
-
const wlCmd = `bash "${wlDest}" "${paths.projectRoot}"`;
|
|
45
|
+
// worklog-checkpoint.mjs via `node` that reminds the agent to capture what we did
|
|
46
|
+
// this session into 02-DOCS/raw/worklog/ (the work-driven on-ramp). Silent when
|
|
47
|
+
// the workspace has no harness wiki. Registered idempotently on both events, with
|
|
48
|
+
// any prior rsc worklog-checkpoint entry (.sh or .mjs) dropped first.
|
|
49
|
+
const wlDest = join(paths.projectRoot, '.rsc', 'worklog-checkpoint.mjs');
|
|
50
|
+
copyFileSync(join(HERE, 'worklog-checkpoint.mjs'), wlDest);
|
|
51
|
+
const wlCmd = `node "${wlDest}" "${paths.projectRoot}"`;
|
|
45
52
|
for (const event of ['PreCompact', 'SessionEnd']) {
|
|
46
53
|
settings.hooks[event] ||= [];
|
|
47
54
|
settings.hooks[event] = settings.hooks[event].filter(
|
|
48
|
-
(e) => !JSON.stringify(e).includes('.rsc/worklog-checkpoint.
|
|
55
|
+
(e) => !JSON.stringify(e).includes('.rsc/worklog-checkpoint.'),
|
|
49
56
|
);
|
|
50
57
|
settings.hooks[event].push({ hooks: [{ type: 'command', command: wlCmd }] });
|
|
51
58
|
}
|
package/targets/index.js
CHANGED
|
@@ -11,16 +11,22 @@ export function baseDir(id, cwd = process.cwd()) {
|
|
|
11
11
|
return join(cwd, '.rsc', 'skills', id);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
// Point an assistant's skill folder at the shared base
|
|
15
|
-
//
|
|
16
|
-
//
|
|
14
|
+
// Point an assistant's skill folder at the shared base. On macOS/Linux a relative
|
|
15
|
+
// symlink avoids duplication. On Windows we copy real files: relative `dir`
|
|
16
|
+
// symlinks require Developer Mode/admin and are not reliably followed by skill
|
|
17
|
+
// discovery, so correctness wins over de-duplication. Idempotent: replaces any
|
|
18
|
+
// existing link/dir at toPath.
|
|
17
19
|
export function linkOrCopy(fromDir, toPath) {
|
|
18
20
|
mkdirSync(dirname(toPath), { recursive: true });
|
|
19
21
|
try { lstatSync(toPath); rmSync(toPath, { recursive: true, force: true }); } catch { /* nothing there */ }
|
|
20
|
-
|
|
21
|
-
symlinkSync(relative(dirname(toPath), fromDir), toPath, 'dir');
|
|
22
|
-
} catch {
|
|
22
|
+
if (process.platform === 'win32') {
|
|
23
23
|
cpSync(fromDir, toPath, { recursive: true });
|
|
24
|
+
} else {
|
|
25
|
+
try {
|
|
26
|
+
symlinkSync(relative(dirname(toPath), fromDir), toPath, 'dir');
|
|
27
|
+
} catch {
|
|
28
|
+
cpSync(fromDir, toPath, { recursive: true });
|
|
29
|
+
}
|
|
24
30
|
}
|
|
25
31
|
return [toPath];
|
|
26
32
|
}
|
|
@@ -31,7 +37,7 @@ export function linkOrCopy(fromDir, toPath) {
|
|
|
31
37
|
// is a single converted file, not a linked directory.
|
|
32
38
|
const SPEC = {
|
|
33
39
|
// JSON-hook + linked skill dirs
|
|
34
|
-
claude: { root: '.claude/skills
|
|
40
|
+
claude: { root: '.claude/skills', hook: '.claude/settings.json', adapter: 'claude' },
|
|
35
41
|
// Converted .mdc rules
|
|
36
42
|
cursor: { root: '.cursor/rules', hook: '.cursor/rules/rsc-suggest.mdc', adapter: 'cursor', skillExt: '.mdc' },
|
|
37
43
|
// AGENTS.md family — all read the same root AGENTS.md
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// rsc SessionStart payload (claude). Wired by targets/claude.js as `node ...` so
|
|
3
|
+
// it runs on every platform including Windows (no bash dependency).
|
|
4
|
+
// argv[2] = absolute path to suggest's SKILL.md argv[3] = absolute project root
|
|
5
|
+
// Always emits suggest's always-on body; appends an onboarding banner when the
|
|
6
|
+
// workspace has no harness profile yet, and an auto-ingest nudge when there is
|
|
7
|
+
// un-ingested material waiting in the inbox.
|
|
8
|
+
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
|
|
11
|
+
const suggestMd = process.argv[2];
|
|
12
|
+
const root = process.argv[3] || process.cwd();
|
|
13
|
+
|
|
14
|
+
try { process.stdout.write(readFileSync(suggestMd, 'utf8')); } catch { /* missing → emit nothing */ }
|
|
15
|
+
|
|
16
|
+
const profile = join(root, '02-DOCS', 'wiki', 'harness', 'user-profile.md');
|
|
17
|
+
const optout = join(root, '.rsc', '.no-harness');
|
|
18
|
+
if (!existsSync(profile) && !existsSync(optout)) {
|
|
19
|
+
process.stdout.write(`
|
|
20
|
+
===== rsc onboarding =====
|
|
21
|
+
Fresh setup: 02-DOCS/wiki/harness/user-profile.md is missing.
|
|
22
|
+
ACTION: invoke \`init\` now (first contact: technical level + accompaniment dial) before the task.
|
|
23
|
+
If the user does not want a harness here: create .rsc/.no-harness
|
|
24
|
+
==========================
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Auto-Ingest nudge: when a harness wiki exists and the inbox holds a real file
|
|
29
|
+
// (anything other than README.md / dotfiles / the _processed archive), tell the
|
|
30
|
+
// agent to run the Auto-Ingest Sweep. The hook only reminds; the agent does the
|
|
31
|
+
// scan + ingest. Cheap signal here; the thorough workspace scan lives in the sweep.
|
|
32
|
+
const inbox = join(root, '02-DOCS', 'inbox');
|
|
33
|
+
if (existsSync(join(root, '02-DOCS', 'wiki')) && existsSync(inbox)) {
|
|
34
|
+
let pending = false;
|
|
35
|
+
try {
|
|
36
|
+
pending = readdirSync(inbox, { withFileTypes: true })
|
|
37
|
+
.some((e) => e.isFile() && e.name !== 'README.md' && !e.name.startsWith('.'));
|
|
38
|
+
} catch { /* unreadable → no nudge */ }
|
|
39
|
+
if (pending) {
|
|
40
|
+
process.stdout.write(`
|
|
41
|
+
===== rsc auto-ingest =====
|
|
42
|
+
Un-ingested material is waiting in 02-DOCS/inbox/.
|
|
43
|
+
ACTION: run the Auto-Ingest Sweep now — ingest inbox/, then scan the workspace
|
|
44
|
+
(minus .rscignore) for un-ingested documents, recording them in wiki/.ingested.json.
|
|
45
|
+
Originals are copied, never moved; deleting an emptied folder needs explicit consent.
|
|
46
|
+
===========================
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// rsc Worklog checkpoint (claude). Wired by targets/claude.js onto PreCompact and
|
|
3
|
+
// SessionEnd as `node ...` so it runs on every platform including Windows.
|
|
4
|
+
// argv[2] = absolute project root
|
|
5
|
+
// Reminds the agent to run a Worklog Sweep (capture what we did this session into
|
|
6
|
+
// 02-DOCS/raw/worklog/). The hook only reminds; the agent writes the worklog.
|
|
7
|
+
// Silent when this workspace has no harness wiki yet.
|
|
8
|
+
import { existsSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
|
|
11
|
+
const root = process.argv[2] || process.cwd();
|
|
12
|
+
|
|
13
|
+
// No harness wiki here → nothing to document into. Stay silent.
|
|
14
|
+
if (!existsSync(join(root, '02-DOCS', 'wiki'))) process.exit(0);
|
|
15
|
+
|
|
16
|
+
process.stdout.write(`
|
|
17
|
+
===== rsc worklog checkpoint =====
|
|
18
|
+
If this session did meaningful work (files changed, a decision made, a commit),
|
|
19
|
+
run a WORKLOG SWEEP before context is lost:
|
|
20
|
+
1. Write 02-DOCS/raw/worklog/<YYYY-MM-DD>-<slug>.md using the harness
|
|
21
|
+
wiki-worklog-template.md (what we did · why · files touched · outcome · next).
|
|
22
|
+
2. Compile it into wiki/ (update existing articles first; wikilinks + Related);
|
|
23
|
+
append significant decisions to 02-DOCS/wiki/harness/decisions.md.
|
|
24
|
+
Skip entirely if this was a pure read/answer turn with no changes.
|
|
25
|
+
==================================
|
|
26
|
+
`);
|
package/targets/session-start.sh
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# rsc SessionStart payload (claude). Wired by targets/claude.js.
|
|
3
|
-
# $1 = absolute path to suggest's SKILL.md $2 = absolute project root
|
|
4
|
-
# Always emits suggest's always-on body; appends an onboarding banner when the
|
|
5
|
-
# workspace has no harness profile yet, and an auto-ingest nudge when there is
|
|
6
|
-
# un-ingested material waiting in the inbox.
|
|
7
|
-
set -u
|
|
8
|
-
|
|
9
|
-
cat "$1" 2>/dev/null
|
|
10
|
-
|
|
11
|
-
profile="$2/02-DOCS/wiki/harness/user-profile.md"
|
|
12
|
-
optout="$2/.rsc/.no-harness"
|
|
13
|
-
|
|
14
|
-
if [ ! -f "$profile" ] && [ ! -f "$optout" ]; then
|
|
15
|
-
cat <<'BANNER'
|
|
16
|
-
|
|
17
|
-
===== rsc onboarding =====
|
|
18
|
-
Fresh setup: 02-DOCS/wiki/harness/user-profile.md is missing.
|
|
19
|
-
ACTION: invoke `init` now (first contact: technical level + accompaniment dial) before the task.
|
|
20
|
-
If the user does not want a harness here: create .rsc/.no-harness
|
|
21
|
-
==========================
|
|
22
|
-
BANNER
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
# Auto-Ingest nudge: when a harness wiki exists and the inbox holds a real file
|
|
26
|
-
# (anything other than README.md / dotfiles / the _processed archive), tell the
|
|
27
|
-
# agent to run the Auto-Ingest Sweep. The hook only reminds; the agent does the
|
|
28
|
-
# scan + ingest. Cheap signal here; the thorough workspace scan lives in the sweep.
|
|
29
|
-
inbox="$2/02-DOCS/inbox"
|
|
30
|
-
if [ -d "$2/02-DOCS/wiki" ] && [ -d "$inbox" ]; then
|
|
31
|
-
pending=$(find "$inbox" -maxdepth 1 -type f ! -name 'README.md' ! -name '.*' 2>/dev/null | head -1)
|
|
32
|
-
if [ -n "$pending" ]; then
|
|
33
|
-
cat <<'BANNER'
|
|
34
|
-
|
|
35
|
-
===== rsc auto-ingest =====
|
|
36
|
-
Un-ingested material is waiting in 02-DOCS/inbox/.
|
|
37
|
-
ACTION: run the Auto-Ingest Sweep now — ingest inbox/, then scan the workspace
|
|
38
|
-
(minus .rscignore) for un-ingested documents, recording them in wiki/.ingested.json.
|
|
39
|
-
Originals are copied, never moved; deleting an emptied folder needs explicit consent.
|
|
40
|
-
===========================
|
|
41
|
-
BANNER
|
|
42
|
-
fi
|
|
43
|
-
fi
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# rsc Worklog checkpoint payload (claude). Wired by targets/claude.js onto the
|
|
3
|
-
# PreCompact and SessionEnd hooks.
|
|
4
|
-
# $1 = absolute project root
|
|
5
|
-
# Reminds the agent to run a Worklog Sweep (capture what we did this session into
|
|
6
|
-
# 02-DOCS/raw/worklog/ so the harness can compile it into the wiki). The hook only
|
|
7
|
-
# REMINDS — the agent writes the worklog (Karpathy: the LLM writes the wiki).
|
|
8
|
-
# Silent when this workspace has no harness wiki yet (nothing to document into).
|
|
9
|
-
set -u
|
|
10
|
-
|
|
11
|
-
root="${1:-$PWD}"
|
|
12
|
-
|
|
13
|
-
# No harness wiki here → nothing to do. Stay silent.
|
|
14
|
-
[ -d "$root/02-DOCS/wiki" ] || exit 0
|
|
15
|
-
|
|
16
|
-
cat <<'BANNER'
|
|
17
|
-
|
|
18
|
-
===== rsc worklog checkpoint =====
|
|
19
|
-
If this session did meaningful work (files changed, a decision made, a commit),
|
|
20
|
-
run a WORKLOG SWEEP before context is lost:
|
|
21
|
-
1. Write 02-DOCS/raw/worklog/<YYYY-MM-DD>-<slug>.md using the harness
|
|
22
|
-
wiki-worklog-template.md (what we did · why · files touched · outcome · next).
|
|
23
|
-
2. Compile it into wiki/ (update existing articles first; wikilinks + Related);
|
|
24
|
-
append significant decisions to 02-DOCS/wiki/harness/decisions.md.
|
|
25
|
-
Skip entirely if this was a pure read/answer turn with no changes.
|
|
26
|
-
==================================
|
|
27
|
-
BANNER
|