oh-my-opencode 5.1.58 → 5.1.59

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.
Files changed (74) hide show
  1. package/dist/cli/index.js +43 -43
  2. package/dist/cli-node/index.js +43 -43
  3. package/dist/index.js +341 -278
  4. package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
  5. package/dist/skills/eval-integrity/SKILL.md +107 -0
  6. package/dist/skills/ulw-research/scripts/fidelity-values.mjs +5 -2
  7. package/dist/skills/ulw-research/scripts/fidelity-values.test.ts +26 -0
  8. package/dist/skills/ulw-research/scripts/html-foreign-object.mjs +61 -0
  9. package/dist/skills/ulw-research/scripts/html-lite.mjs +7 -3
  10. package/dist/skills/ulw-research/scripts/html-lite.test.ts +19 -0
  11. package/dist/tui.js +38 -38
  12. package/package.json +14 -14
  13. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  14. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  15. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  16. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  17. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  19. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  21. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  23. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  24. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  25. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  26. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  27. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  28. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  29. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  30. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  31. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  32. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  33. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  34. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  35. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  36. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  37. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  38. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  39. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  40. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  41. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  42. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  43. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  44. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  45. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  46. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  47. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  52. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  53. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  54. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  55. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  56. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  57. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  58. package/packages/omo-codex/plugin/package-lock.json +12 -12
  59. package/packages/omo-codex/plugin/package.json +1 -1
  60. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  61. package/packages/omo-codex/plugin/skills/eval-integrity/SKILL.md +107 -0
  62. package/packages/omo-codex/plugin/skills/eval-integrity/agents/openai.yaml +2 -0
  63. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-values.mjs +5 -2
  64. package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-foreign-object.mjs +61 -0
  65. package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-lite.mjs +7 -3
  66. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -0
  67. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
  68. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
  69. package/packages/shared-skills/skills/eval-integrity/SKILL.md +107 -0
  70. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.mjs +5 -2
  71. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.test.ts +26 -0
  72. package/packages/shared-skills/skills/ulw-research/scripts/html-foreign-object.mjs +61 -0
  73. package/packages/shared-skills/skills/ulw-research/scripts/html-lite.mjs +7 -3
  74. package/packages/shared-skills/skills/ulw-research/scripts/html-lite.test.ts +19 -0
@@ -5,5 +5,5 @@
5
5
  "index.js": "3a2e4f2575bdfc15448f13768cd8113f8493bf04611c9fefb09b13430d6520de",
6
6
  "page-bundle.js": "bfd51e8383cf47200d57387bbbed258bce5a3a3d00c38fc108034d2888e23f0c"
7
7
  },
