80 lines
4.6 KiB
Markdown
80 lines
4.6 KiB
Markdown
# EPOD: syntax messages for a failed write
|
|
|
|
Status: proposal (2026-10-05). Kral decides later if it goes into the EPOD server.
|
|
The harness proxy does this today (`harness/proxy.py`, `harness/localcheck.py`). The proxy is not changed by this note.
|
|
|
|
## Problem
|
|
|
|
`sap_push_source` fails with only this result when SAP does not accept the source:
|
|
|
|
```json
|
|
{"success":false,"error":"[WRITE] An error occured during the save operation. The changes were not stored."}
|
|
```
|
|
|
|
Example cause: `METHODS run IMPORTING iv TYPE c LENGTH 4.` (a generic type with LENGTH in a method signature).
|
|
The model cannot see the cause, so it cannot repair. In the pilot this was 7 failures in 3 tasks.
|
|
|
|
`sap_syntax_check` does not help: it reads the stored version (inactive or active), not the rejected source.
|
|
Tested 2026-10-05: after the failed write it returned `{"version":"inactive","errorCount":0,"findings":[]}`
|
|
(it checked the empty stub that `sap_create_object` made).
|
|
|
|
## What the proxy does now
|
|
|
|
1. A result of `sap_push_source` is a bare save failure when the JSON has `success:false`, the error text contains
|
|
"during the save operation", and `activation.messages` is empty (`localcheck.is_bare_save_failure`).
|
|
2. The proxy takes the source from the call arguments and runs the abaplint parser on it
|
|
(`localcheck.parser_messages`): one temporary file named by object type (`<name>.clas.abap`,
|
|
`<name>.clas.testclasses.abap` for `includeType` testclasses, `.intf.abap`, `.prog.abap`,
|
|
`<group>.fugr.<name>.abap`, `.ddls.asddls`), rule `parser_error` only, syntax version from the task release target
|
|
(default v758). TABL, FUGR and other types without a parser: no hint.
|
|
3. It adds a `syntaxCheck` field to the same JSON object (`localcheck.augment`). The original result stays in
|
|
the trajectory log as `raw_result`:
|
|
|
|
```json
|
|
{"success":false,
|
|
"error":"[WRITE] An error occured during the save operation. The changes were not stored.",
|
|
"syntaxCheck":{"source":"local abaplint (the rejected source, not stored in SAP)",
|
|
"messages":[{"line":3,"severity":"E",
|
|
"message":"Statement does not exist in the configured ABAP version(or a parser error), \"METHODS\""}]}}
|
|
```
|
|
|
|
Limits: abaplint reports the line and the statement that it cannot parse, not the SAP reason ("TYPE c LENGTH in a
|
|
signature is not allowed"). It does not know SAP rules that are not syntax (reserved words in DDL, name length, CDS
|
|
annotations). It finds only parser errors, no type or semantic errors.
|
|
|
|
## Same logic in the EPOD server
|
|
|
|
The server has the source and the lock, so it can do better than abaplint: check the rejected source with the
|
|
SAP syntax check, without saving it.
|
|
|
|
1. In `sap_push_source` (and `sap_push_element`), when the save step fails, run the ADT syntax check on the
|
|
source in the request. Eclipse checks unsaved editor content through the ADT check run (not tested by the harness yet): POST
|
|
`/sap/bc/adt/checkruns?reporters=abapCheckRun` with a `chkrun:checkObject` that has the object URI and an
|
|
`artifacts` entry with the new source (base64) as `chkrun:content` .
|
|
The answer has `chkrun:checkMessage` entries with `chkrun:uri` (line and column), `chkrun:type` (E, W), and
|
|
`chkrun:shortText`.
|
|
2. Add the messages to the failed result in the same field shape as the proxy, so a client does not care who made
|
|
them:
|
|
|
|
```json
|
|
{"success":false,
|
|
"error":"[WRITE] An error occured during the save operation. The changes were not stored.",
|
|
"syntaxCheck":{"source":"sap_checkrun (the rejected source, not stored)",
|
|
"messages":[{"line":3,"column":41,"severity":"E","message":"..."}]}}
|
|
```
|
|
|
|
3. Keep the order: save, then (only when the save fails) check. A good write costs no extra call.
|
|
4. Extend `sap_syntax_check` with an optional `source` argument (check this source, do not store it). The model
|
|
can then check before it writes. This is useful by itself, also when no write failed.
|
|
5. If the check run itself fails (lock, timeout), return the original result without `syntaxCheck`. The field is optional.
|
|
|
|
Open points for EPOD: whether the checkrun accepts an unsaved source for every object type (classes with include
|
|
types, function modules in a group, CDS); the harness would test this on A4H first (null/oracle runs only).
|
|
|
|
## What stays in the harness either way
|
|
|
|
- A server-side change replaces `localcheck.py` for the types that the server supports. The proxy code
|
|
checks `syntaxCheck` first: if the field is there, it adds nothing.
|
|
- Training data from before the change has the abaplint messages, data after it has the SAP messages. Keep the
|
|
`syntaxCheck.source` text so the two kinds can be told apart (the field is in every record).
|