Skip to content

[codex] clarify KBR ChatGPT import instructions#291

Open
DickHorner wants to merge 2 commits into
mainfrom
codex/kbr-chatgpt-json-instructions
Open

[codex] clarify KBR ChatGPT import instructions#291
DickHorner wants to merge 2 commits into
mainfrom
codex/kbr-chatgpt-json-instructions

Conversation

@DickHorner
Copy link
Copy Markdown
Owner

@DickHorner DickHorner commented May 27, 2026

Summary

This updates the KBR correction-session export instructions generated for ChatGPT so the external correction flow is clearer and directly importable back into ViccoBoard.

Traceability

  • Plan.md §6.20 KBR — Zusammenarbeit/Kompatibilität: Fördermöglichkeiten oder Prüfungsentwürfe mit anderen Nutzern teilen.
  • Plan.md §6.16 KBR — Export & Druck (PDF): export/import-oriented KBR correction artifacts and feedback data.

Changes

  • Explicitly tells ChatGPT that users may upload multiple Leistung files in one message.
  • Keeps each uploaded Leistung isolated while processing and matching candidates.
  • Adds concrete raw JSON structures for Zwischenexport and Ende Korrektur.
  • Provides the real correction-session contract JSON once in a dedicated section and references it from examples with <contract_json_object> to avoid prompt bloat.
  • Adds regression expectations to the export use-case tests.

Impact

Teachers can upload multiple files to ChatGPT in one correction session, and ChatGPT receives a stricter, concrete JSON target for results that are imported back into KBR.

Validation

  • npm test --workspace=@viccoboard/exams -- export-correction-session.use-case.test.ts
  • npm test --workspace=teacher-ui -- kbr-correction-export.test.ts
  • Pre-push quality gate passed: documentation guardrails, workflow guardrails, OpenSSF readiness, package builds, all workspace tests, full production build.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for uploading and processing multiple Leistung files simultaneously, ensuring each file's correction data is kept isolated. It also defines JSON output structures for Zwischenexport and Ende Korrektur containing the contract JSON. The reviewer identified a critical issue where inlining the full contract JSON multiple times within the prompt examples will cause massive token bloat. They suggest using a placeholder <contract_json_object> in the examples and defining a single Contract JSON section at the bottom of the prompt, along with updating the corresponding test assertions.

