okstra 0.130.0 → 0.130.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.130.0",
3
+ "version": "0.130.1",
4
4
  "description": "Multi-agent cross-verification orchestrator runtime + Claude Code skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.130.0",
3
- "builtAt": "2026-07-21T10:12:29.478Z",
2
+ "package": "0.130.1",
3
+ "builtAt": "2026-07-21T10:57:23.020Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -2,10 +2,12 @@
2
2
  producer/consumer of final-report (and schedule) tables.
3
3
 
4
4
  GFM treats every unescaped ``|`` inside a cell as a column boundary — even
5
- inside inline-code spans — and renders ``\\|`` back as a literal ``|``.
6
- Producers therefore escape cell text with ``escape_pipes`` (exposed as the
7
- ``mdcell`` Jinja filter in ``render_final_report``), and consumers split rows
8
- with ``split_pipe_row``, which honours the same ``\\|`` convention.
5
+ inside inline-code spans — and renders ``\\|`` back as a literal ``|``. A row
6
+ is also line-terminated, so a newline inside a value truncates the row at that
7
+ point and drops every column after it. Producers therefore normalise cell text
8
+ with ``to_cell_text`` (exposed as the ``mdcell`` Jinja filter in
9
+ ``render_final_report``), and consumers split rows with ``split_pipe_row``,
10
+ which honours the same ``\\|`` convention.
9
11
  """
10
12
  from __future__ import annotations
11
13
 
@@ -17,17 +19,24 @@ UNESCAPED_PIPE_RE = re.compile(r"(?<!\\)\|")
17
19
 
18
20
  _SEPARATOR_CELL_RE = re.compile(r"\s*:?-+:?\s*")
19
21
 
22
+ _NEWLINE_RE = re.compile(r"\r\n|\r|\n")
20
23
 
21
- def escape_pipes(value: Any) -> str:
22
- """Escape literal ``|`` as ``\\|`` for use inside a markdown table cell.
23
24
 
24
- Idempotent: pipes that are already escaped are left alone, so re-rendering
25
- (Phase 7) never stacks backslashes. ``None`` renders as the empty string
26
- the same contract as the template's ``or ''`` fallbacks.
25
+ def to_cell_text(value: Any) -> str:
26
+ """Render a value as one markdown table cell: no newlines, no bare ``|``.
27
+
28
+ Newlines fold to ``<br>`` (a blank line becomes ``<br><br>``, keeping the
29
+ paragraph break visible) and literal ``|`` is escaped as ``\\|``.
30
+
31
+ Idempotent: pipes that are already escaped are left alone and the folded
32
+ ``<br>`` carries no newline, so re-rendering (Phase 7) never stacks
33
+ backslashes or breaks. ``None`` renders as the empty string — the same
34
+ contract as the template's ``or ''`` fallbacks.
27
35
  """
28
36
  if value is None:
29
37
  return ""
30
- return UNESCAPED_PIPE_RE.sub(r"\\|", str(value))
38
+ folded = _NEWLINE_RE.sub("<br>", str(value).strip())
39
+ return UNESCAPED_PIPE_RE.sub(r"\\|", folded)
31
40
 
32
41
 
33
42
  def split_pipe_row(line: str) -> list[str]:
@@ -50,7 +50,7 @@ from jinja2 import ChainableUndefined, Environment, FileSystemLoader
50
50
 
51
51
  from okstra_ctl.final_report_schema import SchemaError, load_schema, validate as schema_validate
52
52
  from okstra_ctl.i18n import I18nError, SUPPORTED_LANGS, load_dictionary, make_jinja_global
53
- from okstra_ctl.md_table import UNESCAPED_PIPE_RE, escape_pipes
53
+ from okstra_ctl.md_table import UNESCAPED_PIPE_RE, to_cell_text
54
54
  from okstra_ctl.models import UnknownModelError, resolve_model_metadata
55
55
  from okstra_ctl.schema_excerpt import excerpt_cut_from_version
56
56
  from okstra_ctl.seeding import installed_version
@@ -437,10 +437,12 @@ def _build_environment(template_dir: Path) -> Environment:
437
437
  env.filters["yaml_scalar"] = _yaml_scalar
438
438
  env.filters["yaml_inline_list"] = _yaml_inline_list
439
439
  env.filters["model_detail"] = _model_detail
440
- # `mdcell` escapes literal `|` in worker prose so a value like "PASS|FAIL"
441
- # cannot split a markdown table row. Table-cell interpolations only —
442
- # never code blocks / headings / prose, where `\|` would render verbatim.
443
- env.filters["mdcell"] = escape_pipes
440
+ # `mdcell` neutralises the two things in worker prose that can break a
441
+ # markdown table row: a literal `|` (splits the row) and a newline
442
+ # (truncates it, dropping every later column). Table-cell interpolations
443
+ # only — never code blocks / headings / prose, where `\|` and `<br>` would
444
+ # render verbatim.
445
+ env.filters["mdcell"] = to_cell_text
444
446
  # `mdquote` re-marks continuation lines of a blockquote nested in a list
445
447
  # item; the fenced siblings use Jinja's builtin `indent` for the same
446
448
  # reason. Both exist because only the first line of an interpolation