gitlink-cli/docs/workflow-agent-design.md

15 KiB

GitLink CLI Workflow Agent Design

Background

gitlink-cli already provides low-level and shortcut operations for GitLink repositories, issues, pull requests, releases, CI, organizations, search, and users. The repository also includes skills/gitlink-workflow/SKILL.md, which describes AI workflow patterns such as Issue triage, PR review, and Release Notes generation.

The current Go command tree did not include a workflow command group before this work. The competition PR turns the documented workflow concept into concrete, deterministic CLI commands that can be used by human maintainers and AI Agents without calling an external LLM.

Goals

First PR:

  • Add gitlink-cli workflow +triage.
  • Add gitlink-cli workflow +health.
  • Keep write behavior dry-run by default.
  • Produce stable JSON for Agents.
  • Produce concise table output for terminal users.
  • Produce markdown output for reports, PR comments, Issue comments, and competition materials.
  • Support --lang en and --lang zh-CN with a lightweight message helper.

Additional workflow commands:

  • workflow +pr-summary: done
  • workflow +repo-report: done
  • workflow +release-notes: done
  • workflow +stale: planned

Current implementation status:

  • Rule engine: done
  • Local command layer: done
  • API fetch layer: done
  • Boundary tests: expanded for empty responses, field normalization, unknown tolerance, and read-only error handling
  • PR summary command: done with local JSON input, read-only fetch, rules, renderers, and tests
  • Repo report command: done with local JSON input, partial read-only fetch aggregation, scoring, renderers, and tests
  • Release notes command: done with local JSON input, read-only compare fetch, deterministic section classification, renderers, and tests

Current Repository Findings

Command registration:

  • cmd/root.go registers global flags and calls shortcuts.RegisterAll(rootCmd).
  • shortcuts/register.go maps command groups to shortcut slices.
  • Each group exposes Shortcuts() []*common.Shortcut.
  • common.MountShortcut maps a Shortcut into a Cobra command named +<name>.

Runtime and API calls:

  • common.NewRuntimeContext creates client.Client, carries owner, repo, format, and command args.
  • ctx.ResolveOwnerRepo() resolves --owner / --repo or Git remote context.
  • ctx.CallAPI and ctx.CallAPIWithQuery call internal/client.
  • client.Do appends .json, injects auth via transport, parses GitLink error-in-body responses, and returns output.Envelope.

Output:

  • internal/output currently supports json, yaml, and generic table.
  • Workflow requires markdown; the minimal-risk approach is a workflow-local renderer that prints stable workflow DTOs.
  • A later cleanup can promote markdown support into internal/output if multiple command groups need it.
  • Current workflow commands also expose workflow-local json, table, and markdown rendering without changing the global formatter.

Testing:

  • Existing tests use pure unit tests plus httptest.Server.
  • Shortcut tests instantiate common.RuntimeContext manually with a mocked client.Client.
  • This pattern should be reused for workflow API tests.

Command Design

workflow +triage

Examples:

gitlink-cli workflow +triage --owner Gitlink --repo gitlink-cli --state open --limit 30 --dry-run --format json
gitlink-cli workflow +triage --owner Gitlink --repo gitlink-cli --state open --limit 30 --format table
gitlink-cli workflow +triage --owner Gitlink --repo gitlink-cli --state open --limit 30 --lang zh-CN --format markdown

Flags:

  • --state: default open
  • --limit: default 30
  • --page: default 1
  • --dry-run: default true
  • --from: optional local JSON input
  • --title, --body, --number, --author, --url, --labels: optional local single-issue input
  • --lang: default en, allowed en, zh-CN

Stable JSON item fields:

  • issue_id
  • number
  • title
  • url
  • author
  • state
  • created_at
  • updated_at
  • detected_type
  • priority
  • confidence
  • suggested_labels
  • missing_information
  • risk_flags
  • recommended_action
  • suggested_comment
  • reasoning

Rule categories:

  • bug
  • feature
  • question
  • docs
  • ci
  • security
  • performance
  • refactor
  • unknown

Priority:

  • P0: security incident, secret/token leak, auth bypass, repository unusable
  • P1: core command unusable, install/login failure, CI/release blocker
  • P2: normal bug, important feature, missing docs blocking usage
  • P3: ordinary question, typo, minor improvement

Missing information for bug-like issues:

  • reproduction steps
  • expected behavior
  • actual behavior
  • version
  • OS / platform
  • command output
  • logs

workflow +health

Examples:

gitlink-cli workflow +health --owner Gitlink --repo gitlink-cli --format json
gitlink-cli workflow +health --owner Gitlink --repo gitlink-cli --format table
gitlink-cli workflow +health --owner Gitlink --repo gitlink-cli --lang zh-CN --format markdown

Flags:

  • --stale-days: default 30
  • --from: optional local JSON input
  • local metric flags such as --repository, --open-issues, --open-prs, --has-readme, --has-license, and --agent-readiness-score
  • --lang: default en