Comment on lines +188 to 237
JSON structure to output for \`Zwischenexport\`:
{
"contract": {{contractJson}},
"chatRef": "chat-0001",
"importedTaskScores": [
{
"taskId": "task-1",
"points": 0,
"maxPoints": 0,
"scoringUnitId": "task-1.score",
"comment": "Kurzbegruendung mit Bezug zur Leistung",
"confidence": 0.8,
"evidenceIds": ["evidence-1"]
}
],
"evidence": [
{
"id": "evidence-1",
"kind": "quote",
"value": "Kurzer Beleg aus der Leistung"
}
],
"metadata": {
"generalComment": "Kurzer Gesamtkommentar"
}
}

JSON structure to output for \`Ende Korrektur\`:
[
{
"contract": {{contractJson}},
"chatRef": "chat-0001",
"importedTaskScores": []
},
{
"contract": {{contractJson}},
"chatRef": "chat-0002",
"importedTaskScores": []
}
]

Formatting notes for the JSON structures:
- replace example \`chatRef\`, \`taskId\`, \`scoringUnitId\`, points, comments, evidence, and metadata with the resolved values
- use only task IDs and scoring-unit IDs that exist in the loaded contract
- omit optional fields when they are empty or unsupported
- for \`Ende Korrektur\`, output only the array and include one object per resolved Leistung

## Contract

{{contractMarkdown}}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Inlining the entire contract JSON multiple times inside the prompt's example structures (once in Zwischenexport and twice in Ende Korrektur) will cause massive token bloat and potentially exceed the LLM's context window limits for larger exams.

Instead, we can define a single Contract JSON section at the bottom of the prompt to hold the full contract JSON, and use a placeholder like <contract_json_object> in the examples. This reduces the prompt size significantly while keeping the instructions clear.

JSON structure to output for Zwischenexport:
{
  "contract": <contract_json_object>,
  "chatRef": "chat-0001",
  "importedTaskScores": [
    {
      "taskId": "task-1",
      "points": 0,
      "maxPoints": 0,
      "scoringUnitId": "task-1.score",
      "comment": "Kurzbegruendung mit Bezug zur Leistung",
      "confidence": 0.8,
      "evidenceIds": ["evidence-1"]
    }
  ],
  "evidence": [
    {
      "id": "evidence-1",
      "kind": "quote",
      "value": "Kurzer Beleg aus der Leistung"
    }
  ],
  "metadata": {
    "generalComment": "Kurzer Gesamtkommentar"
  }
}

JSON structure to output for Ende Korrektur:
[
  {
    "contract": <contract_json_object>,
    "chatRef": "chat-0001",
    "importedTaskScores": []
  },
  {
    "contract": <contract_json_object>,
    "chatRef": "chat-0002",
    "importedTaskScores": []
  }
]

Formatting notes for the JSON structures:
- replace <contract_json_object> with the full JSON object provided in the Contract JSON section below
- replace example chatRef, taskId, scoringUnitId, points, comments, evidence, and metadata with the resolved values
- use only task IDs and scoring-unit IDs that exist in the loaded contract
- omit optional fields when they are empty or unsupported
- for Ende Korrektur, output only the array and include one object per resolved Leistung

## Contract JSON

    {{contractJson}}

## Contract

{{contractMarkdown}}

Comment on lines +61 to 110
JSON structure to output for `Zwischenexport`:
{
"contract": {{contractJson}},
"chatRef": "chat-0001",
"importedTaskScores": [
{
"taskId": "task-1",
"points": 0,
"maxPoints": 0,
"scoringUnitId": "task-1.score",
"comment": "Kurzbegruendung mit Bezug zur Leistung",
"confidence": 0.8,
"evidenceIds": ["evidence-1"]
}
],
"evidence": [
{
"id": "evidence-1",
"kind": "quote",
"value": "Kurzer Beleg aus der Leistung"
}
],
"metadata": {
"generalComment": "Kurzer Gesamtkommentar"
}
}

JSON structure to output for `Ende Korrektur`:
[
{
"contract": {{contractJson}},
"chatRef": "chat-0001",
"importedTaskScores": []
},
{
"contract": {{contractJson}},
"chatRef": "chat-0002",
"importedTaskScores": []
}
]

Formatting notes for the JSON structures:
- replace example `chatRef`, `taskId`, `scoringUnitId`, points, comments, evidence, and metadata with the resolved values
- use only task IDs and scoring-unit IDs that exist in the loaded contract
- omit optional fields when they are empty or unsupported
- for `Ende Korrektur`, output only the array and include one object per resolved Leistung

## Contract

{{contractMarkdown}}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Inlining the entire contract JSON multiple times inside the prompt's example structures (once in Zwischenexport and twice in Ende Korrektur) will cause massive token bloat and potentially exceed the LLM's context window limits for larger exams.

Instead, we can define a single Contract JSON section at the bottom of the prompt to hold the full contract JSON, and use a placeholder like <contract_json_object> in the examples. This reduces the prompt size significantly while keeping the instructions clear.

JSON structure to output for Zwischenexport:
{
  "contract": <contract_json_object>,
  "chatRef": "chat-0001",
  "importedTaskScores": [
    {
      "taskId": "task-1",
      "points": 0,
      "maxPoints": 0,
      "scoringUnitId": "task-1.score",
      "comment": "Kurzbegruendung mit Bezug zur Leistung",
      "confidence": 0.8,
      "evidenceIds": ["evidence-1"]
    }
  ],
  "evidence": [
    {
      "id": "evidence-1",
      "kind": "quote",
      "value": "Kurzer Beleg aus der Leistung"
    }
  ],
  "metadata": {
    "generalComment": "Kurzer Gesamtkommentar"
  }
}

JSON structure to output for Ende Korrektur:
[
  {
    "contract": <contract_json_object>,
    "chatRef": "chat-0001",
    "importedTaskScores": []
  },
  {
    "contract": <contract_json_object>,
    "chatRef": "chat-0002",
    "importedTaskScores": []
  }
]

Formatting notes for the JSON structures:
- replace <contract_json_object> with the full JSON object provided in the Contract JSON section below
- replace example chatRef, taskId, scoringUnitId, points, comments, evidence, and metadata with the resolved values
- use only task IDs and scoring-unit IDs that exist in the loaded contract
- omit optional fields when they are empty or unsupported
- for Ende Korrektur, output only the array and include one object per resolved Leistung

## Contract JSON

    {{contractJson}}

## Contract

{{contractMarkdown}}

Comment on lines +224 to +231
expect(artifact.promptFile.content).toContain('JSON structure to output for `Zwischenexport`');
expect(artifact.promptFile.content).toContain('JSON structure to output for `Ende Korrektur`');
expect(artifact.promptFile.content).toContain('"contract": {');
expect(artifact.promptFile.content).toContain('"id": "contract-session-session-2026-04-17"');
expect(artifact.promptFile.content).toContain('"chatRef": "chat-0001"');
expect(artifact.promptFile.content).toContain('"importedTaskScores": [');
expect(artifact.promptFile.content).toContain('"evidence": [');
expect(artifact.promptFile.content).toContain('"metadata": {');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update the test assertions to match the optimized prompt structure that uses a single Contract JSON section and placeholders in the example structures.

Suggested change
expect(artifact.promptFile.content).toContain('JSON structure to output for `Zwischenexport`');
expect(artifact.promptFile.content).toContain('JSON structure to output for `Ende Korrektur`');
expect(artifact.promptFile.content).toContain('"contract": {');
expect(artifact.promptFile.content).toContain('"id": "contract-session-session-2026-04-17"');
expect(artifact.promptFile.content).toContain('"chatRef": "chat-0001"');
expect(artifact.promptFile.content).toContain('"importedTaskScores": [');
expect(artifact.promptFile.content).toContain('"evidence": [');
expect(artifact.promptFile.content).toContain('"metadata": {');
expect(artifact.promptFile.content).toContain('JSON structure to output for Zwischenexport');
expect(artifact.promptFile.content).toContain('JSON structure to output for Ende Korrektur');
expect(artifact.promptFile.content).toContain('"contract": <contract_json_object>');
expect(artifact.promptFile.content).toContain('"id": "contract-session-session-2026-04-17"');
expect(artifact.promptFile.content).toContain('"chatRef": "chat-0001"');
expect(artifact.promptFile.content).toContain('"importedTaskScores": [');
expect(artifact.promptFile.content).toContain('"evidence": [');
expect(artifact.promptFile.content).toContain('"metadata": {');

@DickHorner DickHorner marked this pull request as ready for review May 27, 2026 09:16
Copilot AI review requested due to automatic review settings May 27, 2026 09:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens the “KBR correction-session export” instructions that are generated for ChatGPT so teachers can upload multiple Leistung files at once, and ChatGPT can return results in a stricter, directly importable JSON shape.

Changes:

  • Extend contract + prompt instructions to support multiple Leistung uploads per message while keeping each Leistung’s correction data isolated.
  • Embed the concrete correction-session contract JSON into the prompt via a new {{contractJson}} placeholder and pass it from the export use-case.
  • Add regression assertions to ensure the prompt/contract text includes the new multi-upload and JSON-structure guidance.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
modules/exams/src/use-cases/export-correction-session.use-case.ts Passes a serialized contractJson into prompt template rendering so prompts can include the real contract object.
modules/exams/src/rule-packs/default-pack.ts Updates the embedded default contract/prompt templates with multi-upload guidance and explicit JSON structures for Zwischenexport / Ende Korrektur.
modules/exams/rule-packs/default/prompt.template.md Mirrors the default prompt template updates in the file-based rule pack template.
modules/exams/rule-packs/default/contract.template.md Mirrors the default contract template updates in the file-based rule pack template.
modules/exams/tests/export-correction-session.use-case.test.ts Adds assertions to lock in the updated prompt/contract content.

"points": 0,
"maxPoints": 0,
"scoringUnitId": "task-1.score",
"comment": "Kurzbegruendung mit Bezug zur Leistung",
"points": 0,
"maxPoints": 0,
"scoringUnitId": "task-1.score",
"comment": "Kurzbegruendung mit Bezug zur Leistung",
Comment on lines +218 to +223
expect(artifact.promptFile.content).toContain(
'Bitte laden Sie die erste Leistung oder mehrere Leistungen gleichzeitig hoch.'
);
expect(artifact.promptFile.content).toContain(
'the user may upload multiple Leistung files in the same message'
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants