Skip to content

feat: add agent_doc_sync JSRunner job#6

Closed
agzyamov wants to merge 288 commits into
IstiN:mainfrom
agzyamov:feat/agent-doc-sync
Closed

feat: add agent_doc_sync JSRunner job#6
agzyamov wants to merge 288 commits into
IstiN:mainfrom
agzyamov:feat/agent-doc-sync

Conversation

@agzyamov
Copy link
Copy Markdown

Summary

Adds a JSRunner job that auto-generates a Confluence agent reference page from sm.json.

Files

agents/js/agentDocSync.js

  • Reads sm.json to discover all registered agents (via params.jobParams.rules[])
  • Deduplicates configFile references; skips localExecution: true rules
  • Reads each config + its cliPrompt file to extract action description
  • Builds a full HTML page with an Agent Name / Trigger / Action / Output table
  • Publishes to Confluence (updates existing page or creates new one)
  • Fails closed if 0 agents discovered

agents/agent_doc_sync.json

  • JSRunner config template
  • customParams: smJsonPath, confluenceSpace, confluencePageTitle, confluencePageId, confluenceParentId

Usage

./dmtools.sh run agents/agent_doc_sync.json

Fill in the customParams before running (space, title, optional page/parent IDs).

Context

This PR is the DMtools side of epam/dm.ai#2, following maintainer feedback that this kind of automation belongs in a JSRunner job rather than AI-narrated CLI steps.

ai-teammate and others added 30 commits March 1, 2026 09:51
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
JSRunner passes params to action() as {jobParams, ticket, response}.
Custom config must be nested under jobParams, not at the top level.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New MCP tool signature: (owner, repo, workflowFile, inputsJson, ref)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- sm.json: new rule for 'In Review - Passed/Failed' Test Cases → pr_test_automation_review
- smAgent.js: pass skipIfLabel as removeLabel in encoded_config
- postTestReviewComments.js: remove params.removeLabel at end (SM idempotency cleanup)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add removeLabel to pr_test_automation_review.json params directly
  so postTestReviewComments.js receives it as params.removeLabel
- Simplify buildEncodedConfig in smAgent.js (remove unused removeLabel
  passing via encoded_config which was not reaching postJSAction)

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
- Move removeLabel into customParams in pr_test_automation_review.json
- Access it via params.jobParams.customParams.removeLabel in
  postTestReviewComments.js (correct Teammate params structure)

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
- preJSAction: moveToReadyForTesting.js (transition before test generation)
- postJSAction: moveToInTesting.js (transition after test cases generated)
- Add IN_TESTING status to config.js

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
- sm.json: new rule for 'In Rework' Test Cases → pr_test_automation_rework
- pr_test_automation_rework.json: customParams.removeLabel for idempotency
- postTestReworkResults.js: remove SM label via params.jobParams.customParams

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
…n_description→Ready For Development

- jiraHelpers.assignForReview: add optional targetStatus param (default IN_REVIEW)
- assignForReview.js: pass STATUSES.SOLUTION_ARCHITECTURE
- enhanceSolutionDesignDescriptionAndAssess.js: pass STATUSES.READY_FOR_DEVELOPMENT

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
- sm.json: new rule for 'In Review' Stories → pr_review.json
- pr_review.json: customParams.removeLabel for idempotency
- postPRReviewComments.js: remove SM label via params.jobParams.customParams

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
- postTestReviewComments: track mergeSucceeded; if approved but merge
  failed → post conflict comment + move to In Rework
- postPRReviewComments: if approved but merged=false → move to In Rework;
  add conflict panel to Jira comment

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
…ys/skippedKeys format

GraalJS [].concat(undefined) produces [null], so all early-return paths must
return { processedKeys: [], skippedKeys: [] } instead of the old { processed: 0, skipped: 0 }.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…arams.customParams

In Teammate postJSAction, the JSON config's params block is mapped directly onto
the JS params object (verified by params.metadata being accessible directly).
So customParams is at params.customParams, not params.jobParams.customParams.
This fixes SM label removal (sm_test_review_triggered, sm_story_review_triggered,
sm_test_rework_triggered) not working after review/rework agents completed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…runs

