Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Bug report
description: Report a reproducible Samsarix Platform Doctor defect.
title: "bug: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: >-
Thanks for helping improve Samsarix Platform Doctor. Never include API keys,
tokens, private manifests, or other sensitive values. Report vulnerabilities
privately as described in SECURITY.md.
- type: input
id: version
attributes:
label: Samsarix version
placeholder: "0.2.0 or commit SHA"
validations:
required: true
- type: input
id: environment
attributes:
label: Environment
description: Operating system, Python version, and installation method.
placeholder: "Windows 11, Python 3.14, installed from a wheel"
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Reproduction
description: Minimal sanitized manifest and exact command needed to reproduce the issue.
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual behavior
description: Include sanitized output and the exit code.
validations:
required: true
- type: checkboxes
id: safety
attributes:
label: Safety check
options:
- label: I removed credentials, private data, and sensitive paths from this report.
required: true
- label: This is not an undisclosed security vulnerability.
required: true
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Private security report
url: mailto:support@samsarix.com?subject=Security%3A%20Samsarix%20Platform%20Doctor
about: Report unpatched vulnerabilities or sensitive security details privately.
- name: Support
url: mailto:support@samsarix.com?subject=Support%3A%20Samsarix%20Platform%20Doctor
about: Ask a question that is not suitable for a public issue.
30 changes: 30 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Feature request
description: Propose a bounded readiness check or workflow improvement.
title: "feature: "
labels: ["enhancement"]
body:
- type: textarea
id: problem
attributes:
label: Problem
description: What real developer workflow is currently difficult or unreliable?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed outcome
description: Describe the smallest complete behavior that would solve the problem.
validations:
required: true
- type: textarea
id: safety
attributes:
label: Safety and automation considerations
description: Note any command execution, network, credential, timeout, redaction, or CI implications.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
21 changes: 21 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## Summary

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use a top-level heading on the first line.

markdownlint-cli2 reports MD041 because the template starts with ## Summary. Change it to # Summary.

Proposed fix
-## Summary
+# Summary
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Summary
# Summary
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🤖 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 @.github/PULL_REQUEST_TEMPLATE.md at line 1, Update the first heading in the
pull request template from the level-two “Summary” heading to a top-level
“Summary” heading, ensuring the document’s first line satisfies markdownlint
MD041.

Source: Linters/SAST tools


Describe the user-visible outcome and why this is the smallest complete change.

## Verification

- [ ] Formatting and lint pass.
- [ ] Strict type checking passes.
- [ ] Tests and the coverage gate pass.
- [ ] Package build and metadata checks pass when packaging is affected.
- [ ] The strict repository doctor check passes.

List the exact commands and results:

## Compatibility and safety

- [ ] Manifest and JSON compatibility impacts are documented.
- [ ] No secret values, private data, or unsafe command execution were introduced.
- [ ] Documentation, examples, changelog, and productization record are current.

Note security, privacy, dependency, filesystem, network, or rollback considerations here.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ jobs:
python -m coverage run -m unittest discover -s tests
python -m coverage report

- name: Audit runtime dependencies
run: python -m pip_audit . --strict --progress-spinner off

- name: Build distributions
run: python -m build

Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,27 @@ All notable changes to Samsarix Platform Doctor are documented here.

### Added

- Manifest schema version 2 with standards-compliant PEP 440 distribution constraints.
- Read-only executable availability checks that never launch declared commands.
- Manifest schema version in successful JSON reports for contract-aware automation.

### Changed

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Merge duplicate Unreleased subsections.

The ### Added heading at Line 28 duplicates the heading at Line 7. The ### Changed heading at Line 13 also duplicates the heading at Line 37. Keep one Added and one Changed subsection under ## Unreleased, or move the older entries under a separate release heading.

Also applies to: 28-28

🤖 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 `@CHANGELOG.md` at line 13, Consolidate the duplicate Added and Changed
subsections under the Unreleased changelog section: retain one heading for each
category and move all corresponding entries beneath it, or place older entries
under their appropriate separate release heading.

Source: Linters/SAST tools


- `init` now creates version 2 manifests; version 1 manifests remain supported unchanged.
- Package version advanced to `0.2.0` and now depends on PyPA `packaging`.
- Distribution duplicate detection now follows canonical Python package-name semantics.

### Security

- Refuse non-regular manifest files before reading to avoid blocking special-file inputs.
- Convert TOML recursion and oversized numeric conversion failures into structured manifest errors.
- Bound version fields and normalize invalid installed metadata into structured component results.
- Escape terminal controls from all human-rendered dynamic output.
- Update the isolated build backend to a patched `setuptools` release and audit runtime dependencies in CI.
- Handle symbolic-link cycles consistently across Python 3.11 through 3.14.

### Added

