oh-my-opencode 5.1.46 → 5.1.47

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 (101) hide show
  1. package/.agents/command/publish.md +3 -4
  2. package/.agents/skills/publish/SKILL.md +3 -4
  3. package/.opencode/command/publish.md +3 -4
  4. package/dist/agents/atlas/agent.d.ts +3 -2
  5. package/dist/agents/sisyphus/index.d.ts +1 -0
  6. package/dist/agents/sisyphus/kimi-k3-1.d.ts +9 -0
  7. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  8. package/dist/agents/sisyphus-junior/agent.d.ts +1 -1
  9. package/dist/agents/sisyphus-junior/index.d.ts +1 -0
  10. package/dist/agents/sisyphus-junior/kimi-k3-1.d.ts +6 -0
  11. package/dist/agents/types.d.ts +2 -2
  12. package/dist/cli/index.js +29 -21
  13. package/dist/cli/service-auth/keystore.d.ts +8 -3
  14. package/dist/cli-node/index.js +29 -21
  15. package/dist/index.js +634 -17
  16. package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
  17. package/dist/skills/ulw-research/SKILL.md +1 -1
  18. package/dist/skills/ulw-research/references/deliverable-phase.md +9 -2
  19. package/dist/skills/ulw-research/scripts/copy-returns-polish.test.ts +209 -0
  20. package/dist/skills/ulw-research/scripts/fact-commands-meaning.mjs +7 -22
  21. package/dist/skills/ulw-research/scripts/fact-commands-polish.mjs +127 -0
  22. package/dist/skills/ulw-research/scripts/fact-commands-verify.mjs +19 -0
  23. package/dist/skills/ulw-research/scripts/fact-commands.mjs +4 -2
  24. package/dist/skills/ulw-research/scripts/fact-pairs.mjs +7 -9
  25. package/dist/skills/ulw-research/scripts/fact-pairs.test.ts +7 -23
  26. package/dist/skills/ulw-research/scripts/references-fences.test.ts +25 -0
  27. package/dist/skills/ulw-research/scripts/report-tools.test.ts +87 -0
  28. package/dist/skills/ulw-research/scripts/tests/fixtures/fidelity/polish-edits.json +12 -0
  29. package/dist/tui.js +13 -13
  30. package/package.json +13 -13
  31. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  32. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +1 -2
  33. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  34. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  35. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  36. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  38. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  39. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  40. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  41. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  42. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  43. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  44. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  45. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  46. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  47. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  48. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  49. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  50. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  51. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  52. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  53. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  54. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  55. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  56. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  57. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  58. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  59. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  60. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  61. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  62. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  63. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  64. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  65. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  66. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  67. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  68. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  69. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  70. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  71. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  72. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  73. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  74. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  75. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  76. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  77. package/packages/omo-codex/plugin/package-lock.json +12 -12
  78. package/packages/omo-codex/plugin/package.json +1 -1
  79. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +1 -1
  80. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  81. package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +9 -2
  82. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +7 -22
  83. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-polish.mjs +127 -0
  84. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +19 -0
  85. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +4 -2
  86. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-pairs.mjs +7 -9
  87. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -1
  88. package/packages/omo-codex/scripts/install-dist/install-local.mjs +4 -5
  89. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
  90. package/packages/shared-skills/skills/ulw-research/SKILL.md +1 -1
  91. package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +9 -2
  92. package/packages/shared-skills/skills/ulw-research/scripts/copy-returns-polish.test.ts +209 -0
  93. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +7 -22
  94. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-polish.mjs +127 -0
  95. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +19 -0
  96. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +4 -2
  97. package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.mjs +7 -9
  98. package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.test.ts +7 -23
  99. package/packages/shared-skills/skills/ulw-research/scripts/references-fences.test.ts +25 -0
  100. package/packages/shared-skills/skills/ulw-research/scripts/report-tools.test.ts +87 -0
  101. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/polish-edits.json +12 -0
@@ -39,8 +39,8 @@ function filled(): { out: string; fillMap: { fact_id: string }[] } {
39
39
  }
40
40
 
41
41
  function pairs(): Pair[] {
42
- const { out, fillMap } = filled()
43
- return extractPairs(out, LEDGER, CLAIMS, fillMap) as Pair[]
42
+ const { out } = filled()
43
+ return extractPairs(out, LEDGER, CLAIMS) as Pair[]
44
44
  }
45
45
 
46
46
  describe("extractPairs: a filled report", () => {
@@ -110,14 +110,7 @@ describe("extractPairs: a filled report", () => {
110
110
  expect(sentences.some((text) => text.includes("Bridge authority"))).toBe(false)
111
111
  })
112
112
 
113
- test("#given a fill map that omits a fact #when extracted #then that hand-typed fact yields no pair", () => {
114
- const { out, fillMap } = filled()
115
- const kept = fillMap.filter((entry) => entry.fact_id !== "F13")
116
- const result = extractPairs(out, LEDGER, CLAIMS, kept) as Pair[]
117
- expect(result.some((pair) => Array.isArray(pair.fact_ids) && (pair.fact_ids as string[]).includes("F13"))).toBe(false)
118
- })
119
-
120
- test("#given no fill map #when extracted #then every data-fact element counts as filled", () => {
113
+ test("#given the filled fixture #when extracted #then every data-fact element yields its pair", () => {
121
114
  const { out } = filled()
122
115
  expect((extractPairs(out, LEDGER, CLAIMS) as Pair[]).length).toBe(6)
123
116
  })
@@ -125,20 +118,11 @@ describe("extractPairs: a filled report", () => {
125
118
  test("#given a Hangul quote #when extracted #then source_lang is ko", () => {
126
119
  const html = "<html><body><h2>Findings</h2><p>HBM revenue reached {{F21:hbm_rev}} [S5].</p></body></html>"
127
120
  const result = fill(html, LEDGER, { format: "html" }) as { out: string; fillMap: { fact_id: string }[] }
128
- const [pair] = extractPairs(result.out, LEDGER, CLAIMS, result.fillMap) as Pair[]
121
+ const [pair] = extractPairs(result.out, LEDGER, CLAIMS) as Pair[]
129
122
  expect(pair).toMatchObject({ fact_ids: ["F21"], source_lang: "ko", report_lang: "en" })
130
123
  })
131
124
  })
132
125
 
133
- describe("extractPairs: a fill map over translations", () => {
134
- test("#given a fill map that omits the translated fact #when extracted #then no translation pair is emitted", () => {
135
- const { out, fillMap } = filled()
136
- const kept = fillMap.filter((entry) => entry.fact_id !== "Q7")
137
- const result = extractPairs(out, LEDGER, CLAIMS, kept) as Pair[]
138
- expect(result.some((pair) => pair.kind === "translation")).toBe(false)
139
- })
140
- })
141
-
142
126
  describe("hasHedge: a month is not a hedge", () => {
143
127
  test("#given a text that starts with the month May #when checked #then it does not count as hedged", () => {
144
128
  expect(hasHedge("May 2024 sales rose.")).toBe(false)
@@ -152,9 +136,9 @@ describe("hasHedge: a month is not a hedge", () => {
152
136
 
153
137
  describe("extractPairs: determinism", () => {
154
138
  test("#given the same filled report twice #when extracted #then both results are byte-for-byte equal", () => {
155
- const { out, fillMap } = filled()
156
- const first = JSON.stringify(extractPairs(out, LEDGER, CLAIMS, fillMap))
157
- const second = JSON.stringify(extractPairs(out, LEDGER, CLAIMS, fillMap))
139
+ const { out } = filled()
140
+ const first = JSON.stringify(extractPairs(out, LEDGER, CLAIMS))
141
+ const second = JSON.stringify(extractPairs(out, LEDGER, CLAIMS))
158
142
  expect(second).toBe(first)
159
143
  })
160
144
  })
@@ -0,0 +1,25 @@
1
+ // Every references/*.md must have balanced code fences: an unclosed fence renders prose as code
2
+ // and flips every later fence in the file. md-lite is the parser the skill's own tools use.
3
+ import { describe, expect, test } from "bun:test"
4
+ import { readdirSync, readFileSync } from "node:fs"
5
+ import { join } from "node:path"
6
+
7
+ import { parseMarkdown } from "./md-lite.mjs"
8
+
9
+ const REFERENCES = join(import.meta.dir, "..", "references")
10
+ const FILES = readdirSync(REFERENCES).filter((name) => name.endsWith(".md")).sort()
11
+
12
+ describe("references/*.md fence parity", () => {
13
+ test("#given the references directory #when listed #then it holds the reference pages", () => {
14
+ expect(FILES.length).toBeGreaterThan(0)
15
+ })
16
+
17
+ for (const name of FILES) {
18
+ test(`#given ${name} #when its fences are counted #then the count is even and md-lite reports no problem`, () => {
19
+ const text = readFileSync(join(REFERENCES, name), "utf8")
20
+ const fences = text.split("\n").filter((line) => /^ {0,3}(`{3,}|~{3,})/u.test(line))
21
+ expect(fences.length % 2, `${name} has ${fences.length} fence lines`).toBe(0)
22
+ expect(parseMarkdown(text).problems).toEqual([])
23
+ })
24
+ }
25
+ })
@@ -8,6 +8,7 @@ import { PROMOTION } from "./fact-commands-meaning.mjs"
8
8
  import { writeFidelityRecord } from "./fidelity-records.mjs"
9
9
  import { PAIR_KINDS } from "./fact-pairs.mjs"
10
10
  import { VERDICT_SCHEMA } from "./meaning-check.mjs"
11
+ import { POLISH_MARKUP_REASON } from "./polish-apply.mjs"
11
12
  import { COMMANDS, run } from "./report-tools.mjs"
12
13
 
13
14
  const SCRIPT = join(import.meta.dir, "report-tools.mjs")
@@ -503,6 +504,92 @@ describe("meaning verifier under node", () => {
503
504
  })
504
505
  })
505
506
 
507
+ type PolishJson = { data: { out: string; applied: number; rejected: number; unlocated: number }; defects: { code: string; index: number; reason?: string }[] }
508
+
509
+ /** A filled session whose first finding names an acquirer and a target around F1. */
510
+ function polishSession() {
511
+ const session = fidelitySession()
512
+ const { dir, s } = session
513
+ const source = readFileSync(join(dir, "report.src.html"), "utf8").replace("<p>The span length is", "<p>Acme acquired Bolt before the span length reached")
514
+ writeFileSync(join(dir, "report.src.html"), source)
515
+ nodeJson(["fact", "fill", join(dir, "report.src.html"), "--out", join(dir, "report.html"), ...s])
516
+ return session
517
+ }
518
+
519
+ function polishApply(dir: string, edits: string) {
520
+ const args = ["fact", "polish-apply", join(dir, "report.html"), "--edits", edits, "--ledger", join(dir, "fact-ledger.json"), "--out", join(dir, "report.polished.html")]
521
+ const proc = nodeJson(args)
522
+ return { ...proc, json: proc.json as unknown as PolishJson }
523
+ }
524
+
525
+ describe("polish wiring under node", () => {
526
+ test("#given the fixture edits #when fact polish-apply runs #then it exits 0, applies the wording edit, and rejects the numeral edit", () => {
527
+ const { dir } = polishSession()
528
+ const applied = polishApply(dir, join(FIDELITY, "polish-edits.json"))
529
+ const polished = readFileSync(join(dir, "report.polished.html"), "utf8")
530
+ expect(applied.code).toBe(0)
531
+ expect(applied.json.data).toMatchObject({ applied: 1, rejected: 1, unlocated: 0 })
532
+ expect(applied.json.defects.map((d) => [d.code, d.index])).toEqual([["polish_edit_rejected", 1]])
533
+ expect(polished).toContain("Collected from a single cited public page")
534
+ expect(polished).toContain("retrieved 2026-10-01")
535
+ expect(polished).not.toContain("2026-10-02")
536
+ })
537
+
538
+ test("#given an edit that adds an attribute #when polish-apply and polish-diff run #then apply refuses it as markup changed and diff exits 1", () => {
539
+ const { dir } = polishSession()
540
+ const html = readFileSync(join(dir, "report.html"), "utf8")
541
+ const edits = join(dir, "attribute.json")
542
+ writeFileSync(edits, JSON.stringify([{ before: "<h2>Findings</h2>", after: '<h2 id="findings">Findings</h2>', reason: "anchor" }]))
543
+ const applied = polishApply(dir, edits)
544
+ expect(applied.code).toBe(0)
545
+ expect(applied.json.data).toMatchObject({ applied: 0, rejected: 1, unlocated: 0 })
546
+ expect(applied.json.defects.map((d) => [d.code, d.index])).toEqual([["polish_edit_rejected", 0]])
547
+ expect(applied.json.defects[0]?.reason).toContain("markup changed")
548
+ expect(readFileSync(join(dir, "report.polished.html"), "utf8")).toBe(html)
549
+ writeFileSync(join(dir, "attribute.html"), html.replace("<h2>Findings</h2>", '<h2 id="findings">Findings</h2>'))
550
+ const diffed = nodeJson(["fact", "polish-diff", "--before", join(dir, "report.html"), "--after", join(dir, "attribute.html"), "--ledger", join(dir, "fact-ledger.json")])
551
+ expect(diffed.code).toBe(1)
552
+ expect(codesOf(diffed.json)).toContain("polish_diff_fail")
553
+ expect(JSON.stringify(diffed.json)).toContain("markup changed")
554
+ })
555
+
556
+ test("#given an edit whose before holds & #when fact polish-apply runs #then it prints polish-apply's own markup reason verbatim for that edit", () => {
557
+ const { dir } = polishSession()
558
+ const before = "Acme & Bolt"
559
+ const edits = join(dir, "ampersand.json")
560
+ writeFileSync(edits, JSON.stringify([{ before, after: "Acme and Bolt", reason: "ampersand" }]))
561
+ const applied = polishApply(dir, edits)
562
+ const line = ` rejected edit 0 ("${before}"): ${POLISH_MARKUP_REASON}`
563
+ expect(applied.code).toBe(0)
564
+ expect(applied.json.data).toMatchObject({ applied: 0, rejected: 1, unlocated: 0 })
565
+ expect(applied.json.defects.map((d) => [d.code, d.index, d.reason])).toEqual([["polish_edit_rejected", 0, POLISH_MARKUP_REASON]])
566
+ expect(applied.stderr.split("\n")).toContain(line)
567
+ })
568
+
569
+ test("#given a polished copy edited by hand #when fact polish-diff runs #then it exits 1 with polish_diff_fail", () => {
570
+ const { dir } = polishSession()
571
+ const html = readFileSync(join(dir, "report.html"), "utf8")
572
+ writeFileSync(join(dir, "hand.html"), html.replace("320 m", "321 m"))
573
+ const diffed = nodeJson(["fact", "polish-diff", "--before", join(dir, "report.html"), "--after", join(dir, "hand.html"), "--ledger", join(dir, "fact-ledger.json")])
574
+ expect(diffed.code).toBe(1)
575
+ expect(codesOf(diffed.json)).toContain("polish_diff_fail")
576
+ })
577
+
578
+ test("#given an accepted subject and object swap #when fact pairs runs with --changed-since #then only that sentence's pair is emitted, with the new text", () => {
579
+ const { dir, s } = polishSession()
580
+ const edits = join(dir, "swap.json")
581
+ writeFileSync(edits, JSON.stringify([{ before: "Acme acquired Bolt", after: "Bolt acquired Acme", reason: "word order" }]))
582
+ const applied = polishApply(dir, edits)
583
+ const map = join(dir, "report.html.fill-map.json")
584
+ const changed = nodeJson(["fact", "pairs", join(dir, "report.polished.html"), "--changed-since", map, "--out", join(dir, "pairs-changed.json"), ...s])
585
+ const written = JSON.parse(readFileSync(join(dir, "pairs-changed.json"), "utf8"))
586
+ expect(applied.json.data).toMatchObject({ applied: 1, rejected: 0 })
587
+ expect(changed.code).toBe(0)
588
+ expect(written.pairs.map((p: Pair) => [p.kind, p.fact_ids])).toEqual([["quote", ["F1"]]])
589
+ expect(written.pairs[0].sentence).toContain("Bolt acquired Acme")
590
+ })
591
+ })
592
+
506
593
  describe("markdown editions under node", () => {
507
594
  const MD = ["# Bridge", "", "## Findings", "", "The span length is {{F1:span_len}} [S4].", "", "The operator wrote {{Q1:completion}} [S4].", "", "## How this report was made", "", "Collected from one cited public page [S4].", "", "## Sources", "", "1. [S4] Bridge page, retrieved 2026-10-01.", ""].join("\n")
508
595
 
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "before": "Collected from one cited public page [S4].",
4
+ "after": "Collected from a single cited public page [S4].",
5
+ "reason": "Smoother wording."
6
+ },
7
+ {
8
+ "before": "[S4] Bridge page, retrieved 2026-10-01.",
9
+ "after": "[S4] Bridge page, retrieved 2026-10-02.",
10
+ "reason": "Date typo."
11
+ }
12
+ ]