Stable JSON fields:

  • repository
  • open_issues
  • open_prs
  • stale_issues
  • stale_prs
  • recent_activity
  • release_status
  • ci_status
  • documentation_status
  • license_status
  • contribution_status
  • agent_readiness_score
  • health_score
  • risk_level
  • recommendations
  • scoring_notes

Scoring:

  • Issue backlog and response: 20
  • PR backlog and merge state: 20
  • Recent activity: 15
  • Release status: 15
  • Documentation completeness: 10
  • License and contribution readiness: 10
  • Agent readiness: 10

Unknown metric policy:

  • Keep field present.
  • Set status or score detail to unknown.
  • Add one entry to scoring_notes.
  • Either omit the metric from denominator or apply a conservative partial score; the first PR should prefer denominator adjustment to avoid fake precision.

Risk levels:

  • low: 80-100
  • medium: 60-79
  • high: 40-59
  • critical: 0-39

Architecture

Proposed files:

shortcuts/workflow/
  workflow.go          # Shortcuts() and command wiring
  types.go             # Stable DTOs
  triage_rules.go      # pure classifier, scoring, missing info detection
  triage_fetch.go      # GitLink issue fetching and response normalization
  triage_render.go     # json/table/markdown workflow rendering if needed
  health_score.go      # pure health scoring
  health_fetch.go      # repo, issue, PR, release, CI/doc/license probes
  health_render.go     # markdown/table rendering
  messages.go          # en and zh-CN strings
  *_test.go

Registration:

  • Add workflow import in shortcuts/register.go.
  • Add "workflow": workflow.Shortcuts() to groups.
  • Add description "AI agent workflow analysis".

No new dependency is needed for this PR.

Data Normalization

GitLink responses vary by endpoint. Workflow code should not depend on a single raw shape. Add small extraction helpers:

  • stringField(map, keys...)
  • numberField(map, keys...)
  • timeField(map, keys...)
  • sliceField(map, keys...)
  • extractItems(env, candidateKeys...)

Candidate issue list keys:

  • issues
  • data
  • direct array after future client improvements

Candidate issue fields:

  • ID: id, issue_id
  • Number: project_issues_index, number, index, id
  • Title: subject, title
  • Body: description, body
  • Author: author.login, user.login, login
  • URL: html_url, url, issue_url

Health activity fields currently tolerated:

  • updated_at
  • updatedAt
  • last_updated_at
  • lastUpdatedAt
  • last_activity_at
  • lastActivityAt
  • merged_at
  • mergedAt
  • closed_at
  • closedAt

Safety Strategy

  • +triage only reads by default.
  • --dry-run defaults true.
  • A future explicit write flag for posting comments must require --dry-run=false in a later PR.
  • Generated comments are output as data, not posted remotely in the first PR.
  • Health checks never mutate remote state.
  • If an API probe fails, health continues with unknown.
  • The implemented prototype is local-first and has no LLM dependency.
  • Remote fetch mode remains read-only and does not post comments, labels, merges, or close actions.
  • API failures should fall back to unknown metrics or a clear fetch error instead of fabricating healthy data.

Core Pseudocode

Triage

issues := fetchIssues(owner, repo, state, limit, page)
results := []TriageResult{}
for _, issue := range issues {
    text := normalize(issue.Title + "\n" + issue.Body)
    scores := scoreKeywords(text, keywordRules)
    detectedType := maxScoreType(scores)
    priority := scorePriority(text, detectedType)
    missing := detectMissingInfo(issue, detectedType)
    confidence := confidenceFromScores(scores, missing)
    result := TriageResult{
        IssueID: issue.ID,
        Number: issue.Number,
        DetectedType: detectedType,
        Priority: priority,
        SuggestedLabels: labelsFor(detectedType, priority, riskFlags),
        MissingInformation: missing,
        RiskFlags: detectRiskFlags(text),
        RecommendedAction: actionFor(detectedType, priority, missing, lang),
        SuggestedComment: commentFor(missing, lang),
        Reasoning: explainTopMatches(scores, priorityRules),
    }
    results = append(results, result)
}
render(results, format, lang)

Health

signals := collectHealthSignals(owner, repo)
score := NewWeightedScore(100)
score.Add("issues", 20, scoreIssueBacklog(signals.OpenIssues, signals.StaleIssues))
score.Add("prs", 20, scorePRBacklog(signals.OpenPRs, signals.StalePRs))
score.Add("activity", 15, scoreRecentActivity(signals.RecentActivity))
score.Add("release", 15, scoreReleaseStatus(signals.ReleaseStatus))
score.Add("docs", 10, scoreDocStatus(signals.DocumentationStatus))
score.Add("license", 10, scoreLicenseContribution(signals.LicenseStatus, signals.ContributionStatus))
score.Add("agent", 10, scoreAgentReadiness(signals))
result := HealthResult{
    HealthScore: score.Percent(),
    RiskLevel: riskLevel(score.Percent()),
    Recommendations: recommendations(signals, score),
    ScoringNotes: score.Notes(),
}
render(result, format, lang)

Output Protocol

JSON:

  • Use stable struct tags.
  • Include empty arrays as [] where useful for Agent consumption.
  • Avoid prose outside JSON.

