Skip to content

fix(cli): make darnit serve default to openssf-baseline - #577

Merged
Marc-cn merged 1 commit into
darnitdevorg:mainfrom
Marc-cn:fix/serve-default-framework
Oct 12, 2026
Merged

Marc-cn merged 1 commit into
darnitdevorg:mainfrom
Marc-cn:fix/serve-default-framework

Conversation

@Marc-cn

@Marc-cn Marc-cn commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

darnit serve with no --framework serves whichever installed framework sorts first by name. cmd_serve takes frameworks[0] from list_available_frameworks(), which returns a sorted list.

On a full darnit-mcp install the list is gittuf, openssf-baseline, reproducibility, so the server starts with gittuf:

$ darnit serve
INFO: Starting MCP server with framework: gittuf

darnit install registers uvx --from darnit-mcp darnit serve, with no framework. So a client set up the documented way gets the gittuf tools and no OpenSSF Baseline tools. From a source checkout with every workspace plugin, the first name is community-spec; that is how I found it reporting that only the CSL audit tool was available.

darnit audit already has a different rule: load_effective_config_auto defaults to openssf-baseline. This makes serve follow the same default:

  1. openssf-baseline, if it is installed (and allowed by the operator configuration).
  2. Otherwise the only installed framework, if there is exactly one.
  3. Otherwise an error that lists the installed frameworks and asks for --framework.

Changes: a small _default_framework helper in cli.py, the two help strings that said "auto-detect", tests, and a CHANGELOG entry.

Type of Change

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)

One case does change behavior and may deserve the "breaking" box, your call: with several frameworks installed and no baseline, serve used to pick the first by name and now exits 1 asking for --framework.

Framework Changes Checklist

  • Updated framework spec (docs/architecture/framework-design.md) if behavior changed (I did not find the serve default described there; say if it belongs)
  • Ran uv run python scripts/validate_sync.py --verbose and it passes

Testing

  • Tests pass locally (uv run pytest tests/ -v): 5144 passed, 26 skipped (main: 5138)
  • Added tests for new functionality (if applicable)
  • Linting passes (uv run ruff check .)

Six test cases in tests/darnit/test_cli.py: four for the helper, and two that run main(["serve"]) with a fake framework list and a fake server. The two serve tests fail without the fix. Nothing tested the default before.

By hand, starting the real server with stdin closed:

Install Before After
The five darnit-mcp wheels in a clean venv gittuf not re-run on wheels; covered by the unit test with the same list
Workspace, eight frameworks community-spec (seen in Claude Code) openssf-baseline

AI assistance

  • No AI assistance was used
  • AI assistance was used

Claude Fable 5.1 wrote the helper, the tests and the help-text changes, and drafted this description. I ran every command and checked the results myself. The commit carries an Assisted-by: Claude:claude-fable-5-1 trailer.

Additional Notes

  • I have not installed the 0.1.0 that is on PyPI, so I do not know which framework it serves. The claim above is about anything built from current main.
  • feat(cli): add darnit install --from-source #571 registers serve --framework openssf-baseline for source installs and has a code comment saying serve takes the first framework it finds. Naming the framework stays correct after this PR; the comment should be updated in whichever of the two merges second.

mlieberman85
mlieberman85 previously approved these changes Oct 12, 2026

@mlieberman85 mlieberman85 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.

Thanks, confirmed: built darnit-mcp wheels served gittuf on main and serve openssf-baseline with this PR, and the "several installed" refusal works with plugins.allowed.

  1. darnit install still writes uvx --from darnit-mcp darnit serve with no framework (cli.py:694). uvx runs the PyPI release, and 0.1.x still takes frameworks[0], so clients set up the documented way get gittuf until the next release. Could you add "--framework", "openssf-baseline" there (as #571 does for --from-source)? Then W-31 is fixed regardless of version. Happy for it to go in #571 instead if that lands first.
  2. Small: cmd_serve's docstring and the "Legacy mode: Auto-detect" comment are stale; could DEFAULT_FRAMEWORK be shared with load_effective_config_auto so the two defaults can't drift; and the error could say "installed and allowed" when plugins.allowed narrowed the list.

Drafted with Claude Code; reviewed and posted by me.

With no --framework, cmd_serve took the first name from a sorted list of installed frameworks. On a full darnit-mcp install that is gittuf, so the MCP entry darnit install writes (uvx --from darnit-mcp darnit serve) gave clients the gittuf tools.

Use the same default as darnit audit: openssf-baseline when it is installed, otherwise the only installed framework. With several installed and no baseline, exit with an error that asks for --framework.

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Assisted-by: Claude:claude-fable-5-1
@Marc-cn

Marc-cn commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased onto main after #582 merged. The only conflict was the CHANGELOG entry, and nothing else changed. Merging on your approval once CI is green. Your point 1 (plain darnit install passing --framework) goes into #571, and the small ones into a follow-up.

@Marc-cn
Marc-cn force-pushed the fix/serve-default-framework branch from 85e3d38 to 2f57c58 Compare October 12, 2026 20:30
@Marc-cn
Marc-cn merged commit a6de502 into darnitdevorg:main Oct 12, 2026
9 checks passed
Marc-cn added a commit to Marc-cn/darnit that referenced this pull request Oct 13, 2026
Review on darnitdevorg#577: the uvx entry runs the darnit-mcp release on PyPI, and
releases before 0.2.0 serve the first installed framework by name. Pass
--framework openssf-baseline there as well, so clients set up the
documented way get the Baseline tools whatever version uvx resolves.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
@Marc-cn Marc-cn mentioned this pull request Oct 13, 2026
6 of 12 tasks
Marc-cn added a commit to Marc-cn/darnit that referenced this pull request Oct 17, 2026
Review on darnitdevorg#577: the uvx entry runs the darnit-mcp release on PyPI, and
releases before 0.2.0 serve the first installed framework by name. Pass
--framework openssf-baseline there as well, so clients set up the
documented way get the Baseline tools whatever version uvx resolves.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Marc-cn added a commit that referenced this pull request Oct 20, 2026
* feat(cli): add darnit install --from-source

darnit install always registers 'uvx --from darnit-mcp darnit serve' as the MCP server command. From a source checkout that runs the PyPI package, not the code that was installed.

--from-source registers the darnit executable of the running installation instead: the console script next to the running interpreter, falling back to darnit on PATH. The default entry is unchanged.

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Assisted-by: Claude:claude-fable-5-1

* fix(cli): name the framework in the --from-source entry

A source checkout installs every workspace plugin, and darnit serve without --framework takes the first one it finds (community-spec). Claude Code then connected to a server that had no OpenSSF Baseline tools.

Register 'serve --framework openssf-baseline', the same arguments as the manual command in docs/install/from-source.md. Found by running the registered server from Claude Code.

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Assisted-by: Claude:claude-fable-5-1

* fix(cli): name the framework in the uvx entry too

Review on #577: the uvx entry runs the darnit-mcp release on PyPI, and
releases before 0.2.0 serve the first installed framework by name. Pass
--framework openssf-baseline there as well, so clients set up the
documented way get the Baseline tools whatever version uvx resolves.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>

* fix(cli): resolve the --from-source command before writing anything

Review on #571.

- The executable lookup runs before the settings path is prepared, so a
  failed lookup creates no client directory and no .bak of an existing
  settings file. The registered command is logged.
- from-source.md no longer recommends --project with --from-source: it
  writes the absolute path of the checkout venv into .mcp.json.
- CHANGELOG: the uvx --framework change is under Fixed; the comment and
  the entry no longer quote the old uvx line.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>

---------

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
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.

2 participants