Skip to content

fix(server,workflows,web): surface bundled defaults on /api/workflows when no project context#1618

Merged
Wirasm merged 4 commits into
coleam00:devfrom
truffle-dev:fix/workflows-surface-bundled-defaults-no-cwd
May 14, 2026
Merged

fix(server,workflows,web): surface bundled defaults on /api/workflows when no project context#1618
Wirasm merged 4 commits into
coleam00:devfrom
truffle-dev:fix/workflows-surface-bundled-defaults-no-cwd

Conversation

@truffle-dev
Copy link
Copy Markdown
Contributor

@truffle-dev truffle-dev commented May 9, 2026

Summary

  • Problem: GET /api/workflows returns {"workflows":[]} when there is no cwd query param and no registered codebase, even though bundled defaults exist on disk. The Workflows page then renders a misleading empty state telling users to add files to .archon/workflows/.
  • Why it matters: First-run experience after a fresh deployment is broken — users see "no workflows" and a hint that suggests their installation is incomplete, when in fact the 20 bundled defaults are sitting at /app/.archon/workflows/defaults/.
  • What changed: Threaded cwd: string | null through the discovery functions; the null case loads bundled + home scopes and skips the project step. The GET handler now passes null instead of returning []. The empty-state copy in WorkflowList now distinguishes "no project selected" from "no workflows in this project".
  • What did not change (scope boundary): Single-workflow GET/PUT/DELETE handlers were already correct (they fall through to BUNDLED_WORKFLOWS on name lookup when there is no cwd). The separate getArchonWorkspacesPath() issue mentioned in the issue's follow-up comment is a chat-flow bug, not a workflow-list bug, and is left for another change.

UX Journey

Before

  User                     Workflows API                Discovery
  ────                     ─────────────                ─────────
  loads /workflows ──────▶ GET /api/workflows
                           cwd? no
                           registered codebases? none
                           [X] return { workflows: [] }
  sees empty UI ◀───────── "Add workflow definitions to .archon/workflows/"
  ❌ bundled defaults present on disk but never surfaced

After

  User                     Workflows API                Discovery
  ────                     ─────────────                ─────────
  loads /workflows ──────▶ GET /api/workflows
                           cwd? no
                           registered codebases? none
                           workingDir = null      [~]
                           discoverWorkflowsWithConfig(null, ...)  ──▶
                                                                       step 1: bundled (loaded)
                                                                       step 2: home (loaded)
                                                                       step 3: project (skipped)
                           ◀── { workflows: [...bundled, ...home] }
  sees bundled list ◀───── 20 default workflows render

  When the list is genuinely empty (defaults disabled in config):
  - With project selected: "No workflows found in this project. Add definitions to .archon/workflows/."
  - Without project:       "No workflows are available. Bundled defaults should appear automatically;
                            check that defaults.loadDefaultWorkflows is enabled in your config."

Architecture Diagram

Before

api.ts (GET /api/workflows)
  └── if (!workingDir) return { workflows: [] }   [X] short-circuit

workflow-discovery.ts
  └── discoverWorkflows(cwd: string, ...)         [requires cwd]
       step 1: bundled
       step 2: home
       step 3: join(cwd, .archon/workflows)

After

api.ts (GET /api/workflows)
  └── workingDir ?? null → discovery                [~]

workflow-discovery.ts
  └── discoverWorkflows(cwd: string | null, ...)    [~]
       step 1: bundled
       step 2: home
       step 3: if cwd === null → return early       [+]
                else → join(cwd, .archon/workflows)
  └── discoverWorkflowsWithConfig(cwd: string | null, ...)  [~]
       skips loadConfig when cwd === null

WorkflowList.tsx
  └── empty state                                    [~]
       branches on localProjectId

Connection inventory:

From To Status Notes
api.ts GET handler discoverWorkflowsWithConfig modified Passes null instead of returning [] early
discoverWorkflows repo-scope project step modified Skipped when cwd === null
discoverWorkflowsWithConfig loadConfig(cwd) modified Skipped when cwd === null (no per-project config)
WorkflowList.tsx empty-state JSX modified Branches on localProjectId
cli/commands/{validate,workflow}.ts discovery unchanged string is assignable to string | null — no caller changes

