Skip to content

fix(update_project): parse string-typed fields instead of iterating over characters#45825

Merged
pelikhan merged 5 commits into
mainfrom
copilot/update-project-bogus-fields
Jul 16, 2026
Merged

fix(update_project): parse string-typed fields instead of iterating over characters#45825
pelikhan merged 5 commits into
mainfrom
copilot/update-project-bogus-fields

Conversation

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

When an agent double-encodes fields as a JSON string (e.g. "fields": "{\"Lifecycle\":\"Sandbox\"}") instead of a plain object, Object.entries() iterates over character indices ["0","{"], ["1","\""], …, silently creating one SINGLE_SELECT project field per character. The board gets polluted with numeric junk fields that require manual GraphQL cleanup.

Root cause

Both call sites in updateProject passed output.fields directly to applyFieldUpdates after only a truthiness + Object.keys().length check — no type guard.

Changes

  • resolveFieldsObject() helper — added before applyFieldUpdates:

    • If fields is a string → attempt JSON.parse; warn and return null on failure
    • Explicitly handles null after parse (e.g. JSON 'null')
    • Rejects arrays and other non-object types with a core.warning
    • Returns a plain object otherwise
  • Both call sites in updateProject (draft issue path and regular issue path) now route through resolveFieldsObject before invoking applyFieldUpdates

// Before — guard passes for any truthy value including a string
if (output.fields && Object.keys(output.fields).length > 0) {
  await applyFieldUpdates(github, projectId, itemId, output.fields);
}

// After — string is parsed; non-objects are warned and skipped
const resolvedFields = resolveFieldsObject(output.fields);
if (resolvedFields && Object.keys(resolvedFields).length > 0) {
  await applyFieldUpdates(github, projectId, itemId, resolvedFields);
}
  • Tests: three new cases — valid JSON-encoded string (parsed and applied correctly), invalid JSON string (warned + skipped), and array (warned + skipped)

When output.fields is a JSON-encoded string (agent double-encoding),
the old code iterated over character indices and created bogus
SINGLE_SELECT project fields named 0, 1, 2, …

Add resolveFieldsObject() which:
- Parses a string value via JSON.parse, warns and returns null on failure
- Explicitly handles null after parsing (e.g. JSON 'null')
- Rejects arrays and other non-object types with a warning
Both call sites in updateProject now use this helper.

Fixes #44845

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix bogus per-character project fields in update_project fix(update_project): parse string-typed fields instead of iterating over characters Jul 15, 2026
Copilot AI requested a review from pelikhan July 15, 2026 22:02
@pelikhan pelikhan marked this pull request as ready for review July 15, 2026 22:07
Copilot AI review requested due to automatic review settings July 15, 2026 22:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 hardens update_project against agent outputs that mistakenly double-encode fields as a JSON string, preventing Object.entries() from iterating character indices and creating junk project fields.

Changes:

  • Added resolveFieldsObject() to coerce fields into a plain object (including parsing valid JSON strings) and warn/skip on invalid types.
  • Routed both applyFieldUpdates call sites through resolveFieldsObject() to avoid accidental per-character iteration.
  • Added tests covering JSON-string fields, invalid JSON strings, and array inputs.
Show a summary per file
File Description
actions/setup/js/update_project.cjs Adds resolveFieldsObject() and uses it at both field-update call sites to prevent accidental junk field creation.
actions/setup/js/update_project.test.cjs Adds regression tests for double-encoded fields and other invalid fields shapes.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Low

Comment thread actions/setup/js/update_project.cjs Outdated
core.warning("update_project: `fields` must be a JSON object; skipping field updates");
return null;
}
return /** @type {Record<string, unknown>} */ fields;
expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining('Failed to create field "NonExistentField"'));
});

it("warns and skips field updates when fields is a JSON-encoded string (double-encoded)", async () => {
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, investigate the failing JavaScript checks (js-typecheck and impacted-js-tests), address any outstanding review feedback, and push fixes so the PR is ready for maintainer review.

Generated by 👨‍🍳 PR Sous Chef · 8.83 AIC · ⌖ 6 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, investigate the failing JavaScript checks (js-typecheck and impacted-js-tests), address any outstanding review feedback, and push fixes so the PR is re...

Implemented fixes in 742360c. Investigated failing js-typecheck/impacted-js-tests logs, applied the type-check-safe resolveFieldsObject cast adjustment in /home/runner/work/gh-aw/gh-aw/actions/setup/js/update_project.cjs, and renamed the misleading JSON-string test in /home/runner/work/gh-aw/gh-aw/actions/setup/js/update_project.test.cjs. Local validation passed: npm run typecheck, targeted vitest update_project.test.cjs, plus make fmt, make lint, make test-unit, and make test.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category bug
Risk low
Score 60 / 100
Action fast_track
Batch js-runtime-fixes (with #45827, #45826)

Score breakdown: Impact 28 + Urgency 18 + Quality 14

Fixes update_project silently iterating over JSON string characters when fields is double-encoded. Adds JSON.parse guard + tests (2 files). CI unknown — awaiting checks. Part of JS runtime fixes batch.

Run §29462479491

Generated by 🔧 PR Triage Agent · 189.6 AIC · ⌖ 5.52 AIC · ⊞ 5.6K ·

@pelikhan

Copy link
Copy Markdown
Collaborator

Copilot AI and others added 2 commits July 16, 2026 04:54
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix https://github.com/github/gh-aw/actions/runs/29456102257/job/87532870026#step:7:1

Fixed in b2851bb. I investigated the failing step and updated resolveFieldsObject in actions/setup/js/update_project.cjs to return a normalized object shape that satisfies js-typecheck while preserving the field parsing/validation behavior. Verified locally with npm run typecheck and impacted JS tests (make test-impacted-js BASE_REF=origin/main).

@pelikhan pelikhan merged commit cc4ca71 into main Jul 16, 2026
14 checks passed
@pelikhan pelikhan deleted the copilot/update-project-bogus-fields branch July 16, 2026 05:01
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.82.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

update_project: a string-typed fields value creates bogus per-character project fields (0, 1, 2, …)

4 participants