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
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht

## [Unreleased]

### Added

- Versioned `pasweave.json` project configuration (`--config`) covering
source, output, comment styles, visibility, project title and branding,
repository/source-link settings, discovery, compiler settings, and coverage
thresholds. Relative paths resolve from the configuration directory and
cannot escape it; unknown keys, wrong types, unsupported versions, and
invalid values are rejected with input errors (exit code 2).
- `--visibility=public|all` selects whether private declarations are
documented, and `--no-recursive` disables recursion inherited from a
configuration.
- The effective configuration is recorded in `api-model.json`
(`configuration`, `configurationSource`) and the configuration file is part
of the incremental build fingerprint.

### Documentation

- Added the [project configuration](docs/project-configuration.md) guide and
linked it from the README and documentation index.

## [0.7.0] - 2026-09-19

### Added
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,20 @@ PasWeave writes a deterministic `manifest.json` and only ever removes files it
created before. See [safe incremental builds](docs/incremental-builds.md) for
the cache key, invalidation rules, and interruption recovery.

### Reproduce a build from a committed configuration

Commit one `pasweave.json` and rebuild with a single flag; explicit
command-line values still override it:

~~~text
pasweave build --config=pasweave.json
pasweave build --config=pasweave.json --project-name "Nightly API"
~~~

See [project configuration](docs/project-configuration.md) for the schema,
precedence rules, path validation, and the effective configuration recorded in
`api-model.json`.

## 📖 Documentation

Every guide is indexed in [docs/README.md](docs/README.md). Start with
Expand All @@ -239,6 +253,7 @@ Every guide is indexed in [docs/README.md](docs/README.md). Start with
| Guide | What it covers |
|---|---|
| [Documentation index](docs/README.md) | Grouped links to every guide, ADR, and release note |
| [Project configuration](docs/project-configuration.md) | One committed `pasweave.json`, precedence, and reproducibility |
| [Documentation comments](docs/documentation-comments.md) | Comment forms, association, and directives |
| [Generated output](docs/generated-output.md) | HTML, Markdown, JSON, diagnostics, and exit codes |
| [Source discovery](docs/source-discovery.md) | Recursion, include/exclude globs, and safety |
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ page that matches your task.

| Guide | What it covers |
|---|---|
| [Project configuration](project-configuration.md) | `pasweave.json` schema, precedence, path rules, visibility policy, and reproducibility |
| [Source discovery](source-discovery.md) | Recursion, include/exclude globs, precedence, and safety |
| [Compiler-aware parsing](compiler-aware-parsing.md) | Unit/include paths, defines, targets, and precedence |
| [Lazarus projects and packages](lazarus-projects.md) | `.lpi`/`.lpk` inputs, build modes, package graphs, and diagnostics |
Expand Down
5 changes: 4 additions & 1 deletion docs/generated-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ deliberately unresolved.
When source links are configured, the top-level model records the normalized
`repositoryUrl` and `sourceLinkTemplate`. The effective branding tokens
(`projectMark`, `themeAccent`, `themeAccentAlt`, and `themeFont`) are recorded
alongside them. These fields are additive schema-v1 changes.
alongside them. `configurationSource` names the `pasweave.json` file used, and
`configuration` records the effective normalized build options (the same text
hashed into the incremental fingerprint). These fields are additive schema-v1
changes. See the [project configuration guide](project-configuration.md).

`diagnostics.json` contains the same stable diagnostic codes shown on the HTML
and Markdown indexes, ready for CI systems to consume.
Expand Down
148 changes: 148 additions & 0 deletions docs/project-configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Project configuration

A project can commit one `pasweave.json` file and reproduce a build without
restating stable options on every command line:

~~~text
pasweave build --config=pasweave.json
~~~

The file is declarative data only. It cannot run scripts, load plugins, fetch
remote resources, or expand environment variables; those stay out of scope
through `v1.0.0`.

## Precedence

Values are applied in this order, lowest first:

1. documented defaults (`comments: slash`, `visibility: public`, output
`build/docs`, failure threshold `error`);
2. the project configuration file;
3. explicit command-line options.

Command-line options therefore always win. For repeatable options
(`include`, `exclude`, `unitPaths`, `includePaths`, `defines`,
`packagePaths`), the first command-line instance replaces the configured list
rather than appending to it. `--no-recursive` overrides
`discovery.recursive: true`, and `--visibility` overrides the configured
policy.