Label Snapshot

  • Risk: risk: low
  • Size: size: S
  • Scope: server, workflows, web
  • Module: server:routes/api, workflows:workflow-discovery, web:workflows

Change Metadata

  • Change type: bug
  • Primary scope: multi

Linked Issue

Validation Evidence (required)

# Workflow discovery tests (loader.test.ts) — adds 2 new tests
$ bun test packages/workflows/src/loader.test.ts
 119 pass, 0 fail, 271 expect() calls

# Server route tests (api.workflows.test.ts) — adds 1 new test
$ bun test packages/server/src/routes/api.workflows.test.ts
 28 pass, 0 fail, 76 expect() calls

# Web tests + type-check
$ bun --filter @archon/web type-check
$ bun --filter @archon/web test
 30 pass, 0 fail (lib)
 13 pass, 0 fail (stores)

# Type-check across changed packages
$ bun --filter @archon/workflows type-check  → clean
$ bun --filter @archon/server type-check     → clean
$ bun --filter @archon/web type-check        → clean

# Format + lint
$ bun x prettier --check <changed files>     → all matched files use Prettier code style
$ bun x eslint . --cache --max-warnings 0    → clean

# Bundled checks
$ bun run check:bundled         → bundled-defaults.generated.ts is up to date (36 commands, 20 workflows)
$ bun run check:bundled-skill   → bundled-skill.ts is up to date (21 files)
  • Evidence provided: test results, type-check, lint, format, bundled-defaults check.
  • If any command is intentionally skipped, explain why: Pre-existing cli/doctor.test.ts checkWorkspaceWritable failures (2) and 1 workflowRunCommand flake (passes individually, fails in the full suite) reproduce on pristine upstream/dev without these changes — verified via git stash round-trip — so they are not caused by this PR.

Security Impact (required)

  • New permissions/capabilities? No
  • New external network calls? No
  • Secrets/tokens handling changed? No
  • File system access scope changed? Nonull cwd skips the only cwd-derived fs.access call (the project step), so file-system reach is reduced, not expanded.

Compatibility / Migration

  • Backward compatible? Yescwd: string is assignable to cwd: string | null. All existing callers in cli/commands/validate.ts, cli/commands/workflow.ts, and the rest of api.ts continue to pass concrete strings.
  • Config/env changes? No
  • Database migration needed? No

Human Verification (required)

  • Verified scenarios:
    • GET /api/workflows with no cwd and no registered codebases returns the bundled set with source: 'bundled' (new test).
    • discoverWorkflows(null, { loadDefaults: false }) produces zero project-source entries and zero project-step read errors (new test).
    • discoverWorkflows(null, { loadDefaults: true }) still loads bundled defaults and skips the project step (new test).
    • WorkflowList empty-state copy verified by inspection of the conditional render path (no project + no workflows → defaults-hint message; project + no workflows → project-hint message).
  • Edge cases checked: caller-supplied cwd= still validates against registered codebases (unchanged 400 path); registered-codebases path still resolves to the first codebase's default_cwd; discoverWorkflowsWithConfig no longer calls loadConfig when cwd === null (per-project opt-out only makes sense when a project is actually selected).
  • What was not verified: Multi-tenant deployment with custom ~/.archon/workflows/ overrides — the home-scope step is unchanged, so this should behave the same as before.

Side Effects / Blast Radius (required)

  • Affected subsystems/workflows: GET /api/workflows (handler), discoverWorkflows and discoverWorkflowsWithConfig (signature widening), WorkflowList empty-state copy.
  • Potential unintended effects: A fresh deployment that previously saw [] now sees ~20 bundled defaults. That is the intended fix, but it does change the response shape for the no-project path.
  • Guardrails/monitoring for early detection: Existing workflows_discovery_completed info-level log now includes scope: 'no_project_context' when the null path is taken, so dashboards can detect the new branch.

Rollback Plan (required)

  • Fast rollback command/path: Revert this PR. No schema changes, no migrations.
  • Feature flags or config toggles: None new. Users who want the old "empty list when no project" behavior can set defaults.loadDefaultWorkflows: false per project, but the no-project path always loads bundled (this is the bug being fixed).
  • Observable failure symptoms: Workflows page renders unexpected entries, or the existing workflows_discovery_completed log shows scope: 'no_project_context' more often than expected.