- Local `doctor` command with human and JSON output.
- Non-overwriting `init` command and versioned TOML manifest.
- Python, installed-distribution, environment-presence, and contained-file checks.
Expand Down
4 changes: 2 additions & 2 deletions QUICK_START.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ samsarix-platform doctor
The repository manifest should finish with:

```text
Summary: 5 passed, 0 warned, 0 failed
Summary: 6 passed, 0 warned, 0 failed
Result: READY
```

Expand All @@ -36,7 +36,7 @@ samsarix-platform init
samsarix-platform doctor
```

`init` creates only a project and Python requirement. Edit `samsarix-stack.toml` to declare packages, environment variables, and files your application genuinely needs. It refuses to overwrite an existing file.
`init` creates only a project and Python requirement. Edit `samsarix-stack.toml` to declare compatible package versions, executable tools, environment variables, and files your application genuinely needs. It refuses to overwrite an existing file.

## Try the example

Expand Down
34 changes: 22 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# Samsarix Platform Doctor

Samsarix Platform Doctor is a local command-line tool from **Samsarix LLC** that checks whether a Python multi-agent project has the runtime, installed packages, configuration names, and files it declares.
Samsarix Platform Doctor is a local command-line tool from **Samsarix LLC** that checks whether a Python multi-agent project has the runtime, compatible installed packages, executable tools, configuration names, and files it declares.

It is for developers who want an actionable preflight before starting an agent application or running its CI—not another agent framework or hosted service.

> Status: `0.1.0` pre-release. The core local workflow is implemented, tested, and licensed under MPL 2.0, but the package has not been published.
> Status: `0.2.0` pre-release. The core local workflow is implemented, tested, and licensed under MPL 2.0, but the package has not been published.

## What it does

Given a versioned `samsarix-stack.toml`, `samsarix-platform doctor` checks:

- the active Python version;
- whether declared Python distributions are installed;
- whether declared Python distributions are installed at compatible PEP 440 versions;
- whether declared executable commands are available on `PATH`;
- whether declared environment variables are present;
- whether declared project-relative files or directories exist.

Expand Down Expand Up @@ -47,7 +48,7 @@ samsarix-platform doctor
Expected summary:

```text
Summary: 5 passed, 0 warned, 0 failed
Summary: 6 passed, 0 warned, 0 failed
Result: READY
```

Expand All @@ -66,7 +67,7 @@ samsarix-platform doctor
Then add the checks your project actually requires:

```toml
schema_version = 1
schema_version = 2

[project]
name = "research-agent"
Expand All @@ -75,6 +76,12 @@ requires_python = ">=3.11"
[[components]]
name = "OpenAI Python SDK"
distribution = "openai"
version = ">=1,<3"
required = true

[[executables]]
name = "Git"
command = "git"
required = true

[[environment]]
Expand Down Expand Up @@ -126,20 +133,21 @@ samsarix-platform doctor [MANIFEST] [--json] [--strict]
| `1` | A required check failed, or an optional check warned under `--strict`. |
| `2` | The command usage or manifest is invalid, unreadable, missing, or unsafe. |

### Manifest schema version 1
### Manifest schema version 2

Unknown keys and duplicate declarations are errors so misspellings do not silently weaken a check.
Manifests must be UTF-8, are limited to 1 MiB, and cannot place control/formatting characters in rendered fields.
Manifests must be regular UTF-8 files, are limited to 1 MiB, and cannot place control/formatting characters in rendered fields.

| Section | Fields | Behavior |
| --- | --- | --- |
| root | `schema_version = 1` | Required. Other versions fail explicitly. |
| root | `schema_version = 2` | Required. Version 1 remains supported; unsupported versions fail explicitly. |
| `[project]` | `name`, `requires_python` | Both required. Python constraints support `>=MAJOR.MINOR[.PATCH]`. |
| `[[components]]` | `name`, `distribution`, `required`, `description` | Checks installed distribution metadata without importing code. `required` defaults to `true`. |
| `[[components]]` | `name`, `distribution`, `version`, `required`, `description` | Checks installed distribution metadata without importing code. `version` is an optional PEP 440 specifier such as `>=1,<3`; `required` defaults to `true`. |
| `[[executables]]` | `name`, `command`, `required`, `description` | Checks whether a portable command name is discoverable on `PATH` without executing it. `required` defaults to `true`. |
| `[[environment]]` | `name`, `required`, `secret`, `description` | Checks for a nonblank process environment value. Values are never reported. Both booleans default to `true`. |
| `[[files]]` | `path`, `required`, `description` | Uses portable forward-slash paths contained by the manifest directory. `required` defaults to `true`. |

Descriptions are documentation metadata for the manifest. Version 1 intentionally does not execute commands, inspect file contents, contact endpoints, or validate package APIs.
Descriptions are documentation metadata for the manifest. Version 2 intentionally does not execute commands, inspect file contents, contact endpoints, or validate package APIs. Version 1 manifests continue to work unchanged but cannot declare version constraints or executables.

