YamlReporter: structuredOutput is stored as a JSON-encoded string inside a block scalar, not as native YAML data
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 78/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 静か
- 技術スタック
- typescript, yaml
- 領域
- tooling
調査の方向性
src/reporters/yaml.ts から始めて、現在はシリアライズされた部分文字列だけを検証している既存の YAML reporter のテストを確認してください。structuredOutput のパスを変更する前に、そのテストを実行してください。YAML パーサーが入力と同じネストされたデータを持つオブジェクトとして structuredOutput を返し、既存のレポート動作が維持されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Observed behavior
When a successful result includes structuredOutput, YamlReporter.append serialises it by JSON.stringify'ing the value and writing the resulting text into a YAML block scalar:
// src/reporters/yaml.ts
if (result.structuredOutput !== undefined) {
lines.push('structuredOutput: |');
const json = JSON.stringify(result.structuredOutput, null, 2);
for (const line of formatBlockScalar(json).split('\n')) {
lines.push(line === '' ? /* istanbul ignore next */ '' : ` ${line}`);
}
}
A consumer parsing the report file with any YAML loader gets back structuredOutput as a string containing JSON, not as the structured object the agent produced. To use the data they have to do a second JSON.parse step that they would not have to do for any other field in the report.
This is inconsistent with JsonlReporter, which spreads the result into the output line:
// src/reporters/jsonl.ts
const output = `${JSON.stringify({ ...prompt, ...result })}\n`;
For the JSONL reporter, structuredOutput round-trips as a nested object, so a consumer can read entry.structuredOutput.found directly. Switching the configured reporter from JSONL to YAML (or to the default, which is YAML) silently changes the shape of structuredOutput from "structured object" to "JSON-encoded string".
The existing test only asserts that the YAML contains the substrings "found": true and "a.ts": "bug", so the bug is not caught.
Expected behavior
structuredOutput is documented in src/types.ts as "the parsed object that conforms to the schema". A reporter that persists a result entry should preserve that shape: parsing the YAML report should yield an object, not a string. This is also what users will expect from a structured-data report format.
Minimal reproduction
import { mkdtemp, readFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { parseAllDocuments } from 'yaml';
import { YamlReporter } from 'loop-the-loop/reporters/yaml';
const dir = await mkdtemp(join(tmpdir(), 'yaml-structured-bug-'));
const reporter = await YamlReporter.create({ outputDir: dir, jobName: 'demo' });
await reporter.append(
{ id: 'a', prompt: 'p' },
{
status: 'success',
output: 'ok',
structuredOutput: { found: true, items: ['a', 'b'] },
},
);
const text = await readFile(join(dir, 'demo-report.yaml'), 'utf-8');
const obj = parseAllDocuments(text)[0].toJS();
console.log(typeof obj.structuredOutput); // 'string'
console.log(obj.structuredOutput.found); // undefined
console.log(JSON.parse(obj.structuredOutput).found); // true
Suggested fix
Emit structuredOutput as native YAML so it round-trips as an object. The minimal change is to use a YAML serializer for this single field (the rest of the entry could stay hand-written for now):
import { stringify } from 'yaml';
if (result.structuredOutput !== undefined) {
// `stringify` returns a trailing newline; indent under the parent key
const yaml = stringify(result.structuredOutput, { indent: 2 });
lines.push('structuredOutput:');
for (const line of yaml.trimEnd().split('\n')) {
lines.push(` ${line}`);
}
}
The longer-term fix is to delegate serialization of the whole entry to a YAML library, which also resolves the related issues #69 (id field not escaped) and #75 (block scalar indent bug). A test that round-trips structuredOutput through a real YAML parser and asserts deep-equality with the input would prevent regression.
- 主要言語
- TypeScript
- スター
- 2
- フォーク
- 1
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
joewalker/loop-the-loop のほかの issue
-
bug S4
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
joewalker/loop-the-loop#88 ·
-
Git exec(): child killed by a signal rejects with new Error('') and loses the signal informationオープンbug S3
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
joewalker/loop-the-loop#84 ·
-
bug S3
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
joewalker/loop-the-loop#83 ·
-
bug S3
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
joewalker/loop-the-loop#82 ·
-
bug S4
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
joewalker/loop-the-loop#79 ·
joewalker/loop-the-loop の issue をすべて見る
似ている issue
-
bug P3 UI/UX
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
StellarState/SS-backend#712 ·
メンテナーはふだん 1 日以内に返信
-
area: backend bug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
snapotter-hq/SnapOtter#3473 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
gitroomhq/postiz-app#2304 ·
メンテナーはふだん 1 日以内に返信
-
harlan-agent-ready-to-implement routine:ci-review
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
harlan-zw/unlighthouse#454 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信