Risks and Mitigations

  • Risk: A test or downstream caller relied on discoverWorkflows requiring a non-null cwd.
    • Mitigation: Searched the repo for all call sites — cli/commands/validate.ts:90, cli/commands/workflow.ts:176, and the GET handler. All pass concrete strings. The signature widening is purely additive.
  • Risk: A user with defaults.loadDefaultWorkflows: false per project expects the no-project path to also be empty.
    • Mitigation: The no-project path explicitly skips loadConfig because there is no project to read config from. This is documented in the function-level comment. If the user wants to suppress bundled defaults globally, the existing isBinaryBuild()/path mechanism already covers compiled-binary mode.

Summary by CodeRabbit

  • New Features

    • Bundled and home-scoped workflows are discovered and shown even when no project is selected.
  • Bug Fixes

    • API returns bundled/home workflows on first run when no project is registered.
    • Workflow list empty-state message now varies based on whether a project is selected.
  • Tests

    • Added tests for discovery and API behavior in no-project context.
  • Documentation

    • API reference and changelog updated to reflect discovery behavior.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9e88121e-9dbd-4afa-bce1-0d6f04107f71

📥 Commits

Reviewing files that changed from the base of the PR and between 889aec3 and 088dad2.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • packages/server/src/routes/api.workflows.test.ts
  • packages/workflows/src/loader.test.ts
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/workflows/src/loader.test.ts
  • packages/server/src/routes/api.workflows.test.ts

📝 Walkthrough

Walkthrough

When no project is selected, the /api/workflows endpoint previously returned an empty list, causing the UI to display a misleading message about adding workflows to a project. This PR enables workflow discovery with a nullable cwd parameter, allowing bundled and home-scoped workflows to be returned even without project context, and updates the UI messaging to reflect whether a project is selected.

Changes

Support bundled workflows when no project context is selected

Layer / File(s) Summary
Discovery function signatures
packages/workflows/src/workflow-discovery.ts
discoverWorkflows and discoverWorkflowsWithConfig now accept cwd: string | null to enable execution without a project directory.
Discovery execution logic
packages/workflows/src/workflow-discovery.ts
When cwd is null, repo-local workflow discovery is skipped; bundled and home-scoped workflows are aggregated and returned along with any accumulated errors.
API endpoint integration
packages/server/src/routes/api.ts
GET /api/workflows now passes workingDir ?? null to discovery instead of short-circuiting to an empty list, ensuring bundled workflows are returned even without a project context.
Context-aware empty-state messaging
packages/web/src/components/workflows/WorkflowList.tsx
Empty-state message is now conditional on project selection: guides users to add .archon/workflows/ definitions if a project is selected, or to enable defaults.loadDefaultWorkflows if no project is selected.
Test coverage
packages/server/src/routes/api.workflows.test.ts, packages/workflows/src/loader.test.ts
New tests verify null-cwd discovery skips project scope but returns bundled workflows, ensure loadConfig isn't called for null cwd, and confirm the API endpoint retrieves bundled workflows without a cwd query parameter.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • coleam00/Archon#1315: Modifies the same workflow-discovery functions and home/global workflow discovery behavior to support null cwd.

Possibly related issues

Poem

🐰 A workflow without a home, now finds its way,
Through bundled defaults that brighten the day,
No project required to start the quest,
The UI now guides them gently to the best. 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(server,workflows,web): surface bundled defaults on /api/workflows when no project context' accurately summarizes the main change—ensuring bundled defaults are surfaced when no project context exists.
Description check ✅ Passed The PR description comprehensively covers all required template sections: problem statement, why it matters, what changed, scope boundaries, UX journey with before/after diagrams, architecture changes, validation evidence with test results, security impact, compatibility, human verification, side effects, and rollback plan.
Linked Issues check ✅ Passed The changes fully satisfy issue #1173's objective: bundled defaults are now surfaced when no project context exists, workflow discovery signatures accept null cwd, and empty-state messaging differentiates no-project from no-workflows scenarios.
Out of Scope Changes check ✅ Passed All changes directly address issue #1173 and stay within documented scope boundaries. The PR explicitly excludes the separate getArchonWorkspacesPath chat-flow bug for follow-up.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/workflows/src/loader.test.ts (1)