JSRunner agent that queries failed GitHub workflow runs and creates a Bug ticket
per unique failure. Uses ci-run-{runId} label for idempotency (skips if label exists).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…rkflows)

When workflowId is omitted, passes null to github_list_workflow_runs which should
use the /actions/runs endpoint instead of /actions/workflows/{id}/runs.
NOTE: if dmtools returns 404 without workflowId, report at https://github.com/IstiN/dmtools/issues

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…_ticket

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…stAutomationResults

jira_create_ticket does not exist in dmtools MCP tools.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…customParams)

params.metadata is a special shortcut field in dmtools, but customParams is
not — it's only accessible via params.jobParams.customParams. This caused
SM idempotency labels (sm_test_review_triggered, sm_test_rework_triggered,
sm_story_review_triggered) to not be removed after post-actions completed.

Affected: postPRReviewComments.js, postTestReviewComments.js, postTestReworkResults.js
- Add pr_discussions_raw.json to context list in pr_review_instructions.md
  so the regular PR review agent knows to read thread IDs
- Add pr_discussions_raw.json to context list in pr_review_prompt.md
  with explicit instruction to populate resolvedThreadIds
- Add Thread resolution rule to pr_test_review_instructions.md
  (was missing — only the JSON output format was referenced)

Without these changes both reviewers would leave resolvedThreadIds empty
on repeated reviews, causing threads to pile up across rework cycles.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- sm.json: add rule to trigger pr_rework.json for Stories in 'In Rework'
  with sm_story_rework_triggered idempotency label
- pr_rework.json: add customParams.removeLabel = sm_story_rework_triggered
- pushReworkChanges.js: remove SM idempotency label after rework completes
  so the ticket can be re-triggered in future cycles

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New agent config and flow:
- bug_development.json: Teammate agent for bug fixing
  - preCliJSAction: preCliDevelopmentSetup (checkout ai/BUG-XX branch, In Development)
  - postJSAction: developBugAndCreatePR
  - customParams.removeLabel: sm_bug_development_triggered

New post-action developBugAndCreatePR.js — three paths:
  1. outputs/blocked.json exists    → move to Blocked, post blocker reason
  2. outputs/already_fixed.json exists → move to Ready For Testing, post commit ref
  3. Neither                        → normal PR creation via developTicketAndCreatePR

New instructions/development/bug_implementation_instructions.md:
  - Mandatory RCA before any code change (writes outputs/rca.md)
  - Check if already fixed in recent commits (write already_fixed.json)
  - Check if blocked / needs human (write blocked.json)
  - Write failing unit test to reproduce bug before fixing
  - Targeted minimal fix, verify with full test suite

New prompts/bug_development_prompt.md:
  - Structured 7-step workflow: RCA → already-fixed check → blocked check
    → reproduce test → fix → verify → outputs/response.md

bug_merged.json + notifyBugMerged.js:
  - Triggered by SM when Bug reaches Merged status
  - Posts "ready for testing" comment, removes SM label
  - SM targetStatus handles Ready For Testing transition

sm.json updates:
  - Add rule: Ready For Development Bugs → bug_development.json
  - Add rule: Merged Bugs → bug_merged.json (→ Ready For Testing)
  - Expand In Review rule: Stories → Stories & Bugs (same pr_review.json)
  - Expand In Rework rule: Stories → Stories & Bugs (same pr_rework.json)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ai-teammate and others added 26 commits March 28, 2026 08:53
Initial clone is now blobless (--filter=blob:none) so the full commit
graph is already present. Branch fetches are near-instant because git
only needs to download new blobs on demand, not negotiate history.

Reverts the per-fetch depth/filter flags added in 02ec9b9 — they are
no longer needed and --depth=1 would actually break rebase/merge-base.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Blobless clones (--filter=blob:none) are not shallow so calling
git fetch --unshallow fails with exit 128 and pollutes logs with
[ERROR] even though the catch handles it.

Replace blind unshallow with a shallow check first:
  git rev-parse --is-shallow-repository → 'true' only for depth clones

Applied in both getPRDiff and detectMergeConflicts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…n diff)

GitHub's inline comment API returns 422 when the target line is not
inside a diff hunk. This happens when the reviewer comments on existing
code that wasn't changed in this PR iteration.