## Paths

Every path in the file is relative to the directory containing
`pasweave.json`:

- `source` (input unit, directory, or Lazarus project/package);
- `output` (generated documentation root);
- `compiler.unitPaths`, `compiler.includePaths`, `compiler.packagePaths`.

Absolute paths and parent traversal that escapes the configuration directory
are rejected, so a committed configuration stays portable and cannot read or
write outside the project.

## Schema (version 1)

Only the listed keys are accepted at each level; unknown keys and wrong types
are errors.

~~~json
{
"version": 1,
"source": "src",
"output": "build/docs",
"comments": "slash",
"visibility": "public",
"project": {
"name": "My API",
"mark": "API",
"repositoryUrl": "https://github.com/example/project",
"sourceLinkTemplate": "blob/main/{path}#L{line}",
"theme": {
"accent": "#7c3aed",
"accent2": "#0e7490",
"font": "Avenir Next"
}
},
"discovery": {
"recursive": true,
"include": ["src/**"],
"exclude": ["generated/**", "vendor/**"]
},
"compiler": {
"unitPaths": ["packages/core/src"],
"includePaths": ["include"],
"defines": ["USE_FAST_MATH"],
"targetOs": "linux",
"targetCpu": "aarch64",
"buildMode": "Release",
"packagePaths": ["packages"]
},
"coverage": {
"minimum": 90,
"failOn": "warning"
}
}
~~~

| Key | Meaning |
|---|---|
| `version` | Required; must be `1`. |
| `source` | Input to document when no positional input is given. |
| `output` | Output root; default `build/docs`. |
| `comments` | Comment styles: `slash`, `brace`, `paren`, comma-separated, or `all`. |
| `visibility` | `public` (default) documents the public API only; `all` also documents private and strict-private declarations. |
| `project.name` | Display title; otherwise derived from the input. |
| `project.mark` | 1–4 character header mark. |
| `project.repositoryUrl` | Repository origin; must be paired with `project.sourceLinkTemplate`. |
| `project.sourceLinkTemplate` | Repository-relative template with `{path}` and `{line}`. |
| `project.theme.*` | Accent colors and body font; same validation as the CLI options. |
| `discovery.recursive` | Enables recursive discovery; `--no-recursive` overrides it. |
| `discovery.include` / `exclude` | Repeatable globs with the same rules as `--include`/`--exclude`; exclusions win. |
| `compiler.unitPaths` / `includePaths` | Search paths, validated to exist. |
| `compiler.defines` | Conditional defines; plain Pascal identifiers. |
| `compiler.targetOs` / `targetCpu` | Normalized like `--target-os`/`--target-cpu`. |
| `compiler.buildMode` | Required for `.lpi` inputs when no default mode is unique. |
| `compiler.packagePaths` | Additional Lazarus package roots. |
| `coverage.minimum` | Documentation coverage gate (`0`–`100`). |
| `coverage.failOn` | `error` (default) or `warning`. |

## Reproducibility

The effective normalized configuration is written to `api-model.json` as
`configuration`, alongside `configurationSource` (the file path, or empty when
none was used). The configuration file is also part of the incremental build
fingerprint, so editing it invalidates cached output. Combined with
`manifest.json`, a recorded build can be reproduced from the same commit,
configuration file, and command line.

## Validation and errors

Configuration problems are input errors: the CLI exits with code `2` and
prints a message naming the offending key, for example
`unknown configuration key: project.naem` or
`compiler.targetOs is not a supported FPC target: plan9`. Invalid JSON, a
missing file, an unsupported `version`, absolute paths, and escaping path
traversal are rejected the same way.

`pasweave build --help` lists `--config`, `--visibility`, and `--no-recursive`.

## Examples

Document a directory with committed sources and links:

~~~text
pasweave build --config=pasweave.json
~~~

Override the title for one run without editing the file:

~~~text
pasweave build --config=pasweave.json --project-name "Nightly API"
~~~

Document internal declarations too (the private members are rendered, and
coverage follows the same population):

~~~text
pasweave build --config=pasweave.json --visibility=all --clean
~~~
Loading
Loading