2531-2539: ⚡ Quick win

Make the “still loads bundled defaults” assertion explicit.

This test currently only re-checks that project scope is skipped. It should also assert bundled-sourced workflows exist, otherwise it can pass even if bundled loading breaks.

✅ Minimal assertion addition
     const result = await discoverWorkflows(null, { loadDefaults: true });

     // No project-source entries (project step skipped).
     const projectSourced = result.workflows.filter(w => w.source === 'project');
     expect(projectSourced).toHaveLength(0);
+    const bundledSourced = result.workflows.filter(w => w.source === 'bundled');
+    expect(bundledSourced.length).toBeGreaterThan(0);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/workflows/src/loader.test.ts` around lines 2531 - 2539, The test
only asserts no project-sourced workflows but doesn't verify bundled defaults
loaded; update the test that calls discoverWorkflows(null, { loadDefaults: true
}) to also filter result.workflows for entries where w.source === 'bundled' (or
the exact bundled source label used by the loader) and assert that array has
length > 0 (e.g., expect(bundledSourced).toHaveLengthGreaterThan(0) or
expect(bundledSourced.length).toBeGreaterThan(0)) so the bundled-defaults loader
is explicitly validated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/web/src/components/workflows/WorkflowList.tsx`:
- Around line 187-193: The empty-state hint in the WorkflowList component
currently tells users to check defaults.loadDefaultWorkflows which is misleading
when there is no project; update the JSX copy in WorkflowList so it clarifies
that when no project is present the app still attempts bundled defaults
automatically and that users should either create/select a project or check
global configuration (e.g., defaults.loadDefaultWorkflows) if bundled defaults
are missing—locate the message text in WorkflowList and replace it with wording
that explicitly differentiates the “no project” path from project-specific
config.

---

Nitpick comments:
In `@packages/workflows/src/loader.test.ts`:
- Around line 2531-2539: The test only asserts no project-sourced workflows but
doesn't verify bundled defaults loaded; update the test that calls
discoverWorkflows(null, { loadDefaults: true }) to also filter result.workflows
for entries where w.source === 'bundled' (or the exact bundled source label used
by the loader) and assert that array has length > 0 (e.g.,
expect(bundledSourced).toHaveLengthGreaterThan(0) or
expect(bundledSourced.length).toBeGreaterThan(0)) so the bundled-defaults loader
is explicitly validated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 793baad8-8f8e-4c03-a45a-ab262adedd64

📥 Commits

Reviewing files that changed from the base of the PR and between f4f2725 and 2be5dd4.

📒 Files selected for processing (5)
  • packages/server/src/routes/api.ts
  • packages/server/src/routes/api.workflows.test.ts
  • packages/web/src/components/workflows/WorkflowList.tsx
  • packages/workflows/src/loader.test.ts
  • packages/workflows/src/workflow-discovery.ts

Comment thread packages/web/src/components/workflows/WorkflowList.tsx
@Wirasm
Copy link
Copy Markdown
Collaborator

Wirasm commented May 11, 2026

Review Summary

Verdict: minor-fixes-needed

Your PR surfaces bundled and home-scoped workflows when no project is registered, fixing the broken first-run experience where users saw an empty workflow list before any codebase was added. The three changed files implement this cleanly and consistently. A few targeted additions will close the test and docs gaps.

Blocking issues

(none — no CRITICAL or HIGH findings)

Suggested fixes

  • packages/workflows/src/loader.test.ts:2543 + new describe block — Two test gaps to close before merge:

    1. Verify the null-cwd code path was exercised (not just the outcome). After calling discoverWorkflows(null, ...), assert that no project-scoped entry appears in the result — since project discovery is skipped when cwd === null, the result should contain only bundled and home-scoped entries.

    2. Assert loadConfig is not called when cwd is null. Add this inside the new describe('discoverWorkflows with null cwd') block:

      const mockLoadConfig = vi.fn();
      await discoverWorkflowsWithConfig(null, mockLoadConfig);
      expect(mockLoadConfig).not.toHaveBeenCalled();

      This is the only way to catch a silent regression if the if (cwd !== null) guard is removed in future refactoring.

  • packages/docs-web/src/content/docs/reference/api.md — Document what GET /api/workflows returns when cwd is omitted. After the cwd query param description, add: "When cwd is omitted, Archon returns bundled default workflows and any from ~/.archon/workflows/ (home-scoped). Project-specific workflows require either the cwd query param or a registered codebase. This means the endpoint is useful on first launch before any project is registered."

