The project file introduced by _plans/025_file-organization.md is a bare root marker: markfluence.yaml in the root directory, whose existence is its whole meaning. Nothing in it is read, so nothing parses it. This issue is about the first keys.
The substance is less about which keys than about three things deferred deliberately.
The precedence chain is not the credentials chain
Worth settling before any key exists, because conflating the two is the mistake this forecloses.
Credentials resolve flag > environment > .env and answer who you are. Anything the project file holds is about what the content is, and should resolve flag > frontmatter > project file — a different chain, because a per-file answer should beat a per-project one.
So a space in markfluence.yaml is a default that frontmatter overrides, and --space overrides both. Nothing about it belongs in internal/client.Resolve, which owns the credentials chain.
A default space is the obvious first key
Use case 5 in the spec is a hundred files in one space, every one of them repeating space: ENG. That is the duplication a project file is for.
Others worth considering, none urgent: a default page_width, and a default version --message.
Not parent — that varies per file by definition.
The parser is a real cost
There is no YAML library in this module. go.yaml.in/yaml/v3 appears in go.sum only as a /go.mod hash — a module-graph entry with no zip hash — so go mod why reports "main module does not need package" and importing it fails on a missing go.sum entry. Adding it is a new direct dependency, not a promotion of an indirect one.
The alternative is a third minimal parser, after internal/frontmatter and the .env reader. internal/frontmatter cannot be reused as-is: it requires --- fences and returns an empty map without them.
Either is defensible. The point is that the first key is when this gets paid, and the .yaml extension already commits the format.
Decided: strict validation
An unrecognized key is a malformed file. This is what catches spce: ENG, which is the whole reason to validate at all — a silently ignored typo in a project-wide default is worse than one in a single file, because it is wrong everywhere at once.
A malformed file is an error naming what is malformed, and aborts immediately. It is specifically not treated as a valid root marker, and discovery does not keep walking up looking for a better one, and does not fall back to the markdown file's own directory. A project file that exists but cannot be understood means the project's boundary is unknown, and every attachment name depends on that boundary — guessing is worse than stopping.
Rejecting a file it does not understand is the point, not a cost. A
markfluence.yaml written for a newer markfluence contains keys an older binary
would ignore, and ignoring a project-wide default means publishing with the wrong
root, the wrong space, or the wrong width — silently, everywhere. Refusing is the
only safe response to a file from the future.
So the file carries no schema version and unknown keys are fatal, deliberately,
and that should not be loosened later. What should improve is the message: an
unknown key most likely means the binary is older than the project, so the error
should say so rather than only naming the key.
Related
_plans/025_file-organization.md, "The project file", for the root-marker decision and why the file is visible and tool-named.
- The same section decides that
.env is read from the discovered root, which is a separate change to the credentials path and not part of this issue.
- docs/guarantees.md — L2 (
invocation-independent) is why the root cannot be derived from the working directory or from the set of arguments, which is what makes a declared root necessary in the first place.
The project file introduced by
_plans/025_file-organization.mdis a bare root marker:markfluence.yamlin the root directory, whose existence is its whole meaning. Nothing in it is read, so nothing parses it. This issue is about the first keys.The substance is less about which keys than about three things deferred deliberately.
The precedence chain is not the credentials chain
Worth settling before any key exists, because conflating the two is the mistake this forecloses.
Credentials resolve flag > environment >
.envand answer who you are. Anything the project file holds is about what the content is, and should resolve flag > frontmatter > project file — a different chain, because a per-file answer should beat a per-project one.So a
spaceinmarkfluence.yamlis a default that frontmatter overrides, and--spaceoverrides both. Nothing about it belongs ininternal/client.Resolve, which owns the credentials chain.A default
spaceis the obvious first keyUse case 5 in the spec is a hundred files in one space, every one of them repeating
space: ENG. That is the duplication a project file is for.Others worth considering, none urgent: a default
page_width, and a default version--message.Not
parent— that varies per file by definition.The parser is a real cost
There is no YAML library in this module.
go.yaml.in/yaml/v3appears ingo.sumonly as a/go.modhash — a module-graph entry with no zip hash — sogo mod whyreports "main module does not need package" and importing it fails on a missinggo.sumentry. Adding it is a new direct dependency, not a promotion of an indirect one.The alternative is a third minimal parser, after
internal/frontmatterand the.envreader.internal/frontmattercannot be reused as-is: it requires---fences and returns an empty map without them.Either is defensible. The point is that the first key is when this gets paid, and the
.yamlextension already commits the format.Decided: strict validation
An unrecognized key is a malformed file. This is what catches
spce: ENG, which is the whole reason to validate at all — a silently ignored typo in a project-wide default is worse than one in a single file, because it is wrong everywhere at once.A malformed file is an error naming what is malformed, and aborts immediately. It is specifically not treated as a valid root marker, and discovery does not keep walking up looking for a better one, and does not fall back to the markdown file's own directory. A project file that exists but cannot be understood means the project's boundary is unknown, and every attachment name depends on that boundary — guessing is worse than stopping.
Rejecting a file it does not understand is the point, not a cost. A
markfluence.yamlwritten for a newer markfluence contains keys an older binarywould ignore, and ignoring a project-wide default means publishing with the wrong
root, the wrong space, or the wrong width — silently, everywhere. Refusing is the
only safe response to a file from the future.
So the file carries no schema version and unknown keys are fatal, deliberately,
and that should not be loosened later. What should improve is the message: an
unknown key most likely means the binary is older than the project, so the error
should say so rather than only naming the key.
Related
_plans/025_file-organization.md, "The project file", for the root-marker decision and why the file is visible and tool-named..envis read from the discovered root, which is a separate change to the credentials path and not part of this issue.invocation-independent) is why the root cannot be derived from the working directory or from the set of arguments, which is what makes a declared root necessary in the first place.