harness-everything 0.24.0 → 0.25.1

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.
@@ -10,7 +10,7 @@
10
10
  "name": "harness-everything",
11
11
  "source": "./",
12
12
  "description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
13
- "version": "0.24.0",
13
+ "version": "0.25.1",
14
14
  "author": {
15
15
  "name": "Miya Daniel"
16
16
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "harness-everything",
3
3
  "description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
4
- "version": "0.24.0",
4
+ "version": "0.25.1",
5
5
  "author": {
6
6
  "name": "Miya Daniel"
7
7
  },
package/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [0.25.1](https://github.com/dyphn1/Harness-everything/compare/v0.25.0...v0.25.1) (2026-09-24)
6
+
7
+ ### Bug Fixes
8
+
9
+ * **skills:** document worktree submodule reachability ([024185a](https://github.com/dyphn1/Harness-everything/commit/024185ab29363968bbe30d648cf2ef902751e9b9))
10
+ * **skills:** keep worktree contract within token budget ([c41903d](https://github.com/dyphn1/Harness-everything/commit/c41903d2c37e3af127b84b0ba9c5a82cd4fab3ee))
11
+ * **skills:** preserve isolation contract wording ([b14ea2a](https://github.com/dyphn1/Harness-everything/commit/b14ea2a6e6417f4103f16e5d2cf04e6fc994e583))
12
+ * **skills:** require submodule reachability reference ([5c61c2b](https://github.com/dyphn1/Harness-everything/commit/5c61c2bbae0f2e29818579bd2ebcd7d45a76c1b0))
13
+ * **skills:** sync compact worktree contract ([cd4e3a8](https://github.com/dyphn1/Harness-everything/commit/cd4e3a8db276083ac11346031f626058cd02bed3))
14
+ * **skills:** sync isolation contract wording ([7f59b1c](https://github.com/dyphn1/Harness-everything/commit/7f59b1c4e66d00ec84c225ad161e503a443ad1cd))
15
+ * **skills:** sync worktree submodule reference ([b3fdf5d](https://github.com/dyphn1/Harness-everything/commit/b3fdf5dff8b2c22ff02cc39510d23dc60c2489ae))
16
+ * **skills:** sync worktree submodule skill ([08dffec](https://github.com/dyphn1/Harness-everything/commit/08dffec0aa69602b61a1a90b6d10cbf97cea0dcb))
17
+
18
+ ## [0.25.0](https://github.com/dyphn1/Harness-everything/compare/v0.24.0...v0.25.0) (2026-09-23)
19
+
20
+ ### Features
21
+
22
+ * **router:** bound system one labeling runs with --max-batches ([e69b596](https://github.com/dyphn1/Harness-everything/commit/e69b5962888ad9e53ca189f36e67ccf6ada03290)), closes [#233](https://github.com/dyphn1/Harness-everything/issues/233)
23
+
24
+ ### Bug Fixes
25
+
26
+ * **router:** drop agent-authored prompts from system one training data ([8a2f959](https://github.com/dyphn1/Harness-everything/commit/8a2f959bb2ffd56c64d7e9eb2342b1178cd559dd)), closes [#233](https://github.com/dyphn1/Harness-everything/issues/233)
27
+
5
28
  ## [0.24.0](https://github.com/dyphn1/Harness-everything/compare/v0.23.0...v0.24.0) (2026-09-23)
6
29
 
7
30
  ### Features
@@ -25,11 +25,13 @@ function fakeHome() {
25
25
  { type: 'assistant', message: { content: 'assistant text must be skipped' } },
26
26
  ]));
27
27
  write('.codex/sessions/2026/09/01/rollout-a.jsonl', jsonl([
28
+ { type: 'session_meta', payload: { originator: 'codex_vscode', source: 'vscode' } },
28
29
  { type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: '<environment_context>cwd</environment_context>' }] } },
29
30
  { type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'duplicate of the event message' }] } },
30
31
  { type: 'event_msg', payload: { type: 'user_message', message: 'add a --verbose flag with tests' } },
31
32
  ]));
32
33
  write('.codex/sessions/2026/09/02/rollout-b.jsonl', jsonl([
34
+ { type: 'session_meta', payload: { originator: 'Codex Desktop', source: 'vscode' } },
33
35
  { type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: '<user_instructions>agents</user_instructions>' }] } },
34
36
  { type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'older session without event messages' }] } },
35
37
  ]));
@@ -69,6 +71,33 @@ test('S1-C101 each source yields only owner-typed text', () => {
69
71
  } finally { fs.rmSync(home, { recursive: true, force: true }); }
70
72
  });
71
73
 
74
+ test('S1-C106 only interactive Codex sessions count, and VS Code terminal notifications are dropped', () => {
75
+ const home = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-s1-collect-'));
76
+ const appdata = path.join(home, 'AppData', 'Roaming');
77
+ const session = (name, meta, text) => {
78
+ const p = path.join(home, '.codex', 'sessions', '2026', '09', '03', `${name}.jsonl`);
79
+ fs.mkdirSync(path.dirname(p), { recursive: true });
80
+ fs.writeFileSync(p, jsonl([{ type: 'session_meta', payload: meta }, { type: 'event_msg', payload: { type: 'user_message', message: text } }]));
81
+ };
82
+ try {
83
+ session('ide', { originator: 'codex_vscode', source: 'vscode' }, 'typed in the IDE');
84
+ session('desktop', { originator: 'Codex Desktop', source: 'vscode' }, 'typed in the desktop app');
85
+ session('tui', { originator: 'codex-tui', source: 'cli' }, 'typed in the terminal');
86
+ session('from-claude', { originator: 'Claude Code', source: 'vscode' }, 'dispatched by another agent');
87
+ session('exec', { originator: 'codex_exec', source: 'exec' }, 'an exec lane prompt');
88
+ session('ide-exec', { originator: 'codex_vscode', source: 'exec' }, 'another exec prompt');
89
+ session('subagent', { originator: 'codex_vscode', source: { subagent: { thread_spawn: {} } } }, 'a sub-agent prompt');
90
+ session('no-meta', null, 'a session without metadata');
91
+ const chat = path.join(appdata, 'Code', 'User', 'workspaceStorage', 'w', 'chatSessions', 's.jsonl');
92
+ fs.mkdirSync(path.dirname(chat), { recursive: true });
93
+ fs.writeFileSync(chat, jsonl([{ kind: 0, v: { requests: [
94
+ { message: { text: '[Terminal 808808ce-309f notification: command completed with exit code 0]' } },
95
+ { message: { text: 'a real chat prompt' } }] } }]));
96
+ assert.deepEqual(texts(collect.readSources({ home, appdata })), texts([
97
+ { text: 'typed in the IDE' }, { text: 'typed in the desktop app' }, { text: 'typed in the terminal' }, { text: 'a real chat prompt' }]));
98
+ } finally { fs.rmSync(home, { recursive: true, force: true }); }
99
+ });
100
+
72
101
  test('S1-C102 filters, redaction and deduplication', () => {
73
102
  assert.equal(collect.keep('go'), true);
74
103
  assert.equal(collect.keep('x'.repeat(1024)), true);
@@ -89,6 +89,10 @@ test('S1-L05 CLI labels through the configured command, resumes, checks the hold
89
89
  const rows = fs.readFileSync(out, 'utf8').trim().split('\n').map(l => JSON.parse(l));
90
90
  assert.ok(rows.every(r => r.gold === 'tier2' && r.labeler.model === 'sonnet' && /^[0-9a-f]{16}$/.test(r.labeler.rulesSha256)));
91
91
  assert.deepEqual(JSON.parse(cli(['label', '--in', input, '--out', out]).stdout), { labeled: 0, failed: 0, total: 5 });
92
+ const partial = path.join(dir, 'partial.jsonl');
93
+ assert.deepEqual(JSON.parse(cli(['label', '--in', input, '--out', partial, '--batch', '2', '--max-batches', '1']).stdout), { labeled: 2, failed: 0, total: 5 });
94
+ assert.deepEqual(JSON.parse(cli(['label', '--in', input, '--out', partial, '--batch', '2', '--max-batches', '1']).stdout), { labeled: 2, failed: 0, total: 5 }, 'resumes with the next batch');
95
+ assert.equal(fs.readFileSync(partial, 'utf8').trim().split('\n').length, 4);
92
96
  const report = path.join(dir, 'check.json');
93
97
  const check = cli(['check-holdout', '--out', report]);
94
98
  assert.equal(check.status, 0, check.stderr);
@@ -27,6 +27,10 @@ Rules:
27
27
  2. Label the work requested, not the words used. Searching every repository and
28
28
  reporting is `tier1`; changing every repository is `tier3`.
29
29
  3. Pick the smallest tier that covers the whole request.
30
+ A question, a confirmation, a discussion point, or a request to restate,
31
+ reformat or extend the assistant's previous answer without changing files is
32
+ `tier1`. A requested change to code or configuration, however small, is at
33
+ least `tier2`. Only the smallest doc fixes listed in the table stay `tier1`.
30
34
  4. Explicit workflow words ("use fable", "no subagents") do not change the gold.
31
35
  Precedence is a router policy, not a label.
32
36
  5. Never derive gold from the lexical router or any model output. A reviewer may
@@ -42,8 +42,11 @@ The following are dropped:
42
42
  - Session-continuation summaries ("This session is being continued…").
43
43
  - Empty text.
44
44
 
45
- Codex sessions include prompts that another agent dispatched. They are kept and tagged with
46
- their source, because Harness routes them in Codex too.
45
+ Codex sessions are kept only when they are interactive, meaning `session_meta` has a
46
+ `source` of `vscode` or `cli` and an originator that is neither `Claude Code` nor
47
+ `codex_exec`. Exec sessions, sub-agent threads and sessions another agent started contain
48
+ prompts written by an agent, not by the owner. VS Code terminal notifications
49
+ (`[Terminal … notification …`) are dropped as well.
47
50
 
48
51
  ## Filters, families and splits
49
52
 
@@ -80,7 +83,9 @@ their source, because Harness routes them in Codex too.
80
83
  sessions never become collectable history), `--tools ""` and a JSON schema.
81
84
  - The instructions contain the gold table and rules from
82
85
  [system-one-corpus.md](system-one-corpus.md).
83
- - Prompts go in batches of 100. Every returned index must be labeled exactly once with
86
+ - Prompts go in batches of 100. `--max-batches N` stops after N batches so a
87
+ memory-constrained host can label in short foreground runs that resume from the
88
+ labels already written. Every returned index must be labeled exactly once with
84
89
  `tier1`, `tier2`, `tier3` or `null`. A malformed batch is retried once and then
85
90
  recorded as failed. It is never partially accepted.
86
91
  - **Labeler check**: the labeler labels the 215 holdout prompts once, before any training
@@ -88,9 +93,14 @@ their source, because Harness routes them in Codex too.
88
93
  - Labeling proceeds only when agreement is at least 80%.
89
94
  - The instructions are never tuned on the holdout. If the check fails, the owner reviews
90
95
  the disagreements and decides how to proceed.
91
- - **Owner spot-check**: a random 5% sample of the labeled training data is reviewed on the
92
- review page, and the disagreement rate is reported. The owner's decisions replace the LLM
93
- labels for those cases.
96
+ - **Owner spot-check**: a deterministic sample of the labeled training data is reviewed on
97
+ the review page, and the disagreement rate is reported.
98
+ - Each case shows the preceding prompts from the same session as read-only context.
99
+ Without it, short replies read as confirmations: the first spot-check (103 cases,
100
+ no context) disagreed 51% and was not used to override labels.
101
+ - A checkpoint may be trained before the spot-check, but it is released only when
102
+ disagreement is below 20%.
103
+ - Decisions made with context replace the LLM labels for those cases.
94
104
 
95
105
  ## Training and calibration
96
106
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "harness-enforcement",
3
3
  "description": "Repository inventory for the opencode enforcement plugin and its standalone helper",
4
- "version": "0.24.0",
4
+ "version": "0.25.1",
5
5
  "runtime": "index.mjs",
6
6
  "hooks": {
7
7
  "verify": "hooks/verify.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-everything",
3
- "version": "0.24.0",
3
+ "version": "0.25.1",
4
4
  "description": "Harness OS: An Orchestrated Agent Operating System for AI-driven Development",
5
5
  "main": "harness-everything/scripts/bootstrap.js",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-everything",
3
- "version": "0.24.0",
3
+ "version": "0.25.1",
4
4
  "description": "Invariant-first engineering harness for routing, verification, and failure recovery while preserving agent autonomy.",
5
5
  "author": {
6
6
  "name": "Miya Daniel",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "harness-everything",
4
- "version": "0.24.0",
4
+ "version": "0.25.1",
5
5
  "description": "Invariant-first engineering harness for routing, verification, and failure recovery while preserving agent autonomy.",
6
6
  "author": {
7
7
  "name": "Miya Daniel",
@@ -4,44 +4,45 @@ description: Use when work needs isolation or before major implementation plans
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  author: Miya Daniel
7
- version: 0.19.1
7
+ version: 0.25.1
8
8
  ---
9
9
 
10
10
  # Using Git Worktrees
11
11
 
12
- Use native worktree support first; raw Git is the fallback.
12
+ Use native worktree support first; raw Git is fallback.
13
13
 
14
14
  ## Contract
15
15
 
16
- - **Tier 3 / Fable (MUST resolve)** — before broad source/artifact mutation, reuse/create a verified linked worktree. If isolation is unavailable or the user explicitly chooses to stay in place, MUST report an explicit degraded fallback/risk before continuing.
17
- - **Ordinary mode (SHOULD)** — use isolation when it materially reduces collision/risk; explicit user preference may keep work in place.
18
- - **MUST NOT** nest a worktree inside an already isolated worktree.
16
+ - **Tier 3 / Fable (MUST resolve)** — isolate before broad mutation. If unavailable or explicitly declined, MUST report an explicit degraded fallback/risk.
17
+ - **Ordinary mode SHOULD** isolate when it materially reduces collision/risk.
18
+ - **MUST NOT** nest a worktree inside an isolated worktree.
19
19
 
20
20
  ## Workflow
21
21
 
22
- **Step 0 — Detect isolation** (adapt per `environment-detection`):
22
+ **Step 0 — Detect**:
23
23
  ```bash
24
24
  git rev-parse --git-dir
25
25
  git rev-parse --git-common-dir
26
26
  git branch --show-current
27
27
  git rev-parse --show-superproject-working-tree
28
+ git submodule status --recursive
28
29
  ```
29
- Different git/common dirs and no superproject => already isolated; continue to Step 2. A submodule is a normal repo for this check.
30
+ Different git/common dirs and no superproject => already isolated. If submodules exist, **MUST** read `<this-skill-dir>/references/submodules-in-worktrees.md` before committing inside them.
30
31
 
31
- **Step 1 — Create/enter**: use native `EnterWorktree`, `/worktree`, or `--worktree` first; otherwise use `git worktree add "$path" -b "$BRANCH_NAME"`. Use an already-ignored or external/sibling path when possible. If creation/entry fails, MUST surface the degraded isolation disposition before continuing.
32
+ **Step 1 — Create/enter**: use native `EnterWorktree`, `/worktree`, or `--worktree`; otherwise `git worktree add "$path" -b "$BRANCH_NAME"`. On failure, MUST surface the degraded disposition.
32
33
 
33
- **Step 2 — Setup**: install project dependencies as needed.
34
+ **Step 2 — Setup**: install dependencies as needed.
34
35
 
35
- **Step 3 — Baseline**: run relevant tests/build before implementation when useful; surface existing failures before relying on the baseline.
36
+ **Step 3 — Baseline**: run relevant tests/build when useful; surface existing failures.
36
37
 
37
38
  Deep dive: <this-skill-dir>/references/workflow-details.md
38
39
 
39
40
  ## USE FOR:
40
- - Tier 3 / Fable-class mutable engineering
41
+ - Tier 3 / Fable mutable engineering
41
42
  - feature work needing isolation
42
43
  - pre-implementation-plan setup
43
44
 
44
45
  ## DO NOT USE FOR:
45
46
  - nesting inside an existing worktree
46
- - read-only analysis with no mutation
47
- - branch/merge workflows unrelated to workspace isolation
47
+ - read-only analysis
48
+ - unrelated branch/merge workflows
@@ -0,0 +1,135 @@
1
+ # Submodules inside linked worktrees
2
+
3
+ A linked worktree of a superproject does **not** share the primary checkout's submodule object store. After `git submodule update --init`, each submodule normally uses a worktree-specific git dir such as:
4
+
5
+ ```text
6
+ <super>/.git/worktrees/<worktree-id>/modules/<submodule>
7
+ ```
8
+
9
+ The primary checkout uses:
10
+
11
+ ```text
12
+ <super>/.git/modules/<submodule>
13
+ ```
14
+
15
+ A superproject gitlink records only a commit SHA. It does not publish or copy that commit into the primary checkout. Therefore a submodule commit made only on detached HEAD in a linked worktree can become unreachable when that worktree is removed.
16
+
17
+ ## Required rules
18
+
19
+ 1. **MUST use a named branch before committing in the submodule.** `git submodule update` normally leaves the submodule detached.
20
+ 2. **MUST make the new submodule commit reachable outside the linked worktree before treating the superproject gitlink bump as deliverable.** Publish it to the submodule remote, or fetch it into the primary checkout's submodule repository.
21
+ 3. **MUST verify external reachability before removing the linked worktree.** A branch that exists only inside the linked worktree is not sufficient publication evidence.
22
+
23
+ ## Detect the situation
24
+
25
+ From the superproject worktree:
26
+
27
+ ```bash
28
+ git rev-parse --git-dir
29
+ git rev-parse --git-common-dir
30
+ git submodule status --recursive
31
+ git -C <submodule> rev-parse --absolute-git-dir
32
+ git -C <submodule> branch --show-current
33
+ ```
34
+
35
+ A linked superproject has different git/common dirs. A blank submodule branch means detached HEAD.
36
+
37
+ PowerShell uses the same Git commands; quote paths containing spaces:
38
+
39
+ ```powershell
40
+ git -C "<submodule>" rev-parse --absolute-git-dir
41
+ git -C "<submodule>" branch --show-current
42
+ ```
43
+
44
+ ## Prevent the problem
45
+
46
+ Before editing or committing in the submodule:
47
+
48
+ ```bash
49
+ git -C <submodule> switch -c <task-branch>
50
+ # edit + verify
51
+ git -C <submodule> add <paths>
52
+ git -C <submodule> commit -m "<message>"
53
+ SUB_SHA=$(git -C <submodule> rev-parse HEAD)
54
+ ```
55
+
56
+ PowerShell:
57
+
58
+ ```powershell
59
+ git -C "<submodule>" switch -c "<task-branch>"
60
+ # edit + verify
61
+ git -C "<submodule>" add <paths>
62
+ git -C "<submodule>" commit -m "<message>"
63
+ $SubSha = git -C "<submodule>" rev-parse HEAD
64
+ ```
65
+
66
+ ## Publish before the gitlink is considered deliverable
67
+
68
+ Preferred path when the submodule has a remote:
69
+
70
+ ```bash
71
+ git -C <submodule> push -u origin <task-branch>
72
+ git -C <submodule> branch -r --contains "$SUB_SHA"
73
+ ```
74
+
75
+ ```powershell
76
+ git -C "<submodule>" push -u origin "<task-branch>"
77
+ git -C "<submodule>" branch -r --contains $SubSha
78
+ ```
79
+
80
+ If pushing is not appropriate, copy the commit into the primary checkout's submodule repository. From the linked worktree first give a detached commit a name if necessary:
81
+
82
+ ```bash
83
+ git -C <worktree>/<submodule> branch -f <task-branch> <sha>
84
+ git -C <primary>/<submodule> fetch <worktree>/<submodule> <task-branch>:<task-branch>
85
+ git -C <primary>/<submodule> cat-file -e <sha>^{commit}
86
+ ```
87
+
88
+ ```powershell
89
+ git -C "<worktree>/<submodule>" branch -f "<task-branch>" "<sha>"
90
+ git -C "<primary>/<submodule>" fetch "<worktree>/<submodule>" "<task-branch>:<task-branch>"
91
+ git -C "<primary>/<submodule>" cat-file -e "<sha>^{commit}"
92
+ ```
93
+
94
+ After the commit is externally reachable, stage the gitlink in the superproject:
95
+
96
+ ```bash
97
+ git add <submodule>
98
+ git diff --cached --submodule=log
99
+ ```
100
+
101
+ ## Recovery after an unpublished gitlink was already committed
102
+
103
+ Do **not** remove the linked worktree. Recover the referenced SHA while its submodule object store still exists:
104
+
105
+ ```bash
106
+ git -C <worktree>/<submodule> branch -f <task-branch> <sha>
107
+ git -C <primary>/<submodule> fetch <worktree>/<submodule> <task-branch>:<task-branch>
108
+ git -C <primary>/<submodule> cat-file -e <sha>^{commit}
109
+ git -C <primary> submodule update
110
+ ```
111
+
112
+ The PowerShell form is identical except paths/refs should be quoted as shown above.
113
+
114
+ ## Pre-removal check
115
+
116
+ For every changed gitlink SHA, prove at least one external home exists:
117
+
118
+ ```bash
119
+ git -C <submodule> branch -r --contains <sha>
120
+ # OR, from the primary checkout:
121
+ git -C <primary>/<submodule> cat-file -e <sha>^{commit}
122
+ ```
123
+
124
+ If neither succeeds, **MUST NOT** remove the linked worktree yet.
125
+
126
+ ## Handoff checklist
127
+
128
+ For each changed submodule record:
129
+
130
+ - submodule path
131
+ - commit SHA
132
+ - branch name
133
+ - publication location: remote-tracking ref or primary checkout object store
134
+ - superproject gitlink staged/committed state
135
+ - reachability check result before worktree removal
package/sbom.cdx.json CHANGED
@@ -2,23 +2,23 @@
2
2
  "$schema": "https://cyclonedx.org/schema/bom-1.7.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.7",
5
- "serialNumber": "urn:uuid:5f8c3ad1-23b9-55c5-a389-ff6c3877f9dd",
5
+ "serialNumber": "urn:uuid:fb030470-2601-5f76-9c8c-9e7efeb21a03",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-23T13:40:29.695Z",
8
+ "timestamp": "2026-09-24T12:40:30.113Z",
9
9
  "tools": [
10
10
  {
11
11
  "vendor": "Harness Everything",
12
12
  "name": "generate-sbom.js",
13
- "version": "0.24.0"
13
+ "version": "0.25.1"
14
14
  }
15
15
  ],
16
16
  "component": {
17
17
  "type": "application",
18
- "bom-ref": "pkg:npm/harness-everything@0.24.0",
18
+ "bom-ref": "pkg:npm/harness-everything@0.25.1",
19
19
  "name": "harness-everything",
20
- "version": "0.24.0",
21
- "purl": "pkg:npm/harness-everything@0.24.0"
20
+ "version": "0.25.1",
21
+ "purl": "pkg:npm/harness-everything@0.25.1"
22
22
  }
23
23
  },
24
24
  "components": [
@@ -1999,7 +1999,7 @@
1999
1999
  ]
2000
2000
  },
2001
2001
  {
2002
- "ref": "pkg:npm/harness-everything@0.24.0",
2002
+ "ref": "pkg:npm/harness-everything@0.25.1",
2003
2003
  "dependsOn": [
2004
2004
  "pkg:npm/%40commitlint/cli@19.8.1",
2005
2005
  "pkg:npm/%40commitlint/config-conventional@19.8.1",
@@ -12,7 +12,9 @@ const REPO = path.resolve(__dirname, '..');
12
12
  const MAX_BYTES = 1024;
13
13
  const VALIDATION_PERCENT = 15;
14
14
  // Whole-text wrappers injected by hosts or hooks; text that starts with one is not typed by the owner.
15
- const WRAPPER = /^<(environment_context|user_instructions|recommended_plugins|send_user_message_question_reply|command-|local-command|task-notification|bash-|turn_aborted|user_shell_command|skill)/i;
15
+ const WRAPPER = /^(<(environment_context|user_instructions|recommended_plugins|send_user_message_question_reply|command-|local-command|task-notification|bash-|turn_aborted|user_shell_command|skill)|\[Terminal [0-9a-f-]+ notification)/i;
16
+ // Codex sessions typed by the owner: interactive IDE/desktop/terminal ones, not exec lanes, sub-agents or agent-started sessions.
17
+ const interactiveCodex = meta => !!meta && ['vscode', 'cli'].includes(meta.source) && !['Claude Code', 'codex_exec'].includes(meta.originator);
16
18
  // Blocks a host inserts inside typed text; they are removed and the rest is kept.
17
19
  const INSERTED = /<(system-reminder|ide_[a-z_]+)>[\s\S]*?<\/\1>/gi;
18
20
  const sha = text => createHash('sha256').update(text, 'utf8').digest('hex');
@@ -61,12 +63,14 @@ function fromClaude(file) {
61
63
  return rows;
62
64
  }
63
65
  function fromCodex(file) {
64
- const events = []; const items = [];
66
+ const events = []; const items = []; let meta = null;
65
67
  for (const line of readLines(file)) {
66
68
  const e = parse(line); if (!e || !e.payload) continue;
69
+ if (e.type === 'session_meta' && !meta) { meta = e.payload; if (!interactiveCodex(meta)) return []; continue; }
67
70
  if (e.type === 'event_msg' && e.payload.type === 'user_message') { const t = typed(e.payload.message); if (t) events.push(t); }
68
71
  if (e.type === 'response_item' && e.payload.role === 'user') for (const c of e.payload.content || []) { const t = typed(c && c.text); if (t) items.push(t); }
69
72
  }
73
+ if (!interactiveCodex(meta)) return [];
70
74
  // Event messages are the typed text; response items repeat it with injected context, so they are a fallback only.
71
75
  return events.length ? events : items;
72
76
  }
@@ -39,9 +39,9 @@ function validateReply(batch, reply) {
39
39
  }
40
40
  return out;
41
41
  }
42
- async function labelAll(data, { run, rules, batchSize = 100, concurrency = 4, done = new Set(), onBatch = () => {}, onFailure = () => {}, retryDelayMs = 30000 }) {
42
+ async function labelAll(data, { run, rules, batchSize = 100, concurrency = 4, done = new Set(), onBatch = () => {}, onFailure = () => {}, retryDelayMs = 30000, maxBatches = Infinity }) {
43
43
  const todo = data.filter(d => !done.has(d.id));
44
- const batches = []; for (let i = 0; i < todo.length; i += batchSize) batches.push(todo.slice(i, i + batchSize));
44
+ const batches = []; for (let i = 0; i < todo.length && batches.length < maxBatches; i += batchSize) batches.push(todo.slice(i, i + batchSize));
45
45
  const labeled = []; const failed = []; let next = 0;
46
46
  // Every failed attempt is reported with its reason; a thrown run (rate limit, timeout) waits before the retry.
47
47
  const attempt = async batch => {
@@ -127,7 +127,8 @@ async function main(argv) {
127
127
  const onBatch = rows => fs.appendFileSync(out, rows.map(r => `${JSON.stringify({ ...r, labeler })}\n`).join(''), { mode: 0o600 });
128
128
  // Failure log: first ID, size and reason only, never prompt text.
129
129
  const onFailure = (batch, reason) => fs.appendFileSync(`${out}.failures.jsonl`, `${JSON.stringify({ firstId: batch[0].id, size: batch.length, reason, at: new Date().toISOString() })}\n`);
130
- const { labeled, failed } = await labelAll(data, { run, rules, batchSize, concurrency, done, onBatch, onFailure });
130
+ const maxBatches = Number(opt('--max-batches', 'Infinity'));
131
+ const { labeled, failed } = await labelAll(data, { run, rules, batchSize, concurrency, done, onBatch, onFailure, maxBatches });
131
132
  console.log(JSON.stringify({ labeled: labeled.length, failed: failed.length, total: data.length }));
132
133
  } else if (op === 'check-holdout') {
133
134
  const out = opt('--out'); if (!out) throw new Error('check-holdout needs --out');
@@ -4,44 +4,45 @@ description: Use when work needs isolation or before major implementation plans
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  author: Miya Daniel
7
- version: 0.19.1
7
+ version: 0.25.1
8
8
  ---
9
9
 
10
10
  # Using Git Worktrees
11
11
 
12
- Use native worktree support first; raw Git is the fallback.
12
+ Use native worktree support first; raw Git is fallback.
13
13
 
14
14
  ## Contract
15
15
 
16
- - **Tier 3 / Fable (MUST resolve)** — before broad source/artifact mutation, reuse/create a verified linked worktree. If isolation is unavailable or the user explicitly chooses to stay in place, MUST report an explicit degraded fallback/risk before continuing.
17
- - **Ordinary mode (SHOULD)** — use isolation when it materially reduces collision/risk; explicit user preference may keep work in place.
18
- - **MUST NOT** nest a worktree inside an already isolated worktree.
16
+ - **Tier 3 / Fable (MUST resolve)** — isolate before broad mutation. If unavailable or explicitly declined, MUST report an explicit degraded fallback/risk.
17
+ - **Ordinary mode SHOULD** isolate when it materially reduces collision/risk.
18
+ - **MUST NOT** nest a worktree inside an isolated worktree.
19
19
 
20
20
  ## Workflow
21
21
 
22
- **Step 0 — Detect isolation** (adapt per `environment-detection`):
22
+ **Step 0 — Detect**:
23
23
  ```bash
24
24
  git rev-parse --git-dir
25
25
  git rev-parse --git-common-dir
26
26
  git branch --show-current
27
27
  git rev-parse --show-superproject-working-tree
28
+ git submodule status --recursive
28
29
  ```
29
- Different git/common dirs and no superproject => already isolated; continue to Step 2. A submodule is a normal repo for this check.
30
+ Different git/common dirs and no superproject => already isolated. If submodules exist, **MUST** read `<this-skill-dir>/references/submodules-in-worktrees.md` before committing inside them.
30
31
 
31
- **Step 1 — Create/enter**: use native `EnterWorktree`, `/worktree`, or `--worktree` first; otherwise use `git worktree add "$path" -b "$BRANCH_NAME"`. Use an already-ignored or external/sibling path when possible. If creation/entry fails, MUST surface the degraded isolation disposition before continuing.
32
+ **Step 1 — Create/enter**: use native `EnterWorktree`, `/worktree`, or `--worktree`; otherwise `git worktree add "$path" -b "$BRANCH_NAME"`. On failure, MUST surface the degraded disposition.
32
33
 
33
- **Step 2 — Setup**: install project dependencies as needed.
34
+ **Step 2 — Setup**: install dependencies as needed.
34
35
 
35
- **Step 3 — Baseline**: run relevant tests/build before implementation when useful; surface existing failures before relying on the baseline.
36
+ **Step 3 — Baseline**: run relevant tests/build when useful; surface existing failures.
36
37
 
37
38
  Deep dive: <this-skill-dir>/references/workflow-details.md
38
39
 
39
40
  ## USE FOR:
40
- - Tier 3 / Fable-class mutable engineering
41
+ - Tier 3 / Fable mutable engineering
41
42
  - feature work needing isolation
42
43
  - pre-implementation-plan setup
43
44
 
44
45
  ## DO NOT USE FOR:
45
46
  - nesting inside an existing worktree
46
- - read-only analysis with no mutation
47
- - branch/merge workflows unrelated to workspace isolation
47
+ - read-only analysis
48
+ - unrelated branch/merge workflows
@@ -0,0 +1,135 @@
1
+ # Submodules inside linked worktrees
2
+
3
+ A linked worktree of a superproject does **not** share the primary checkout's submodule object store. After `git submodule update --init`, each submodule normally uses a worktree-specific git dir such as:
4
+
5
+ ```text
6
+ <super>/.git/worktrees/<worktree-id>/modules/<submodule>
7
+ ```
8
+
9
+ The primary checkout uses:
10
+
11
+ ```text
12
+ <super>/.git/modules/<submodule>
13
+ ```
14
+
15
+ A superproject gitlink records only a commit SHA. It does not publish or copy that commit into the primary checkout. Therefore a submodule commit made only on detached HEAD in a linked worktree can become unreachable when that worktree is removed.
16
+
17
+ ## Required rules
18
+
19
+ 1. **MUST use a named branch before committing in the submodule.** `git submodule update` normally leaves the submodule detached.
20
+ 2. **MUST make the new submodule commit reachable outside the linked worktree before treating the superproject gitlink bump as deliverable.** Publish it to the submodule remote, or fetch it into the primary checkout's submodule repository.
21
+ 3. **MUST verify external reachability before removing the linked worktree.** A branch that exists only inside the linked worktree is not sufficient publication evidence.
22
+
23
+ ## Detect the situation
24
+
25
+ From the superproject worktree:
26
+
27
+ ```bash
28
+ git rev-parse --git-dir
29
+ git rev-parse --git-common-dir
30
+ git submodule status --recursive
31
+ git -C <submodule> rev-parse --absolute-git-dir
32
+ git -C <submodule> branch --show-current
33
+ ```
34
+
35
+ A linked superproject has different git/common dirs. A blank submodule branch means detached HEAD.
36
+
37
+ PowerShell uses the same Git commands; quote paths containing spaces:
38
+
39
+ ```powershell
40
+ git -C "<submodule>" rev-parse --absolute-git-dir
41
+ git -C "<submodule>" branch --show-current
42
+ ```
43
+
44
+ ## Prevent the problem
45
+
46
+ Before editing or committing in the submodule:
47
+
48
+ ```bash
49
+ git -C <submodule> switch -c <task-branch>
50
+ # edit + verify
51
+ git -C <submodule> add <paths>
52
+ git -C <submodule> commit -m "<message>"
53
+ SUB_SHA=$(git -C <submodule> rev-parse HEAD)
54
+ ```
55
+
56
+ PowerShell:
57
+
58
+ ```powershell
59
+ git -C "<submodule>" switch -c "<task-branch>"
60
+ # edit + verify
61
+ git -C "<submodule>" add <paths>
62
+ git -C "<submodule>" commit -m "<message>"
63
+ $SubSha = git -C "<submodule>" rev-parse HEAD
64
+ ```
65
+
66
+ ## Publish before the gitlink is considered deliverable
67
+
68
+ Preferred path when the submodule has a remote:
69
+
70
+ ```bash
71
+ git -C <submodule> push -u origin <task-branch>
72
+ git -C <submodule> branch -r --contains "$SUB_SHA"
73
+ ```
74
+
75
+ ```powershell
76
+ git -C "<submodule>" push -u origin "<task-branch>"
77
+ git -C "<submodule>" branch -r --contains $SubSha
78
+ ```
79
+
80
+ If pushing is not appropriate, copy the commit into the primary checkout's submodule repository. From the linked worktree first give a detached commit a name if necessary:
81
+
82
+ ```bash
83
+ git -C <worktree>/<submodule> branch -f <task-branch> <sha>
84
+ git -C <primary>/<submodule> fetch <worktree>/<submodule> <task-branch>:<task-branch>
85
+ git -C <primary>/<submodule> cat-file -e <sha>^{commit}
86
+ ```
87
+
88
+ ```powershell
89
+ git -C "<worktree>/<submodule>" branch -f "<task-branch>" "<sha>"
90
+ git -C "<primary>/<submodule>" fetch "<worktree>/<submodule>" "<task-branch>:<task-branch>"
91
+ git -C "<primary>/<submodule>" cat-file -e "<sha>^{commit}"
92
+ ```
93
+
94
+ After the commit is externally reachable, stage the gitlink in the superproject:
95
+
96
+ ```bash
97
+ git add <submodule>
98
+ git diff --cached --submodule=log
99
+ ```
100
+
101
+ ## Recovery after an unpublished gitlink was already committed
102
+
103
+ Do **not** remove the linked worktree. Recover the referenced SHA while its submodule object store still exists:
104
+
105
+ ```bash
106
+ git -C <worktree>/<submodule> branch -f <task-branch> <sha>
107
+ git -C <primary>/<submodule> fetch <worktree>/<submodule> <task-branch>:<task-branch>
108
+ git -C <primary>/<submodule> cat-file -e <sha>^{commit}
109
+ git -C <primary> submodule update
110
+ ```
111
+
112
+ The PowerShell form is identical except paths/refs should be quoted as shown above.
113
+
114
+ ## Pre-removal check
115
+
116
+ For every changed gitlink SHA, prove at least one external home exists:
117
+
118
+ ```bash
119
+ git -C <submodule> branch -r --contains <sha>
120
+ # OR, from the primary checkout:
121
+ git -C <primary>/<submodule> cat-file -e <sha>^{commit}
122
+ ```
123
+
124
+ If neither succeeds, **MUST NOT** remove the linked worktree yet.
125
+
126
+ ## Handoff checklist
127
+
128
+ For each changed submodule record:
129
+
130
+ - submodule path
131
+ - commit SHA
132
+ - branch name
133
+ - publication location: remote-tracking ref or primary checkout object store
134
+ - superproject gitlink staged/committed state
135
+ - reachability check result before worktree removal