Table:

  • Triage columns: NUMBER, TYPE, PRIORITY, CONFIDENCE, MISSING, ACTION
  • Health rows: METRIC, STATUS, SCORE, NOTE

Markdown:

  • Triage: one summary table with type, priority, confidence, action, and missing information.
  • Health: repository score, metric table, recommendations, and scoring notes.
  • zh-CN changes rule messages and recommendation text, not JSON field names.

Test Plan

Unit tests:

  • Issue type classification.
  • Priority scoring.
  • Missing information detection.
  • Risk flag detection.
  • Suggested comment generation.
  • Health weighted score and risk level.
  • Unknown metric denominator adjustment.
  • Markdown headings and required sections.

Mock API tests:

  • workflow +triage fetches issues and normalizes raw response.
  • workflow +health tolerates failing CI/release/doc probes.

Command tests:

  • --dry-run defaults to true.
  • --lang zh-CN accepted.
  • invalid --lang falls back to en.
  • --format markdown routes to markdown renderer.

Later Extensions

workflow +pr-summary

Inputs:

  • --number
  • --from
  • --lang
  • --format
  • optional --include-files
  • optional --include-commits
  • optional --max-files
  • optional --max-commits

Default format:

  • table for human review when --format is omitted

Data:

  • PR details
  • changed files
  • commits

Output:

  • change_type
  • risk_level
  • review_focus
  • test_suggestions
  • merge_checklist
  • reasoning

Implementation status:

  • read-only local JSON mode: done
  • read-only GitLink fetch mode: done
  • rules and renderers: done
  • tests: rules, fetch boundary, render, and command wiring

Safety:

  • no comments
  • no approve/reject
  • no merge
  • no remote write operation

workflow +repo-report

Inputs:

  • --owner
  • --repo
  • --from
  • --lang
  • --format
  • optional --issue-limit
  • optional --pr-limit
  • optional --stale-days
  • optional --include-issues
  • optional --include-prs
  • optional --include-health

Default format:

  • markdown for maintainer and competition reports when --format is omitted

Data:

  • repository health input and score
  • issue triage results aggregated by type, priority, risk, and missing information
  • PR summary results aggregated by type, risk, and review focus

Output:

  • report_score
  • risk_level
  • health
  • issue_summary
  • pr_summary
  • recommendations
  • reasoning

Partial report strategy:

  • health, issue, and PR sections are fetched independently
  • if at least one enabled section succeeds, the command returns a partial report
  • failed sections are recorded in scoring notes or reasoning
  • PR remote aggregation currently uses PR list metadata only; detailed changed files and commits remain available through workflow +pr-summary --number

Safety:

  • read-only aggregation only
  • no comments, labels, closes, approve/reject, or merge operations
  • no LLM dependency

workflow +release-notes

Inputs:

  • --from
  • --from-ref
  • --to-ref
  • optional --version
  • optional --max-commits
  • optional --include-prs
  • optional --lang

Data:

  • PR titles
  • commit messages
  • changed file paths when present in compare data

Markdown categories:

  • Breaking Changes
  • Features
  • Bug Fixes
  • Documentation
  • Tests
  • Refactoring
  • Chores

Examples:

gitlink-cli workflow +release-notes --from shortcuts/workflow/testdata/release_notes.json --format markdown
gitlink-cli workflow +release-notes --owner Gitlink --repo gitlink-cli --from-ref v0.1.0 --to-ref master --version v0.2.0 --format json

Behavior:

  • Use local JSON input when --from is set.
  • In remote mode, read GET /v1/:owner/:repo/compare?from=<from-ref>&to=<to-ref>.
  • Classify commits and PRs with deterministic rules.
  • Render json, table, or markdown; default output is markdown.
  • Do not create releases, comments, labels, reviews, or merges.

workflow +stale

Inputs:

  • --stale-days
  • --state
  • --dry-run

Behavior:

  • Identify stale issues and PRs.
  • Generate suggested comments or labels.
  • Do not mutate remote state by default.

API Fetch Layer

The current fetch layer uses:

  • triage_fetch.go
  • health_fetch.go
  • pr_fetch.go
  • repo_report_fetch.go

Design goals already applied:

  • tolerate unknown or partial API fields
  • map GitLink response shapes into stable workflow DTOs
  • continue operating when optional signals fail
  • keep remote-write actions disabled until explicitly enabled later

Planned fetch-layer extension:

  • triage_fetch.go and health_fetch.go remain the normalization boundary for remote mode.
  • pr_fetch.go now reuses the same stable DTO and message patterns for read-only PR metadata, changed files, and commits.
  • repo_report_fetch.go composes the existing fetch helpers and records partial failures instead of failing the whole report.
  • release_notes_fetch.go reuses the same normalization and renderer patterns for read-only compare data.
  • Unknown or missing fields should stay explicit in JSON output so Agents can decide how to proceed.

Implementation Order

  1. Pure DTOs and rule engine.
  2. Pure health scoring.
  3. Workflow renderers.
  4. Command registration.
  5. API fetch and normalization.
  6. Tests.
  7. README updates.
  8. Competition docs and test report.