@engineeros/connector 0.13.2 → 0.13.3

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.
@@ -691,7 +691,7 @@ async function executeAssessment(assignment, assessmentState) {
691
691
  progress = 15;
692
692
  reportProgress("Calculating changed files and affected evidence");
693
693
  }
694
- const result = await executeWorkspaceAssessment(assignment, config, {
694
+ let result = await executeWorkspaceAssessment(assignment, config, {
695
695
  onProcess: (child) => {
696
696
  if (active === assessmentState) {
697
697
  assessmentState.child = child;
@@ -709,17 +709,32 @@ async function executeAssessment(assignment, assessmentState) {
709
709
  },
710
710
  });
711
711
  flushOutput();
712
- const response = await fetch(
713
- assessmentResultUrl(config.server_url, config.connector_id, assessmentId),
714
- {
715
- method: "POST",
716
- headers: {
717
- "Content-Type": "application/json",
718
- Authorization: `Bearer ${config.token}`,
712
+ const submitResult = (payload) =>
713
+ fetch(
714
+ assessmentResultUrl(
715
+ config.server_url,
716
+ config.connector_id,
717
+ assessmentId,
718
+ ),
719
+ {
720
+ method: "POST",
721
+ headers: {
722
+ "Content-Type": "application/json",
723
+ Authorization: `Bearer ${config.token}`,
724
+ },
725
+ body: JSON.stringify(payload),
719
726
  },
720
- body: JSON.stringify(result),
721
- },
722
- );
727
+ );
728
+ let response = await submitResult(result);
729
+ if (response.status === 422 && result.correctAfterRejection) {
730
+ const rejection = await describeRejectedResponse(
731
+ response,
732
+ "the assessment",
733
+ );
734
+ result = await result.correctAfterRejection(rejection);
735
+ flushOutput();
736
+ response = await submitResult(result);
737
+ }
723
738
  if (!response.ok) {
724
739
  throw new Error(
725
740
  await describeRejectedResponse(response, "the assessment"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@engineeros/connector",
3
- "version": "0.13.2",
3
+ "version": "0.13.3",
4
4
  "description": "Connect a local coding agent to EngineerOS, using ACP when supported.",
5
5
  "private": false,
6
6
  "type": "module",
package/src/runner.mjs CHANGED
@@ -419,31 +419,70 @@ export async function executeWorkspaceAssessment(
419
419
  },
420
420
  });
421
421
  completed = recovered.completed;
422
- const report = recovered.report;
423
- const endingRevision = await run(
424
- "git",
425
- ["rev-parse", "HEAD"],
426
- config.workspace,
427
- { allowFailure: true },
428
- );
429
- const endingHead =
430
- endingRevision.code === 0
431
- ? endingRevision.stdout.trim().slice(0, 128)
432
- : null;
433
- if (startingHead !== endingHead) {
434
- throw new Error(
435
- "The Git commit changed during assessment. Refresh the workspace inventory and assess the new commit.",
436
- );
437
- }
438
- return {
439
- stage: assignment.stage,
440
- report_markdown: report,
441
- observed_head_revision: endingHead,
442
- changed_files: changeImpact.changedFiles,
443
- change_impact_markdown: changeImpact.markdown,
444
- model: completed.model ?? config.agent_protocol ?? "coding-agent",
445
- usage: completed.usage ?? null,
446
- };
422
+ const buildResult = async (turn, report) => {
423
+ const endingRevision = await run(
424
+ "git",
425
+ ["rev-parse", "HEAD"],
426
+ config.workspace,
427
+ { allowFailure: true },
428
+ );
429
+ const endingHead =
430
+ endingRevision.code === 0
431
+ ? endingRevision.stdout.trim().slice(0, 128)
432
+ : null;
433
+ if (startingHead !== endingHead) {
434
+ throw new Error(
435
+ "The Git commit changed during assessment. Refresh the workspace inventory and assess the new commit.",
436
+ );
437
+ }
438
+ return {
439
+ stage: assignment.stage,
440
+ report_markdown: report,
441
+ observed_head_revision: endingHead,
442
+ changed_files: changeImpact.changedFiles,
443
+ change_impact_markdown: changeImpact.markdown,
444
+ model: turn.model ?? config.agent_protocol ?? "coding-agent",
445
+ usage: turn.usage ?? null,
446
+ };
447
+ };
448
+ const result = await buildResult(completed, recovered.report);
449
+ if (!recovered.correctionUsed) {
450
+ Object.defineProperty(result, "correctAfterRejection", {
451
+ enumerable: false,
452
+ value: async (validationMessage) => {
453
+ callbacks.onEvent?.({
454
+ type: "assessment.output_correction",
455
+ message: "The Agent is correcting the rejected stage report",
456
+ });
457
+ const correction = launchAgentProcess(
458
+ config.workspace,
459
+ assessmentRejectionCorrectionPrompt(
460
+ validationMessage,
461
+ execution.requiredOutputHeading,
462
+ ),
463
+ execution.sandboxMode,
464
+ config,
465
+ callbacks,
466
+ execution.profile,
467
+ completed.sessionId,
468
+ );
469
+ callbacks.onProcess?.(correction.child);
470
+ const corrected = await correction.completed;
471
+ const correctedReport = normalizeAgentStructuredOutput(
472
+ corrected.finalMessage,
473
+ execution.requiredOutputHeading,
474
+ );
475
+ return buildResult(
476
+ {
477
+ ...corrected,
478
+ usage: mergeTokenUsage(completed.usage, corrected.usage),
479
+ },
480
+ correctedReport,
481
+ );
482
+ },
483
+ });
484
+ }
485
+ return result;
447
486
  }
448
487
 
449
488
  export async function workspaceChangeImpact(
@@ -835,6 +874,7 @@ export async function recoverAssessmentStageOutput({
835
874
  try {
836
875
  return {
837
876
  completed,
877
+ correctionUsed: false,
838
878
  report: normalizeAgentStructuredOutput(
839
879
  completed.finalMessage,
840
880
  requiredOutputHeading,
@@ -854,6 +894,7 @@ export async function recoverAssessmentStageOutput({
854
894
  ...corrected,
855
895
  usage: mergeTokenUsage(completed.usage, corrected.usage),
856
896
  },
897
+ correctionUsed: true,
857
898
  report: normalizeAgentStructuredOutput(
858
899
  corrected.finalMessage,
859
900
  requiredOutputHeading,
@@ -867,6 +908,26 @@ export async function recoverAssessmentStageOutput({
867
908
  }
868
909
  }
869
910
 
911
+ export function assessmentRejectionCorrectionPrompt(
912
+ validationMessage,
913
+ requiredOutputHeading,
914
+ ) {
915
+ return [
916
+ "## Rejected Stage Output Recovery",
917
+ "",
918
+ "EngineerOS rejected the previous stage report because it was incomplete or violated the structured Markdown contract:",
919
+ "",
920
+ String(validationMessage || "The stage report was rejected.").trim(),
921
+ "",
922
+ "Treat the previous stage report as the authoritative draft.",
923
+ "Copy every valid section and block unchanged; repair only the incomplete or invalid entries identified by EngineerOS validation.",
924
+ "Do not re-inspect the repository or replace valid evidence unless the validation error requires it.",
925
+ "Return the entire corrected structured Markdown stage report so EngineerOS can validate it atomically, not only the repaired fragment or missing tail.",
926
+ `The first non-whitespace line must be exactly: ${requiredOutputHeading}`,
927
+ "Do not return progress commentary, an explanation of the correction, or a code fence.",
928
+ ].join("\n");
929
+ }
930
+
870
931
  export function assessmentStageCorrectionPrompt(
871
932
  originalPrompt,
872
933
  requiredOutputHeading,