Friction: wire remediate stage — parse friction first, strip-before-findings, artifact write #228
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The remediate stage's final message is both the annotated findings document (the exit condition that
parseRemainingFindings/validateFindingsconsume) and, after this issue, a friction report. The two must never collide: a friction entry shaped like- [ ] …would be misparsed as an unresolved finding. The safe design (perdocs/adr/016-friction-logging.md) is:## Frictionsection is appended after the annotated findings;Depends on the foundation issue (parser, strip helper, artifact service, renderer).
Contracts (from the foundation issue)
## Frictionsection appended last in the final message — i.e. after the last findings severity section (## Low).- category: <enum>+ indenteddescription,impact,resolution, optionalref..pi-loop/runs/<run-id>/friction.json(provenance stampedstage: "remediate") + renderedFRICTION.md.Changes
src/remediate/helpers/buildRemediateWrapper.ts— add the friction contract to the wrapper (keep the existing annotated-findings exit condition text intact):## Frictionsection."src/skills/remediateSkill.ts— add a short "Log friction" reminder (same wording style as implement).src/remediate/services/runRemediateStage.ts— wire capture + parse + strip + artifacts:const { text: annotatedFindings } = await runStageFn({ ... });.const frictionResult = parseFriction(annotatedFindings);(log warnings).const findingsOnly = stripFrictionSection(annotatedFindings);.const remainingFindings = parseRemainingFindings(findingsOnly);andconst { wellFormed } = validateFindings(findingsOnly);— not on the raw text.writeFriction(runDir, artifact)(stampedstage: 'remediate',runId,model,recordedAt) +writeFrictionMd(...).entries: [],wellFormed: true) + renderedFRICTION.mdstating "No friction recorded.", so per-run friction files always exist.friction: { entries: FrictionEntry[]; wellFormed: boolean }toRunRemediateStageResult.src/remediate/types/remediate.ts— extendRunRemediateStageResultwith thefrictionfield (import types fromsrc/friction/types).Acceptance criteria
remainingFindingsandvalidateFindings.wellFormedare computed on the stripped text and are identical to what they would be for the findings-only message.- [ ] …syntax inside the friction section is never counted inremainingFindings(regression-tested).wellFormed: false+ warnings; findings parsing unaffected; stage still succeeds.npm run lintandnpm testgreen.Unit tests (add alongside the seams)
runRemediateStage.test.ts— mockrunStageFn:remainingFindingscomputed on stripped text, artifacts written, result carriesfriction;wellFormed: true;- [ ] foo→remainingFindingsunchanged (empty), friction entry ignored;wellFormed: false, stage succeeds;buildRemediateWrapper.test.ts— friction contract present; annotated-findings exit condition still present.parseRemainingFindings+validateFindingson stripped vs raw text.Dependencies
runRemediateStagebeyondrunStageFn(already injectable).pi-loop opened and merged a pull request for this issue: #243