Instead of silently dropping those comments, fall back to a regular
PR comment prefixed with the file:line reference so no feedback is lost.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mment

Threads from general PR review comments (REQUEST CHANGES reviews, summary
comments) have rootCommentId/threadId = null. String(null) = 'null' was
sent to github_reply_to_pr_thread, causing silent failures.

Fix: if inReplyToId is null/undefined, post as a top-level PR comment
instead of attempting an invalid thread reply.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add project_key resolution in triggerWorkflow:
- rule.projectKey takes priority (explicit)
- falls back to basename of configPath (e.g. configs/mapc.js → 'mapc')
- passes as project_key in github_trigger_workflow inputs
- logs [project_key=X] when set

Also documents new projectKey rule field in header JSDoc.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
postPRReviewComments.js:
- adds deriveProjectKey, buildAutoStartEncodedConfig, hasPrApprovedLabel helpers
- after moving ticket to In Rework: if customParams.autoStartRework=true
  and autoStartReworkConfigFile is set, triggers ai-teammate.yml with
  the rework config; skips if ticket has pr_approved label

pushReworkChanges.js:
- adds same helpers + imports LABELS from config.js
- after moving ticket to In Review: if customParams.autoStartReview=true
  and autoStartReviewConfigFile is set, triggers ai-teammate.yml with
  the review config; skips if ticket has pr_approved label

Both use config.repository.owner/repo as the AI repo to trigger on.
project_key is derived from customParams.projectKey or configPath basename.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After ticket is moved to In Review:
- if customParams.autoStartReview=true and autoStartReviewConfigFile is set,
  triggers ai-teammate.yml with the review config
- skips if ticket already has pr_approved label
- project_key derived from customParams.projectKey or configPath basename

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eview

customParams lives at params.jobParams.customParams in postJSAction context,
not at params.customParams. Was reading wrong path → autoStartReview never fired.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
configLoader overrides config.repository with targetRepository (project repo),
so auto-start was triggering on PostNL-commercial-mobileApp instead of
PostNL-commercial-ai where ai-teammate.yml lives.

All three auto-start scripts now prefer customParams.aiRepository when set,
falling back to config.repository only when absent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
New module fetchParentContextToInput.js:
- Finds ticket's parent, searches siblings with [BA]/[SA]/[VD] prefix
- Writes parent_context_ba.md, parent_context_sa.md, parent_context_vd.md
- BA = Business Analysis (ACs, business rules, user flows)
- SA = Solution Architecture (technical design, data model, API contracts)
- VD = Visual Design (UI mockups, component specs)
- Fully non-fatal: missing parent or no children → silent skip

Integrated into all three MAPC pre-CLI setup scripts as last step:
- preCliDevelopmentSetup.js (story_development)
- preparePRForReview.js (pr_review)
- preCliReworkSetup.js (pr_rework)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…omParams

Module is now a no-op when customParams.parentContextFetch is absent.
When present, all behaviour is driven by config:
- jql: JQL with {parentKey} placeholder (default: BA/SA/VD filter)
- fields: Jira fields to fetch (default: key, summary, description, status)
  custom field IDs can be added; missing fields are re-fetched via jira_get_ticket
- contexts: array of {prefix, file, label, description} for matching and output

Defaults reproduce the original BA/SA/VD behaviour.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Input

- preCliSolutionSetup.js: chains fetchQuestionsToInput + fetchParentContextToInput
  for story_solution agent pre-CLI step
- test_fetchParentContextToInput.js: 20 unit tests covering no-op guard, JQL
  placeholder replacement, context matching (case-insensitive), file content,
  re-fetch fallback for missing fields, and error resilience
- run_fetchParentContextToInput.json: standalone runner for new tests
- run_all.json: include new test file in full test suite

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add explicit steps 5-7 for parent_context_ba/sa/vd.md so the development
agent reads them in priority order before implementing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- pr_review_prompt.md: add parent_context_ba/sa/vd.md to context file list
  so reviewer checks implementation against BA ACs, SA design, VD specs
- pr_rework_prompt.md: add parent_context_ba/sa/vd.md as steps 4-6 in reading
  order so rework agent has full parent context before applying fixes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- renderFieldsMarkdown now accepts optional fieldLabels map for display names