Minor / nice-to-have

  • packages/server/src/routes/api.ts:1782: Drop the trailing period on the inline comment — one-line comments should be terse.
  • packages/server/src/routes/api.workflows.test.ts:16: Update the mock type annotation to async (_cwd: string | null) => ({ for correctness.
  • CHANGELOG.md: Add an entry under [Unreleased] > ### Fixed: "GET /api/workflows no longer returns an empty array when no cwd query param is provided and no codebases are registered — bundled and home-scoped workflows now surface correctly on first run (Workflows page shows false empty state when no project/cwd is selected #1173)." (Skip if maintainers batch bug fixes.)
  • packages/workflows/src/workflow-discovery.tsdiscoverWorkflowsWithConfig docstring: Reword "config lookup is skipped" to clarify that config is not consulted because loadDefaults defaults to true when cwd is null.

Compliments

  • The UX journey and architecture diagrams in the PR description are thorough and make the intent immediately clear.
  • The WorkflowList.tsx empty-state conditional (localProjectId check) is a thoughtful UX touch — the message now distinguishes "no workflows in this project" from "no workflows available" without a project context.
  • The early-return comment at api.ts:1779-1783 documents the user-facing problem (not task/PR references) — exactly the kind of WHY-comment the CLAUDE.md policy encourages.

Reviewed via maintainer-review-pr workflow (Pi/Minimax). Aspects run: code-review, test-coverage, comment-quality, docs-impact.

truffle-dev added a commit to truffle-dev/Archon that referenced this pull request May 11, 2026
- api.md: document cwd-omitted behavior so the empty-state case is discoverable
- workflow-discovery.ts: docstring explains loadDefaults default rather than just naming the skipped branch
- api.workflows.test.ts: mockDiscoverWorkflows accepts string | null to match the wider signature
- api.ts: drop trailing period inside the multi-line inline comment
- CHANGELOG.md: add the coleam00#1173 Fixed entry under [Unreleased]
- loader.test.ts: add a regression test that asserts loadConfig is not invoked when cwd is null
@truffle-dev
Copy link
Copy Markdown
Contributor Author

Addressed in 018928c:

  1. loader.test.ts — added the loadConfig not-called-when-cwd-is-null assertion. Used bun's mock since the file is bun:test, not vitest.
  2. workflow-discovery.ts — docstring reworded to explain loadDefaults keeps its true initial value rather than just naming the skipped branch.
  3. api.md — cwd-omitted behavior paragraph added under the List Workflows section, so the first-launch case is discoverable from the docs.
  4. api.ts — trailing period dropped on the multi-line inline comment.
  5. api.workflows.test.tsmockDiscoverWorkflows now types _cwd as string | null.
  6. CHANGELOG.md#1173 entry added under [Unreleased] > Fixed.

The "verify null-cwd path was exercised" sub-point of (1) was already covered: the existing test at L2531-2539 filters result.workflows for source === 'project' and asserts length zero, and CodeRabbit's parallel ask for the bundled-source length > 0 assertion landed in 897c145.

… when no project context (coleam00#1173)

GET /api/workflows short-circuits to an empty array when there is no
`cwd` query param and no registered codebases. The handler never
reaches discovery, so bundled defaults are not surfaced and the UI
renders a misleading "Add workflow definitions to .archon/workflows/"
empty state on first run — even though the bundled YAML files are
present on disk.

This change:

- Threads `cwd: string | null` through `discoverWorkflows` and
  `discoverWorkflowsWithConfig`. When `cwd` is `null` the discovery
  function loads bundled + home scopes and skips the project step
  cleanly (no path-join with an empty cwd, no read-error noise).
- Removes the early-return in the GET handler. When no project
  context exists, it now calls `discoverWorkflowsWithConfig(null, ...)`
  so the response carries the bundled set instead of `[]`.
- Distinguishes the empty-state copy in `WorkflowList` so the rare
  case where the list is genuinely empty reads correctly. With a
  project selected: "No workflows found in this project. Add
  workflow definitions to .archon/workflows/ in the project root."
  Without a project: "No workflows are available. Bundled defaults
  should appear here automatically; if they do not, check that
  `defaults.loadDefaultWorkflows` is enabled in your config."

Tests cover both the API (new `falls back to null cwd when no cwd
query and no codebases registered` case in `api.workflows.test.ts`)
and the discovery layer (new `discoverWorkflows with null cwd` block
in `loader.test.ts` asserting no project-source entries and no
project-step read errors).
The second test in the null-cwd discovery group only verified that
project-source workflows are absent. That assertion would still pass
if the bundled-defaults loader silently regressed.

Add an explicit `bundled` source-label assertion so the test catches
that regression directly.
- api.md: document cwd-omitted behavior so the empty-state case is discoverable
- workflow-discovery.ts: docstring explains loadDefaults default rather than just naming the skipped branch
- api.workflows.test.ts: mockDiscoverWorkflows accepts string | null to match the wider signature
- api.ts: drop trailing period inside the multi-line inline comment
- CHANGELOG.md: add the coleam00#1173 Fixed entry under [Unreleased]
- loader.test.ts: add a regression test that asserts loadConfig is not invoked when cwd is null
@truffle-dev truffle-dev force-pushed the fix/workflows-surface-bundled-defaults-no-cwd branch from 018928c to 889aec3 Compare May 12, 2026 19:05
@Wirasm
Copy link
Copy Markdown
Collaborator

Wirasm commented May 13, 2026

Review Summary

Verdict: ready-to-merge

Solid bug fix. Your change plumbs null through the discovery chain so GET /api/workflows surfaces bundled + home-scoped workflows on first launch — before any codebase is registered. The implementation is clean, well-scoped, and tested. Four optional polish items below; none are blocking.

Suggested fixes

  • loader.test.ts:2524–2527: The inline (issue #1173) reference is a rot risk — the surrounding comment fully explains the behavior without it. Remove the reference.

  • api.workflows.test.ts:135–136: Same issue — remove (issue #1173); the WHY is self-explanatory.

  • loader.test.ts (the loadDefaults: false case): The test doesn't assert that zero workflows are returned — it passes even if bundled defaults are erroneously loaded. Add expect(result.workflows.length).toBe(0) after the bundled-filter check.

Minor / nice-to-have

  • loader.test.ts:2541–2544: The comment points to an exact branch in workflow-discovery.ts. If that branch is renamed during a future refactor, this comment misdirects. Reword to capture intent without the file+line reference.

  • CHANGELOG.md: The entry frames the fix as "no longer returns empty array" — consider appending a positive-framing clause: — making the workflow picker functional on first launch before any project is registered.

Compliments

  • The WHY comments in api.ts:1779–1784 and workflow-discovery.ts:285–288 are excellent — they capture non-obvious invariants clearly.
  • The test suite properly isolates mock targets and exercises the null-cwd path from both the discovery unit and the API handler level.
  • API documentation updated in the same PR; no docs debt introduced.

Reviewed via maintainer-review-pr workflow (Pi/Minimax). Aspects run: code-review, error-handling, test-coverage, comment-quality, docs-impact.

Address Wirasm's polish review on coleam00#1618:

- loader.test.ts: assert result.workflows.length === 0 in the
  loadDefaults:false case so the test no longer passes if bundled
  defaults are accidentally loaded.
- loader.test.ts: drop the inline (issue coleam00#1173) reference and the
  workflow-discovery.ts file+line pointer from the two comments
  that risk rotting on future refactor.
- api.workflows.test.ts: drop the inline (issue coleam00#1173) reference.
- CHANGELOG: append positive framing to the coleam00#1173 line so the
  entry reads as "what works now" not just "what no longer breaks".
@truffle-dev
Copy link
Copy Markdown
Contributor Author

  1. loader.test.ts:2524-2527 — dropped the inline (issue #1173) reference; the surrounding comment now stands on its own (088dad2).
  2. api.workflows.test.ts:135-136 — same drop on the API-handler test (088dad2).
  3. loader.test.ts loadDefaults:false case — added expect(result.workflows).toHaveLength(0) so the test no longer passes if bundled defaults are accidentally loaded; verified locally with bun test packages/workflows/src/loader.test.ts (120 pass) (088dad2).
  4. loader.test.ts:2541-2544 — reworded the comment to capture intent without the workflow-discovery.ts file+line pointer (088dad2).
  5. CHANGELOG — appended , making the workflow picker functional on first launch before any project is registered to the Workflows page shows false empty state when no project/cwd is selected #1173 line so the entry reads as what works now, not just what no longer breaks (088dad2).

@Wirasm Wirasm merged commit 3d290d8 into coleam00:dev May 14, 2026
4 checks passed
@truffle-dev
Copy link
Copy Markdown
Contributor Author

Thanks for the merge. The two-round review caught two test-assertion gaps that were passing silently: loadConfig-not-called on null cwd, and loadDefaults: false returning zero workflows. Both would have shipped behind green CI without the review. Useful pattern for the next round in this area.

cropse pushed a commit to cropse/Archon that referenced this pull request May 19, 2026
… when no project context (coleam00#1618)

* fix(server,workflows,web): surface bundled defaults on /api/workflows when no project context (coleam00#1173)

GET /api/workflows short-circuits to an empty array when there is no
`cwd` query param and no registered codebases. The handler never
reaches discovery, so bundled defaults are not surfaced and the UI
renders a misleading "Add workflow definitions to .archon/workflows/"
empty state on first run — even though the bundled YAML files are
present on disk.

This change:

- Threads `cwd: string | null` through `discoverWorkflows` and
  `discoverWorkflowsWithConfig`. When `cwd` is `null` the discovery
  function loads bundled + home scopes and skips the project step
  cleanly (no path-join with an empty cwd, no read-error noise).
- Removes the early-return in the GET handler. When no project
  context exists, it now calls `discoverWorkflowsWithConfig(null, ...)`
  so the response carries the bundled set instead of `[]`.
- Distinguishes the empty-state copy in `WorkflowList` so the rare
  case where the list is genuinely empty reads correctly. With a
  project selected: "No workflows found in this project. Add
  workflow definitions to .archon/workflows/ in the project root."
  Without a project: "No workflows are available. Bundled defaults
  should appear here automatically; if they do not, check that
  `defaults.loadDefaultWorkflows` is enabled in your config."

Tests cover both the API (new `falls back to null cwd when no cwd
query and no codebases registered` case in `api.workflows.test.ts`)
and the discovery layer (new `discoverWorkflows with null cwd` block
in `loader.test.ts` asserting no project-source entries and no
project-step read errors).

* test(workflows): assert bundled defaults surface when cwd is null

The second test in the null-cwd discovery group only verified that
project-source workflows are absent. That assertion would still pass
if the bundled-defaults loader silently regressed.

Add an explicit `bundled` source-label assertion so the test catches
that regression directly.

* fix(workflows): address review on coleam00#1618

- api.md: document cwd-omitted behavior so the empty-state case is discoverable
- workflow-discovery.ts: docstring explains loadDefaults default rather than just naming the skipped branch
- api.workflows.test.ts: mockDiscoverWorkflows accepts string | null to match the wider signature
- api.ts: drop trailing period inside the multi-line inline comment
- CHANGELOG.md: add the coleam00#1173 Fixed entry under [Unreleased]
- loader.test.ts: add a regression test that asserts loadConfig is not invoked when cwd is null

* test(workflows): tighten null-cwd assertions + drop rot-prone refs

Address Wirasm's polish review on coleam00#1618:

- loader.test.ts: assert result.workflows.length === 0 in the
  loadDefaults:false case so the test no longer passes if bundled
  defaults are accidentally loaded.
- loader.test.ts: drop the inline (issue coleam00#1173) reference and the
  workflow-discovery.ts file+line pointer from the two comments
  that risk rotting on future refactor.
- api.workflows.test.ts: drop the inline (issue coleam00#1173) reference.
- CHANGELOG: append positive framing to the coleam00#1173 line so the
  entry reads as "what works now" not just "what no longer breaks".
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.

Workflows page shows false empty state when no project/cwd is selected

2 participants