## Development

Expand All @@ -159,12 +167,13 @@ python -m mypy src tests
python -m coverage erase
python -m coverage run -m unittest discover -s tests
python -m coverage report
python -m pip_audit . --strict --progress-spinner off
python -m build
python -m twine check dist/*
samsarix-platform doctor samsarix-stack.toml --strict
```

The runtime has no third-party dependencies. `requirements-dev.txt` is tooling-only and exactly pinned for repeatable contributor and CI checks.
The runtime uses PyPA's `packaging` library for standards-compliant PEP 440 evaluation. `requirements-dev.txt` is tooling-only and exactly pinned for repeatable contributor and CI checks.

## Packaging and release

Expand All @@ -188,7 +197,8 @@ See [the architecture guide](docs/ARCHITECTURE.md) for data flow, trust boundari
- Manifest file paths reject absolute paths, `..`, Windows-only separators, resolved symlink escapes, and cyclic/unresolvable links.
- Secret values are reduced to present/not-present and never included in human or JSON output.
- The parser rejects unknown keys, wrong types, duplicates, and unsupported schema versions.
- Parsing reads at most 1 MiB and rejects terminal control/formatting characters.
- Parsing accepts only regular files, reads at most 1 MiB, and converts parser limits into concise input errors.
- Human output escapes terminal control/formatting characters from paths and installed-package metadata; JSON uses JSON escaping.
- `init` never overwrites a destination or follows an existing destination symlink.
- Checks are local, bounded by manifest size, and non-destructive.
- There is no network access, telemetry, AI provider use, or operating cost in the core tool.
Expand Down
14 changes: 8 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ This roadmap separates four gates: merge, release, publication, and flagship ado

Portfolio role: **internal infrastructure**. Use this to improve the portfolio through immutable, reviewed automation or internal deployments. It must not become a hidden runtime dependency for customer-facing products.

Current disposition: Merge as a prerelease-quality foundation after the focused merge gates pass; release remains blocked on the items below.
Current disposition: publish the repository as an MPL-2.0 open-source prerelease and merge only after the focused source, package, and hosted-CI gates pass. PyPI publication remains a separate owner-controlled milestone.

## Stabilize the productized default

- Keep the default branch buildable from a clean checkout and preserve exact-head CI evidence.
- Keep Samsarix LLC branding, package identity, license metadata, and compatibility aliases internally consistent.
- Preserve the pre-productization default under a rollback ref before merging; do not delete legacy history.
- Locally reproduced in this pass: unit tests, formatting, lint, types, 90% coverage, and package build pass.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- ROADMAP.md ---'
cat -n ROADMAP.md | sed -n '1,40p'
printf '%s\n' '--- coverage references ---'
rg -n -i --glob '!node_modules' --glob '!dist' --glob '!build' \
  'coverage|branch coverage|90%|95%' .

Repository: Deathcharge/samsarix-platform

Length of output: 5552


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- coverage configuration ---'
cat -n pyproject.toml | sed -n '55,85p'
printf '%s\n' '--- documented verification results ---'
cat -n docs/PRODUCTIZATION.md | sed -n '135,165p'
printf '%s\n' '--- release and contribution coverage requirements ---'
cat -n docs/RELEASING.md | sed -n '28,45p'
cat -n CONTRIBUTING.md | sed -n '24,55p'

Repository: Deathcharge/samsarix-platform

Length of output: 6273


Report the measured coverage correctly.

Line 16 should state 95% branch-aware total coverage. 90% is the configured coverage floor, not the measured result.

🤖 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 `@ROADMAP.md` at line 16, Update the coverage statement in ROADMAP.md to report
the measured result as 95% branch-aware total coverage, replacing the incorrect
90% value while preserving the rest of the validation summary.

- Next: adopt one real manifest consumer and treat hosted zero-runner failures as infrastructure, not product failures.
- Review priority: Diagnose pre-step hosted CI failures, adopt one real manifest consumer, and require green exact-head wheel/CLI checks before release.
- Environment contract v2 now validates PEP 440 distribution ranges and read-only executable availability while preserving schema v1 compatibility.
- Next: use public-repository Actions to establish exact-head CI, then adopt one real manifest consumer through an immutable revision.
- Review priority: green exact-head wheel/CLI checks, real consumer adoption, then package-publication provenance.

## Release candidate

Expand All @@ -25,11 +26,12 @@ Current disposition: Merge as a prerelease-quality foundation after the focused

Current hardening backlog:

- Hosted CI is red at the exact inspected SHA and gives no diagnostic steps/logs.
- Checks only presence, not component versions, executable/API compatibility, credential validity, or service reachability.
- Private-repository CI was blocked before runner startup by the account billing setting; public standard GitHub-hosted runners avoid paid Actions minutes.
- Executable checks establish safe `PATH` discovery only; they do not execute tools to probe their versions or APIs.
- Credential validity, package API compatibility, and service reachability are not checked.
- No evidenced adopter, public package, tag, release, or stable schema consumer.
- The `samsarix-platform` name still suggests a broader platform than the implemented doctor command.
- Package identity, private-repository visibility, and MPL publication authority need owner review.
- PyPI namespace ownership, trusted publishing, provenance, and first-release authority remain owner gates.

## Samsarix adoption

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Supported versions

Samsarix Platform Doctor is currently a `0.1.x` pre-release. Security fixes are
Samsarix Platform Doctor is currently a `0.2.x` pre-release. Security fixes are
made on the latest supported release line and the default branch. Older
pre-release snapshots may not receive fixes.

Expand Down
25 changes: 16 additions & 9 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ flowchart LR
C --> D["Validated immutable manifest"]
D --> E["Python check"]
D --> F["Distribution metadata checks"]
D --> G["Environment presence checks"]
D --> H["Contained file checks"]
D --> G["Executable PATH checks"]
D --> H["Environment presence checks"]
D --> L["Contained file checks"]
E --> I["Doctor report"]
F --> I
G --> I
H --> I
L --> I
I --> J["Human output or JSON"]
J --> K["Exit 0, 1, or 2"]
```
Expand All @@ -43,26 +45,31 @@ For `init`, a relative user-selected destination is joined lexically to the curr

## Manifest contract

Schema version 1 supports four inputs:
Schema version 2 supports five inputs:

- project name and minimum Python version;
- installed distribution names;
- installed distribution names and optional PEP 440 version specifiers;
- executable command names discoverable on `PATH`;
- process environment-variable names;
- project-relative file or directory paths.

The schema deliberately rejects unknown keys, duplicate identities, nonportable environment names, invalid distribution names, control/formatting characters, backslash file paths, absolute paths, `..`, and unsupported versions. Manifests must be UTF-8 and are limited to 1 MiB. This makes configuration mistakes visible, prevents terminal-output forgery, bounds parser memory, and keeps the first version easy to reason about.
The schema deliberately rejects unknown keys, duplicate identities, nonportable environment names, invalid distribution names, control/formatting characters, backslash file paths, absolute paths, `..`, and unsupported versions. Manifests must be regular UTF-8 files and are limited to 1 MiB. Parser recursion and numeric-conversion limits become structured input errors. This makes configuration mistakes visible, prevents blocking special-file reads, bounds parser memory, and keeps the contract easy to reason about.

The minimum Python constraint is intentionally limited to `>=MAJOR.MINOR[.PATCH]`. General PEP 440 range evaluation would require more policy and a runtime dependency; add it only with a schema-version decision and compatibility tests.
The minimum Python constraint remains intentionally limited to `>=MAJOR.MINOR[.PATCH]`. Component versions use PyPA's standard PEP 440 `SpecifierSet`. Version 1 manifests remain supported but reject version and executable fields so typos cannot silently weaken older contracts.

## Trust boundaries

### Manifest boundary

Treat the manifest as untrusted local input. The loader reads at most 1 MiB, schema processing is linear in the declared entries, and it performs no recursive evaluation, template expansion, deserialization hooks, or command execution.
Treat the manifest as untrusted local input. The loader opens a regular file without following a path between validation and reading, reads at most 1 MiB, and turns parser resource-limit failures into structured errors. Schema processing is linear in the declared entries and performs no recursive evaluation, template expansion, deserialization hooks, or command execution.

### Component boundary

A distribution name is passed only to `importlib.metadata.version`. The declared package is never imported, so package-level code cannot execute as a side effect of the check. Presence does not establish API compatibility or safety.
A distribution name is passed only to `importlib.metadata.version`. The declared package is never imported, so package-level code cannot execute as a side effect of the check. Version compatibility does not establish API compatibility or safety.

### Executable boundary

An executable name is passed only to `shutil.which`. Commands must be portable bare names: paths, arguments, whitespace, and shell syntax are rejected. Samsarix never launches the discovered executable.

### Environment boundary

Expand All @@ -74,7 +81,7 @@ Manifest paths use POSIX separators and must be relative. Parsing rejects lexica

### Output boundary

Reports contain project names, variable names, distribution names, installed versions, relative paths, and the absolute manifest path. These are not credential values but may still reveal project metadata. Consumers decide where JSON reports may be stored.
Reports contain project names, variable names, distribution names, installed versions, relative paths, and the absolute manifest path. Human rendering escapes control and Unicode formatting characters from every dynamic value; JSON relies on JSON escaping. These fields are not credential values but may still reveal project metadata. Consumers decide where JSON reports may be stored.

## Failure and recovery behavior

Expand Down
Loading