8
- "stagedAtUtc": "2026-11-02T13:36:22.435Z"
8
+ "stagedAtUtc": "2026-11-03T09:02:51.904Z"
9
9
  }
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: eval-integrity
3
+ description: "Assess integrity of an eval, benchmark, metric, A/B test, holdout, LLM-judge, or user-study claim when the question is whether measurement, comparison, or evidence is independent and trustworthy."
4
+ ---
5
+
6
+ # Evaluation Integrity
7
+
8
+ Provide a read-only audit of whether an evaluation can support its stated claim. Do not alter code,
9
+ data, prompts, labels, or study operations. Begin with exactly one verdict line in the form
10
+ `**Verdict: PASS**`, `**Verdict: FAIL**`, or `**Verdict: INCONCLUSIVE**`. Emit no other verdict
11
+ line and do not restate the verdict later in the report. A favorable score is not itself evidence
12
+ of integrity.
13
+
14
+ ## Route correctly
15
+
16
+ - **NOT for code review:** route implementation, correctness, security, or maintainability review to
17
+ `review-work`.
18
+ - **NOT for data processing:** route cleaning, transforming, joining, modeling, or analyzing data to
19
+ `data-scientist`.
20
+ - Use this skill for the independence and validity of the measurement setup, not for producing a
21
+ result from it.
22
+
23
+ ## Audit method
24
+
25
+ ### 1. State the claim and map the evaluation
26
+
27
+ Write the claim in testable form: what comparison, metric, threshold, or causal statement is being
28
+ made; for which population; and under which decision rule. Map every role before judging it:
29
+
30
+ | Element | Record |
31
+ | --- | --- |
32
+ | Claim | The conclusion and decision it is meant to justify. |
33
+ | System under test | Exact model, version, configuration, prompt, policy, or treatment. |
34
+ | Dataset and split | Sources, collection dates, inclusion rules, train/dev/test or holdout assignment. |
35
+ | Designer | Who selected the task, data, prompts, treatments, metric, and stopping rule. |
36
+ | Evaluator or judge | Who or what assigns quality judgments, including model and prompt versions. |
37
+ | Scorer | The rule or system that turns outputs or judgments into the reported metric. |
38
+ | Subjects | Humans, records, tasks, or units exposed to treatment or observation. |
39
+
40
+ Trace shared ownership, shared data, shared prompts, shared labels, and shared selection decisions
41
+ across this map. Several models do **not** establish independence merely because there are several
42
+ of them; identify distinct training, tuning, prompt design, labels, data, and decision authority.
43
+
44
+ ### 2. Check the ground truth
45
+
46
+ Identify the independent ground truth that could confirm the claim without reusing the system's own
47
+ preferences, outputs, labels, or optimization target. Test whether it is:
48
+
49
+ - external to the system under test and its designer;
50
+ - collected or adjudicated without seeing the treatment identity when blinding is feasible;
51
+ - appropriate to the claim rather than a proxy selected because it favors one arm; and
52
+ - fixed before comparison, or accompanied by a disclosed multiplicity and selection procedure.
53
+
54
+ If no independent ground truth exists, do not substitute agreement among related systems. Mark the
55
+ claim **INCONCLUSIVE** unless the stated claim is explicitly limited to that related system's score.
56
+
57
+ ### 3. Probe independence failures
58
+
59
+ Check only risks relevant to the mapped design:
60
+
61
+ - **Contamination:** benchmark items, answers, or near duplicates reached training, prompt design,
62
+ retrieval, tuning, or post-hoc selection.
63
+ - **Invalid controls:** arms differ beyond the intended treatment, allocation is biased, exposure is
64
+ unequal, or the control cannot answer the causal comparison.
65
+ - **Circular judging:** the evaluated system, its designer, or a derived rubric defines its own
66
+ success without external confirmation.
67
+ - **Scorer-label coupling:** labels, thresholds, reward signals, or rubric choices are reused by the
68
+ scorer in a way that makes agreement self-fulfilling.
69
+ - **Evaluator-designer coupling:** the evaluator, judge prompt, or adjudication process is selected,
70
+ tuned, or influenced by the comparison designer without an independent safeguard.
71
+ - **Split or annotator dependence:** overlapping sources, duplicates, temporal leakage, shared
72
+ annotators, or correlated annotation policies invalidate assumed independence.
73
+ - **Hypothesis priming:** task framing, examples, pre-registration gaps, or interim results steer
74
+ evaluators or analysts toward the expected outcome.
75
+ - **Observer and demand effects:** subjects or observers infer the desired treatment or outcome, and
76
+ behavior or ratings change because of that knowledge.
77
+
78
+ For each concern, distinguish documented evidence from an assumption. Missing provenance for data,
79
+ splits, labels, prompts, evaluator selection, or scoring is **INCONCLUSIVE**, not evidence that the
80
+ design was independent.
81
+
82
+ ### 4. Reach the verdict
83
+
84
+ - **PASS:** evidence supports an independent, valid measurement path for the stated claim, with no
85
+ material unresolved dependency.
86
+ - **FAIL:** evidence shows a dependency or invalid design that materially invalidates or overstates
87
+ the stated claim.
88
+ - **INCONCLUSIVE:** provenance or evidence is missing, the ground truth is not independently
89
+ established, or remaining uncertainty prevents either result.
90
+
91
+ Do not convert uncertainty into PASS because a metric looks plausible, a result is statistically
92
+ significant, or multiple related evaluators agree.
93
+
94
+ ## Report
95
+
96
+ Report the verdict first. Then report only findings that fired; do not pad the report with risks
97
+ that were checked and did not fire. For each fired finding include:
98
+
99
+ 1. **Evidence:** the observed artifact, provenance record, or explicit absence of one.
100
+ 2. **Impact:** which claim or inference the issue weakens or invalidates.
101
+ 3. **Minimal independence fix:** the smallest separation, blind, held-out source, external
102
+ adjudication, or control change that would address it.
103
+ 4. **Missing evidence:** what must be supplied to resolve the finding, if applicable.
104
+ 5. **Residual risk:** what remains uncertain after the minimal fix.
105
+
106
+ Keep conclusions bounded to the evidence. This audit advises; it does not certify a system,
107
+ recompute results, or approve deployment.
@@ -82,13 +82,16 @@ export function exportRows(ledger) {
82
82
 
83
83
  const walk = (node) => node.children.filter((child) => child.tag !== "#text").flatMap((child) => [child, ...walk(child)])
84
84
 
85
- /** SVG text nodes of a chart: data labels, or ticks with their declared grid. */
85
+ /** SVG text nodes of a chart: data labels, or ticks with their declared grid; foreignObject HTML counts as unticked labels. */
86
86
  function svgLabels(raw) {
87
- return walk(parseHtml(raw)).filter((node) => node.tag === "text").map((node) => {
87
+ const nodes = walk(parseHtml(raw))
88
+ const texts = nodes.filter((node) => node.tag === "text").map((node) => {
88
89
  let tick = null
89
90
  for (let cur = node.parent; cur && !tick; cur = cur.parent) if (cur.tag === "g" && /(?:^|\s)ticks(?:\s|$)/.test(cur.attrs.class ?? "")) tick = cur.attrs
90
91
  return { text: proseText(node), tick }
91
92
  })
93
+ const foreign = nodes.filter((node) => node.tag === "foreignobject").map((node) => ({ text: proseText(node), tick: null }))
94
+ return [...texts, ...foreign]
92
95
  }
93
96
 
94
97
  function onGrid(value, tick) {
@@ -212,6 +212,32 @@ describe("verification claims are structural (data-claim-kind)", () => {
212
212
  })
213
213
  })
214
214
 
215
+ describe("foreignObject (omo #11570)", () => {
216
+ const chartFO = (inner: string) =>
217
+ `<figure data-chart-source="assets/share.csv"><svg viewBox="0 0 200 100"><foreignObject><div xmlns="http://www.w3.org/1999/xhtml">${inner}</div></foreignObject></svg><figcaption>Share by segment [S4].</figcaption></figure>`
218
+ const valueFact = (id: string, text: string, value: string) => `<data class="fact" data-fact="${id}" value="${value}">${text}</data>`
219
+
220
+ const CASES: [string, string, string[]][] = [
221
+ ["fact element unit change", chartFO(`<p>Span ${fact("F1", "110.6 mm", "mm")} long [S4].</p>`), ["unit_mismatch", "chart_value_untraceable"]],
222
+ ["fact element digit change", chartFO(`<p>Units ${fact("F2", "1,273")} sold [S4].</p>`), ["value_mismatch", "chart_value_untraceable"]],
223
+ ["fact element digit plus value attribute", chartFO(`<p>Units ${valueFact("F2", "1,273", "1,273")} sold [S4].</p>`), ["value_mismatch", "chart_value_untraceable"]],
224
+ ["bare numeral sentence", chartFO(`<p>Growth 1234567 m [S4].</p>`), ["chart_value_untraceable"]],
225
+ ["numeral-free control", chartFO(`<p>Share by segment, no numbers here [S4].</p>`), []],
226
+ ["clean fact at a plot value", chartFO(`<p>Share ${fact("F5", "12%", "%")} total [S4].</p>`), []],
227
+ ]
228
+ for (const [name, body, want] of CASES) {
229
+ test(`#given ${name} inside foreignObject #when checked #then ${want.length ? want.join(" + ") : "clean"}`, () => {
230
+ expect(codes(run(body))).toEqual(want)
231
+ })
232
+ }
233
+
234
+ test("#given the same fact mutations in prose #when checked #then the same fact codes", () => {
235
+ expect(codes(run(`<p>Span ${fact("F1", "110.6 mm", "mm")} long [S4].</p>`))).toEqual(["unit_mismatch"])
236
+ expect(codes(run(`<p>Units ${valueFact("F2", "1,273", "1,273")} sold [S4].</p>`))).toEqual(["value_mismatch"])
237
+ expect(codes(run("<p>Growth 1234567 m [S4].</p>"))).toEqual(["untraceable_number"])
238
+ })
239
+ })
240
+
215
241
  describe("charts", () => {
216
242
  const SRC = 'data-chart-source="assets/share.csv"'
217
243
 
@@ -0,0 +1,61 @@
1
+ // html-foreign-object.mjs - the <foreignObject> carve-out for the html-lite tokenizer.
2
+ //
3
+ // An <svg> element is raw drawing markup, except <foreignObject>, which by definition holds
4
+ // HTML. The tokenizer keeps the svg's inner source in `raw` and additionally parses each
5
+ // foreignObject subtree into real children of the svg node, so the fidelity checks read chart
6
+ // HTML exactly like prose while the rest of the svg stays raw. Plain Node ESM, no dependencies.
7
+
8
+ import { makeNode, readTag } from "./html-lite.mjs"
9
+
10
+ /** Newlines in text before offset `to`. */
11
+ function newlinesBefore(text, to) {
12
+ let count = 0
13
+ for (let at = text.indexOf("\n"); at !== -1 && at < to; at = text.indexOf("\n", at + 1)) count++
14
+ return count
15
+ }
16
+
17
+ /** Shift a parsed subtree's line numbers by `delta` (fragment lines are relative to the fragment). */
18
+ function shiftLines(node, delta) {
19
+ node.line += delta
20
+ for (const child of node.children) shiftLines(child, delta)
21
+ }
22
+
23
+ const isLetter = (ch) => (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z")
24
+
25
+ /**
26
+ * Parse an svg node's <foreignObject> subtrees into real children; the rest of the svg stays raw.
27
+ * @param {object} node an <svg> LiteNode whose `raw` holds its inner source
28
+ * @param {number} rawStartLine document line of the first raw character
29
+ * @param {(source: string) => object} parseHtml the tokenizer, passed in so this module never imports it back
30
+ */
31
+ export function attachForeignObjects(node, rawStartLine, parseHtml) {
32
+ const raw = node.raw ?? ""
33
+ for (let lt = raw.indexOf("<"); lt !== -1; lt = raw.indexOf("<", lt + 1)) {
34
+ if (raw[lt + 1] === "/" || !isLetter(raw[lt + 1] ?? "")) continue
35
+ const open = readTag(raw, lt + 1)
36
+ if (open.name !== "foreignobject" || open.selfClosing) continue
37
+ let depth = 0
38
+ let innerEnd = raw.length
39
+ let resume = raw.length
40
+ for (let at = raw.indexOf("<", open.end); at !== -1; at = raw.indexOf("<", at + 1)) {
41
+ const closing = raw[at + 1] === "/"
42
+ if (!closing && !isLetter(raw[at + 1] ?? "")) continue
43
+ if (readTag(raw, at + (closing ? 2 : 1)).name !== "foreignobject") continue
44
+ if (closing) {
45
+ if (depth === 0) { innerEnd = at; const gt = raw.indexOf(">", at); resume = gt === -1 ? raw.length : gt + 1; break }
46
+ depth--
47
+ } else depth++
48
+ }
49
+ // Tags are lowercased by readTag, so the attached node is "foreignobject" like any parsed tag.
50
+ const fo = makeNode("foreignobject", open.attrs, node, rawStartLine + newlinesBefore(raw, lt))
51
+ const frag = parseHtml(raw.slice(open.end, innerEnd))
52
+ const body = frag.children.find((child) => child.tag === "body") ?? frag
53
+ for (const child of body.children) {
54
+ child.parent = fo
55
+ shiftLines(child, rawStartLine + newlinesBefore(raw, open.end) - 1)
56
+ fo.children.push(child)
57
+ }
58
+ node.children.push(fo)
59
+ lt = resume - 1
60
+ }
61
+ }
@@ -3,10 +3,13 @@
3
3
  // Single forward scan with indexOf (no whole-document regex, no backtracking). Produces a
4
4
  // LiteNode tree: { tag, attrs, children, parent, line, text, raw }. Text nodes carry
5
5
  // tag "#text"; <style>/<script>/<svg> keep their inner source in `raw` and have no parsed
6
- // children. The "#document" root also carries `ids` (id -> occurrence count) so
7
- // selectorPath can tell whether an id is unique. Plain Node ESM, no dependencies.
6
+ // children, except an <svg> node also gains its <foreignObject> subtrees as parsed children
7
+ // (see html-foreign-object.mjs; the rest of the svg stays raw). The "#document"
8
+ // root also carries `ids` (id -> occurrence count) so selectorPath can tell whether an id
9
+ // is unique. Plain Node ESM, no dependencies.
8
10
 
9
11
  import { decodeEntities } from "./entities.mjs"
12
+ import { attachForeignObjects } from "./html-foreign-object.mjs"
10
13
 
11
14
  export { decodeEntities }
12
15
 
@@ -25,7 +28,7 @@ const SAFE_ID = /^[A-Za-z_][\w-]*$/
25
28
  export const PROSE_TAGS = new Set(["p", "li", ...HEADINGS, "td", "th", "figcaption", "blockquote", "dd", "dt"])
26
29
  export const PROSE_BREAKS = new Set([...P_CLOSERS, ...PROSE_TAGS, "br", "tr"])
27
30
 
28
- function makeNode(tag, attrs, parent, line) {
31
+ export function makeNode(tag, attrs, parent, line) {
29
32
  return { tag, attrs, children: [], parent, line, text: "", raw: null }
30
33
  }
31
34
 
@@ -181,6 +184,7 @@ export function parseHtml(source) {
181
184
  if (!tag.selfClosing) {
182
185
  const [innerEnd, resume] = findRawClose(src, tag.end, tag.name)
183
186
  node.raw = src.slice(tag.end, innerEnd)
187
+ if (tag.name === "svg") attachForeignObjects(node, lineAt(starts, tag.end), parseHtml)
184
188
  at = textStart = resume
185
189
  }
186
190
  } else if (!VOID_TAGS.has(tag.name)) {
@@ -129,6 +129,25 @@ describe("parseHtml", () => {
129
129
  expect(childTags(svg.parent as LiteNode)).toEqual(["script", "svg", "p"])
130
130
  })
131
131
 
132
+ test("#given an svg with drawing markup and a foreignObject #when parsed #then raw is kept and only the foreignObject subtree is parsed", () => {
133
+ // given
134
+ const source =
135
+ "<body><svg viewBox=\"0 0 200 100\"><path d=\"M0 0\"/><text>12%</text><foreignObject>\n<div>chart 110.6 mm</div>\n</foreignObject></svg></body>"
136
+ // when
137
+ const doc = parseHtml(source)
138
+ // then
139
+ const svg = byTag(doc, "svg")[0] as LiteNode
140
+ expect(svg.raw).toBe("<path d=\"M0 0\"/><text>12%</text><foreignObject>\n<div>chart 110.6 mm</div>\n</foreignObject>")
141
+ expect(childTags(svg)).toEqual(["foreignobject"])
142
+ const fo = byTag(doc, "foreignobject")[0] as LiteNode
143
+ expect(fo.line).toBe(1)
144
+ const div = byTag(doc, "div")[0] as LiteNode
145
+ expect(div.line).toBe(2)
146
+ expect(proseText(div)).toBe("chart 110.6 mm")
147
+ expect(byTag(doc, "text")).toHaveLength(0)
148
+ expect(byTag(doc, "path")).toHaveLength(0)
149
+ })
150
+
132
151
  test("#given an unclosed fragment without body #when parsed #then the tree still has body > div > p", () => {
133
152
  // given
134
153
  const source = "<div><p>unclosed"
package/dist/tui.js CHANGED
@@ -3461,7 +3461,7 @@ var init_agent_model_requirements = __esm(() => {
3461
3461
  {
3462
3462
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
3463
3463
  model: "gpt-5.6-sol",
3464
- variant: "medium"
3464
+ variant: "high"
3465
3465
  },
3466
3466
  { providers: ["zai-coding-plan", "opencode", "bailian-coding-plan"], model: "glm-5.2" },
3467
3467
  { providers: ["opencode"], model: "big-pickle" }
@@ -3473,12 +3473,12 @@ var init_agent_model_requirements = __esm(() => {
3473
3473
  {
3474
3474
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
3475
3475
  model: "gpt-6-sol",
3476
- variant: "medium"
3476
+ variant: "high"
3477
3477
  },
3478
3478
  {
3479
3479
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
3480
3480
  model: "gpt-5.6-sol",
3481
- variant: "medium"
3481
+ variant: "high"
3482
3482
  }
3483
3483
  ],
3484
3484
  requiresProvider: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
@@ -3486,7 +3486,7 @@ var init_agent_model_requirements = __esm(() => {
3486
3486
  },
3487
3487
  oracle: {
3488
3488
  fallbackChain: [
3489
- { providers: ["openai", "chatgpt-subscription", "opencode"], model: "gpt-5.6-sol", variant: "xhigh" },
3489
+ { providers: ["openai", "chatgpt-subscription", "opencode"], model: "gpt-5.6-sol", variant: "high" },
3490
3490
  { providers: ["github-copilot"], model: "gpt-5.6-sol", variant: "high" },
3491
3491
  {
3492
3492
  providers: ["google", "google-vertex", "opencode"],
@@ -3510,7 +3510,7 @@ var init_agent_model_requirements = __esm(() => {
3510
3510
  fallbackChain: [
3511
3511
  { providers: ["kimi-for-coding"], model: "kimi-for-coding-highspeed", variant: "off" },
3512
3512
  { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptLunaFast, variant: "low" },
3513
- { providers: ["anthropic", "github-copilot"], model: LATEST_MODEL_BY_FAMILY.claudeHaiku, variant: "medium" },
3513
+ { providers: ["anthropic", "github-copilot"], model: LATEST_MODEL_BY_FAMILY.claudeHaiku, variant: "high" },
3514
3514
  { providers: ["deepseek"], model: "deepseek-flash", variant: "max" },
3515
3515
  { providers: ["opencode-go", "bailian-coding-plan"], model: "qwen3.7-plus" },
3516
3516
  { providers: ["opencode-go"], model: "minimax-m2.7" }
@@ -3520,7 +3520,7 @@ var init_agent_model_requirements = __esm(() => {
3520
3520
  fallbackChain: [
3521
3521
  { providers: ["kimi-for-coding"], model: "kimi-for-coding-highspeed", variant: "off" },
3522
3522
  { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptLunaFast, variant: "low" },
3523
- { providers: ["anthropic", "github-copilot"], model: LATEST_MODEL_BY_FAMILY.claudeHaiku, variant: "medium" },
3523
+ { providers: ["anthropic", "github-copilot"], model: LATEST_MODEL_BY_FAMILY.claudeHaiku, variant: "high" },
3524
3524
  { providers: ["deepseek"], model: "deepseek-flash", variant: "max" },
3525
3525
  { providers: ["opencode-go", "bailian-coding-plan"], model: "qwen3.7-plus" },
3526
3526
  { providers: ["opencode-go"], model: "minimax-m2.7" }
@@ -3539,12 +3539,12 @@ var init_agent_model_requirements = __esm(() => {
3539
3539
  {
3540
3540
  providers: ["anthropic", "github-copilot", "opencode"],
3541
3541
  model: FABLE_55_LAUNCH.id,
3542
- variant: "xhigh"
3542
+ variant: "high"
3543
3543
  },
3544
3544
  {
3545
3545
  providers: ["anthropic", "github-copilot", "opencode"],
3546
3546
  model: LATEST_MODEL_BY_FAMILY.claudeFable,
3547
- variant: "xhigh"
3547
+ variant: "high"
3548
3548
  },
3549
3549
  {
3550
3550
  providers: ["anthropic", "github-copilot", "opencode"],
@@ -3586,7 +3586,7 @@ var init_agent_model_requirements = __esm(() => {
3586
3586
  },
3587
3587
  momus: {
3588
3588
  fallbackChain: [
3589
- { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptAstra, variant: "xhigh" },
3589
+ { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptAstra, variant: "high" },
3590
3590
  { providers: ["github-copilot"], model: LATEST_MODEL_BY_FAMILY.gptAstra, variant: "high" },
3591
3591
  { providers: ["openai", "chatgpt-subscription", "opencode"], model: LATEST_MODEL_BY_FAMILY.gptAstra, variant: "high" },
3592
3592
  {
@@ -3614,7 +3614,7 @@ var init_agent_model_requirements = __esm(() => {
3614
3614
  {
3615
3615
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
3616
3616
  model: "gpt-5.6-sol",
3617
- variant: "medium"
3617
+ variant: "high"
3618
3618
  },
3619
3619
  { providers: ["opencode-go"], model: "minimax-m3" },
3620
3620
  { providers: ["minimax-coding-plan", "minimax-cn-coding-plan"], model: "MiniMax-M3" },
@@ -3628,7 +3628,7 @@ var init_agent_model_requirements = __esm(() => {
3628
3628
  {
3629
3629
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
3630
3630
  model: "gpt-5.6-sol",
3631
- variant: "medium"
3631
+ variant: "high"
3632
3632
  },
3633
3633
  { providers: ["opencode-go"], model: "minimax-m3" },
3634
3634
  { providers: ["minimax-coding-plan", "minimax-cn-coding-plan"], model: "MiniMax-M3" },
@@ -3683,14 +3683,14 @@ var init_category_model_requirements = __esm(() => {
3683
3683
  },
3684
3684
  "deep-low": {
3685
3685
  fallbackChain: [
3686
- { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptSol, variant: "medium" },
3687
- { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptSolFast, variant: "medium" },
3686
+ { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptSol, variant: "high" },
3687
+ { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptSolFast, variant: "high" },
3688
3688
  {
3689
3689
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
3690
3690
  model: "gpt-5.6-sol",
3691
- variant: "medium"
3691
+ variant: "high"
3692
3692
  },
3693
- { providers: ["openai", "chatgpt-subscription"], model: "gpt-5.6-sol-fast", variant: "medium" }
3693
+ { providers: ["openai", "chatgpt-subscription"], model: "gpt-5.6-sol-fast", variant: "high" }
3694
3694
  ]
3695
3695
  },
3696
3696
  "deep-high": {
@@ -3733,7 +3733,7 @@ var init_category_model_requirements = __esm(() => {
3733
3733
  {
3734
3734
  providers: ["anthropic", "anthropic-api", "github-copilot"],
3735
3735
  model: LATEST_MODEL_BY_FAMILY.claudeHaiku,
3736
- variant: "medium"
3736
+ variant: "high"
3737
3737
  },
3738
3738
  { providers: ["deepseek"], model: "deepseek-flash", variant: "off" },
3739
3739
  {
@@ -3753,16 +3753,16 @@ var init_category_model_requirements = __esm(() => {
3753
3753
  {
3754
3754
  providers: ["anthropic", "anthropic-api", "github-copilot", "opencode"],
3755
3755
  model: LATEST_MODEL_BY_FAMILY.claudeSonnet,
3756
- variant: "medium"
3756
+ variant: "high"
3757
3757
  },
3758
3758
  { providers: ["xiaomi", "opencode-go"], model: "mimo-v2.6-pro", variant: "max" },
3759
- { providers: ["xai", "github-copilot", "opencode-go"], model: "grok-4.7", variant: "xhigh" },
3759
+ { providers: ["xai", "github-copilot", "opencode-go"], model: "grok-4.7", variant: "high" },
3760
3760
  { providers: ["zai-coding-plan", "opencode-go"], model: LATEST_MODEL_BY_FAMILY.glm, variant: "high" },
3761
- { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptSol, variant: "medium" },
3761
+ { providers: ["openai", "chatgpt-subscription"], model: LATEST_MODEL_BY_FAMILY.gptSol, variant: "high" },
3762
3762
  {
3763
3763
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
3764
3764
  model: "gpt-5.6-sol",
3765
- variant: "medium"
3765
+ variant: "high"
3766
3766
  },
3767
3767
  {
3768
3768
  providers: ["anthropic", "anthropic-api", "github-copilot", "opencode"],
@@ -3783,7 +3783,7 @@ var init_category_model_requirements = __esm(() => {
3783
3783
  {
3784
3784
  providers: ["anthropic", "anthropic-api", "github-copilot", "opencode"],
3785
3785
  model: LATEST_MODEL_BY_FAMILY.claudeOpus,
3786
- variant: "medium"
3786
+ variant: "high"
3787
3787
  },
3788
3788
  { providers: ["zai-coding-plan", "opencode-go"], model: LATEST_MODEL_BY_FAMILY.glm, variant: "max" },
3789
3789
  {
@@ -5549,7 +5549,7 @@ var init_openai_categories = __esm(() => {
5549
5549
  },
5550
5550
  {
5551
5551
  name: "deep-low",
5552
- config: { model: `openai/${LATEST_MODEL_BY_FAMILY.gptSol}`, variant: "medium" },
5552
+ config: { model: `openai/${LATEST_MODEL_BY_FAMILY.gptSol}`, variant: "high" },
5553
5553
  description: "Default deep lane: one goal, one deliverable, decisions the child can settle from what it reads; preferred over deep-high for 3D graphics, computer/browser use, CAPTCHA, multimodal, backend, logic, and algorithm work. Multiple goals fan out as parallel calls.",
5554
5554
  callerGuidance: DEEP_LOW_CATEGORY_CALLER_GUIDANCE,
5555
5555
  promptAppend: DEEP_LOW_CATEGORY_PROMPT_APPEND,
@@ -5574,14 +5574,14 @@ var init_openai_categories = __esm(() => {
5574
5574
  },
5575
5575
  {
5576
5576
  name: "unspecified-low",
5577
- config: { model: `anthropic/${LATEST_MODEL_BY_FAMILY.claudeSonnet}`, variant: "medium" },
5577
+ config: { model: `anthropic/${LATEST_MODEL_BY_FAMILY.claudeSonnet}`, variant: "high" },
5578
5578
  description: "Tasks that don't fit other categories, low effort required",
5579
5579
  callerGuidance: UNSPECIFIED_LOW_CATEGORY_CALLER_GUIDANCE,
5580
5580
  promptAppend: UNSPECIFIED_LOW_CATEGORY_PROMPT_APPEND
5581
5581
  },
5582
5582
  {
5583
5583
  name: "unspecified-high",
5584
- config: { model: `anthropic/${LATEST_MODEL_BY_FAMILY.claudeOpus}`, variant: "medium" },
5584
+ config: { model: `anthropic/${LATEST_MODEL_BY_FAMILY.claudeOpus}`, variant: "high" },
5585
5585
  description: "Tasks that don't fit other categories, high effort required",
5586
5586
  callerGuidance: UNSPECIFIED_HIGH_CATEGORY_CALLER_GUIDANCE,
5587
5587
  promptAppend: UNSPECIFIED_HIGH_CATEGORY_PROMPT_APPEND,
@@ -75719,7 +75719,7 @@ init_shared();
75719
75719
  // package.json
75720
75720
  var package_default = {
75721
75721
  name: "oh-my-opencode",
75722
- version: "5.1.58",
75722
+ version: "5.1.59",
75723
75723
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
75724
75724
  main: "./dist/index.js",
75725
75725
  types: "dist/index.d.ts",
@@ -75906,7 +75906,7 @@ var package_default = {
75906
75906
  },
75907
75907
  devDependencies: {
75908
75908
  "@clack/prompts": "^1.8.1",
75909
- "@code-yeongyu/senpi": "2026.11.2-1",
75909
+ "@code-yeongyu/senpi": "2026.11.2-3",
75910
75910
  "@modelcontextprotocol/sdk": "^1.30.0",
75911
75911
  "@oh-my-opencode/agents-md-core": "workspace:*",
75912
75912
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
@@ -75971,18 +75971,18 @@ var package_default = {
75971
75971
  typescript: "^7.0.2"
75972
75972
  },
75973
75973
  optionalDependencies: {
75974
- "oh-my-opencode-darwin-arm64": "5.1.58",
75975
- "oh-my-opencode-darwin-x64": "5.1.58",
75976
- "oh-my-opencode-darwin-x64-baseline": "5.1.58",
75977
- "oh-my-opencode-linux-arm64": "5.1.58",
75978
- "oh-my-opencode-linux-arm64-musl": "5.1.58",
75979
- "oh-my-opencode-linux-x64": "5.1.58",
75980
- "oh-my-opencode-linux-x64-baseline": "5.1.58",
75981
- "oh-my-opencode-linux-x64-musl": "5.1.58",
75982
- "oh-my-opencode-linux-x64-musl-baseline": "5.1.58",
75983
- "oh-my-opencode-windows-arm64": "5.1.58",
75984
- "oh-my-opencode-windows-x64": "5.1.58",
75985
- "oh-my-opencode-windows-x64-baseline": "5.1.58"
75974
+ "oh-my-opencode-darwin-arm64": "5.1.59",
75975
+ "oh-my-opencode-darwin-x64": "5.1.59",
75976
+ "oh-my-opencode-darwin-x64-baseline": "5.1.59",
75977
+ "oh-my-opencode-linux-arm64": "5.1.59",
75978
+ "oh-my-opencode-linux-arm64-musl": "5.1.59",
75979
+ "oh-my-opencode-linux-x64": "5.1.59",
75980
+ "oh-my-opencode-linux-x64-baseline": "5.1.59",
75981
+ "oh-my-opencode-linux-x64-musl": "5.1.59",
75982
+ "oh-my-opencode-linux-x64-musl-baseline": "5.1.59",
75983
+ "oh-my-opencode-windows-arm64": "5.1.59",
75984
+ "oh-my-opencode-windows-x64": "5.1.59",
75985
+ "oh-my-opencode-windows-x64-baseline": "5.1.59"
75986
75986
  },
75987
75987
  overrides: {
75988
75988
  hono: "^4.13.8",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "5.1.58",
3
+ "version": "5.1.59",
4
4
  "description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
5
5
  "main": "./dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -187,7 +187,7 @@
187
187
  },
188
188
  "devDependencies": {
189
189
  "@clack/prompts": "^1.8.1",
190
- "@code-yeongyu/senpi": "2026.11.2-1",
190
+ "@code-yeongyu/senpi": "2026.11.2-3",
191
191
  "@modelcontextprotocol/sdk": "^1.30.0",
192
192
  "@oh-my-opencode/agents-md-core": "workspace:*",
193
193
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
@@ -252,18 +252,18 @@
252
252
  "typescript": "^7.0.2"
253
253
  },
254
254
  "optionalDependencies": {
255
- "oh-my-opencode-darwin-arm64": "5.1.58",
256
- "oh-my-opencode-darwin-x64": "5.1.58",
257
- "oh-my-opencode-darwin-x64-baseline": "5.1.58",
258
- "oh-my-opencode-linux-arm64": "5.1.58",
259
- "oh-my-opencode-linux-arm64-musl": "5.1.58",
260
- "oh-my-opencode-linux-x64": "5.1.58",
261
- "oh-my-opencode-linux-x64-baseline": "5.1.58",
262
- "oh-my-opencode-linux-x64-musl": "5.1.58",
263
- "oh-my-opencode-linux-x64-musl-baseline": "5.1.58",
264
- "oh-my-opencode-windows-arm64": "5.1.58",
265
- "oh-my-opencode-windows-x64": "5.1.58",
266
- "oh-my-opencode-windows-x64-baseline": "5.1.58"
255
+ "oh-my-opencode-darwin-arm64": "5.1.59",
256
+ "oh-my-opencode-darwin-x64": "5.1.59",
257
+ "oh-my-opencode-darwin-x64-baseline": "5.1.59",
258
+ "oh-my-opencode-linux-arm64": "5.1.59",
259
+ "oh-my-opencode-linux-arm64-musl": "5.1.59",
260
+ "oh-my-opencode-linux-x64": "5.1.59",
261
+ "oh-my-opencode-linux-x64-baseline": "5.1.59",
262
+ "oh-my-opencode-linux-x64-musl": "5.1.59",
263
+ "oh-my-opencode-linux-x64-musl-baseline": "5.1.59",
264
+ "oh-my-opencode-windows-arm64": "5.1.59",
265
+ "oh-my-opencode-windows-x64": "5.1.59",
266
+ "oh-my-opencode-windows-x64-baseline": "5.1.59"
267
267
  },
268
268
  "overrides": {
269
269
  "hono": "^4.13.8",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omo",
3
- "version": "5.1.58",
3
+ "version": "5.1.59",
4
4
  "description": "One Codex plugin namespace for Yeongyu's local Codex components.",
5
5
  "author": {
6
6
  "name": "Yeongyu Kim",
@@ -8,7 +8,7 @@
8
8
  "command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
9
9
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
10
10
  "timeout": 30,
11
- "statusMessage": "(OmO 5.1.58) Checking Bootstrap Provisioning"
11
+ "statusMessage": "(OmO 5.1.59) Checking Bootstrap Provisioning"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-bootstrap",
3
- "version": "5.1.58",
3
+ "version": "5.1.59",
4
4
  "description": "Codex SessionStart bootstrap component that provisions LazyCodex runtime dependencies from a detached worker.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
10
10
  "timeout": 30,
11
- "statusMessage": "(OmO 5.1.58) Checking Comments"
11
+ "statusMessage": "(OmO 5.1.59) Checking Comments"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-comment-checker",
3
- "version": "5.1.58",
3
+ "version": "5.1.59",
4
4
  "description": "Codex plugin that runs comment-checker after edit-like PostToolUse hooks.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
10
10
  "timeout": 5,
11
- "statusMessage": "(OmO 5.1.58) Recommending Git Bash MCP"
11
+ "statusMessage": "(OmO 5.1.59) Recommending Git Bash MCP"
12
12
  }
13
13
  ]
14
14
  }
@@ -20,7 +20,7 @@
20
20
  "type": "command",
21
21
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
22
22
  "timeout": 5,
23
- "statusMessage": "(OmO 5.1.58) Resetting Git Bash MCP Reminder"
23
+ "statusMessage": "(OmO 5.1.59) Resetting Git Bash MCP Reminder"
24
24
  }
25
25
  ]
26
26
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-git-bash-hook",
3
- "version": "5.1.58",
3
+ "version": "5.1.59",
4
4
  "description": "Codex hook component that reminds Windows sessions to prefer the OMO git_bash MCP.",
5
5
  "type": "module",
6
6
  "private": true,