- fieldLabels resolved from cfg.fieldLabels (per-agent config)
- Fixes rendering when JIRA_EXTRA_FIELDS is not set in CI environment

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- DEFAULT_FIELDS now includes 'comment'
- renderCommentsMarkdown: renders comments as quoted markdown blocks
  with author, date, and body
- renderFieldsMarkdown: special-cases 'comment' field via renderCommentsMarkdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Root cause of 422 errors: AI was using diff-position (line number within
pr_diff.txt) instead of actual file line number from the @@ hunk header.

- Explain exactly how to calculate line number from @@ header
- Add concrete example: @@ -1344,6 +1344,9 @@ + 3 context lines = line 1347
- Recommend general comment fallback when line number is uncertain

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…uestions)

- New optional cfg.childQuestions: { jql, answerField } in parentContextFetch
- After writing each context file, JQL fetches [Q] children of that ticket
  ({contextTicketKey} replaced with actual key)
- Questions appended as '## Questions & Answers' section with Q/Answer format
- Non-fatal: any Q-fetch failure is warned and skipped

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CLI agents write outputs to outputs/{ticketKey}/response.md
instead of root outputs/response.md.

Add readOutput() helper: tries root path first, then ticket subdir fallback.
This fixes bug_rca (and any agent using writeSolutionAndDiagrams.js) silently
skipping Jira field updates when the file is in a subdirectory.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Agents were writing to outputs/{ticketKey}/response.md (subdir)
instead of outputs/response.md (root), causing silent Jira submission failure.

Add prominent warning block explaining exact required paths and
that subdirectories will cause the RCA to be silently discarded.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
9 recurring mistake categories extracted from closed review threads
in PostNL-commercial-mobileApp PRs #918-934 (reviewers: dmytro-medvediuk-epam,
pavel-kavalchuk-epam):

1. accessibilityRole enum vs raw strings (src/utils/helpers/accessibilityRoles.ts)
2. Scope discipline — only AC-required changes
3. Reuse existing components/utils/styles (flex1, getCountryFlagUrl, ModalDropdownPicker)
4. Project-wide accessibility fixes, not just changed files
5. Don't hide children of Pressable (accessible by default)
6. Never pass undefined to screen reader props — use empty string
7. Extract accessibility label logic to helper functions
8. Branch must be up-to-date with develop before PR
9. All styles in .styles.ts files — no inline createStyles in component files

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…n main repo

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tructions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- agents/instructions/common/investigate_before_answer.md: general instruction
  for agents to investigate current code/API before answering questions, to
  avoid guessing about what is already implemented
- agents/instructions/product/po_domain_knowledge.md: describes dm.ai product
  context — CLI orchestration toolkit, 3-layer model (connectors, preCLI→AI→
  postCLI, ready-made Jobs), key architecture facts, and how AI agents use
  DMtools

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Added sections for API surface (REST routes, MCP/@mcptool, OpenAPI specs)
- Added CLI commands check (dmtools --help, @command annotations)
- Added UI/UX check (React/Vue/Angular components, routes, Figma stories)
- Removed po_domain_knowledge.md — moved to dm.ai project repo (.dmtools/instructions/)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a JSRunner job that auto-generates a Confluence agent reference
page from sm.json:
- agents/js/agentDocSync.js  — reads sm.json rules, deduplicates config
  refs, reads each config + prompt file, builds HTML table, publishes
  to Confluence (update or create)
- agents/agent_doc_sync.json — JSRunner config template with customParams
  for confluenceSpace, confluencePageTitle, etc.

Run with: ./dmtools.sh run agents/agent_doc_sync.json

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 930313b178

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread js/agentDocSync.js
// 4. Fetch current page and update or create
var currentPage = fetchPage(pageId, pageTitle, space);
if (currentPage) {
var existingId = pageId || currentPage.id;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use fetched page ID after title fallback

If confluencePageId is configured but stale/invalid, fetchPage() correctly falls back to confluence_find_content_by_title_and_space(...) and can return a valid page object, but this line still prefers the original pageId when calling confluence_update_page_with_history. In that case the update is attempted against the wrong ID and the sync fails even though the page was successfully found by title.

Useful? React with 👍 / 👎.

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.

3 participants