Projects

A Sec project is the complete source tree governed by one project manifest:

.sec/sec.toml

The project defines the buildable products, reusable platform variants, compiler defaults, compile-time parameters, output rules and project-wide tooling settings for that source tree.

Source modules are discovered from the directory tree and imports. They do not need to be repeated as a manually maintained module list in the manifest.

Core rule: A Sec project has one project boundary, one .sec/sec.toml manifest and any number of logical build targets inside that project.

Project Terminology

Term Meaning
Project The complete source tree governed by one .sec/sec.toml
Module One source directory and its shared Sec namespace
Target One logical buildable product
Variant One concrete platform/build configuration for a target
Artifact A file produced by one target variant
Compilation plan The fully resolved target + variant build configuration used by the compiler

These concepts are deliberately separate. A module is not a project, and a target is not an operating-system/architecture pair.

Project Boundary

The directory containing .sec/sec.toml is the project root.

shop/
    .sec/
        sec.toml

    cmd/
    internal/
    domain/
    bin/

The manifest governs the complete source tree below that root.

Applications, command-line tools, libraries, firmware images and other independently buildable products are represented as targets inside the same project.

Sec does not use a separate manifest for every source module.

The Project Manifest

The canonical project manifest is:

.sec/sec.toml

It describes project-level build information such as:

  • project identity;
  • default build behavior;
  • profiles;
  • reusable variants;
  • logical targets;
  • compiler options;
  • compile-time parameters;
  • analysis/tooling settings;
  • build-counter configuration;
  • dependencies when the dependency model is implemented.
Important: The manifest describes buildable products and project configuration. It should not duplicate the complete source-module tree.

One Manifest per Project

A project contains exactly one .sec/sec.toml. Nested Sec projects are not supported.

This is invalid:

project/
    .sec/sec.toml

    server/
        .sec/sec.toml

    worker/
        .sec/sec.toml

server and worker should instead be represented as targets in the root project manifest.

The single-manifest rule gives project-wide tooling one coherent view of:

  • imports and dependency resolution;
  • target and variant selection;
  • formatting;
  • diagnostics;
  • ownership and whole-project analysis;
  • call graphs;
  • stack and allocation analysis;
  • build caching;
  • platform selection.

Project Discovery

Project-aware tools search the current directory and parent directories for:

.sec/sec.toml

The nearest valid containing project manifest defines the active project.

This lets commands such as sec init run from a directory inside the project without creating a second nested project.

Source Discovery

Ordinary source modules are discovered through directory structure and import reachability.

A target names its entry module:

[target.shop]
kind = "command"
source = "cmd/shop"

The complete source graph is then derived by following imports.

The manifest does not require a list such as:

# Not required:
modules = [
    "domain/orders",
    "domain/products",
    "storage/database",
]

Module discovery remains part of the module/import model described in the previous chapter.

Project-Root Source Files

Sec source files may exist directly in the project root. This is useful for small projects and root libraries.

codec/
    .sec/
        sec.toml

    codec.sec
    encoder.sec

    internal/
        parser/
            parser.sec

Root-level .sec files form one root module.

For a root library module, the expected module name is:

  1. project.module when explicitly declared in the manifest;
  2. otherwise project.name when the project name is a valid Sec identifier.
[project]
name = "codec"

Root files then use:

module codec

If the project name is not a valid Sec identifier, declare the source module name explicitly:

[project]
name = "inventory-service"
module = "inventory"

Root source files then declare:

module inventory

A minimal command project may instead use the project root itself as an entry module:

module main

with:

[target.app]
kind = "command"
source = "."

One directory cannot simultaneously be both module main and a differently named root library module.

Reserved and Recognized Directories

The project-root names reserved by Sec are:

cmd
bin
.sec

internal is recognized and carries mandatory access semantics when used, but using it is optional.

Other organizational directory names normally have no special language meaning.

cmd

cmd is the canonical source root for executable and firmware entry targets.

cmd/
    shop/
        main.sec

    worker/
        main.sec

Rules:

  • .sec files may not exist directly in cmd/;
  • each target is placed in a child directory;
  • a command or firmware entry module normally declares module main;
  • reusable code should live outside the entry module;
  • entry modules should primarily configure and connect reusable modules.

This is invalid:

cmd/shared.sec

bin

bin is reserved for generated build output.

Rules:

  • bin is never a source module;
  • imports from bin/... are invalid;
  • .sec source below bin is invalid project source;
  • sec clean may remove compiler-owned output below bin;
  • unknown user files must not be removed merely because they happen to be below bin unless compiler ownership is recorded.

.sec

.sec is compiler and project metadata storage.

.sec/
    sec.toml
    state/
    cache/

Source modules must not be declared below .sec.

Mutable compiler-owned state belongs below this directory rather than being written back into source files or the declarative manifest unless the manifest itself is intentionally edited.

internal

internal is an optional but recognized access-control marker.

Its restrictions are mandatory whenever the path segment is used.

internal/
    storage/
        storage.sec

The source module still declares:

module storage

.sec files may not be placed directly in an internal marker directory:

internal/helper.sec    // invalid

Use a child module directory:

internal/
    helper/
        helper.sec

Import accessibility follows the subtree rule documented in Modules and Imports.

Ordinary Organizational Directories

Names such as these have no special language semantics:

modules
domain
application
app
services
features
components
adapters
infrastructure

Projects may use them freely.

In particular, a directory named modules is not required and is not treated specially by the compiler.

Project Identity

The manifest's [project] section defines project identity information.

A simple root-library project may use:

[project]
name = "codec"

When the project name cannot itself be a Sec module identifier, provide an explicit root module name:

[project]
name = "inventory-service"
module = "inventory"

Project identity is stable project metadata. Project tools such as sec init must preserve the existing project identity, project UUID and project name rather than silently replacing them.

The exact project-identity fields supported by the manifest are compiler-versioned. Unknown required fields must not be invented by tools.

Analysis Settings

Project-wide analysis/tooling settings live under:

[analysis]

The current closure-analysis setting includes:

[analysis]
lsp_depth = "interactive"

Such settings control tooling resource use and optional precision.

They do not redefine language semantics and do not disable safety analysis required for program correctness.

Targets

A target is one logical buildable product.

Targets are declared under:

[target.<name>]

Example:

[target.shop]
kind = "command"
source = "cmd/shop"
artifact = "shop"
variants = [
    "linux-amd64",
    "macos-arm64",
    "windows-amd64",
]

A target owns:

  • logical product identity;
  • entry module;
  • target kind;
  • artifact base name;
  • selected variants;
  • target-specific compiler options;
  • target-specific compile-time parameters;
  • build-counter behavior.
Rule: A target is a product, not a platform tuple. The same target may produce several platform-specific artifacts.

Target Kinds

The initial target kinds are:

command
library
firmware
test

The target kind describes what logical product is being built.

The test target kind is for an explicitly buildable test-oriented target or artifact. Ordinary source-level tests and sec test do not require a manifest test target.

Target Source

The target source identifies the entry module.

[target.worker]
kind = "command"
source = "cmd/worker"

The full source graph is discovered by following imports from that entry.

The source path and target kind do not vary by platform variant.

If two outputs require different entry modules or represent different logical products, declare separate targets.

Test Compilation

sec test creates a dedicated TestCompilationPlan.

It is not implemented by taking a production build and casually appending test files.

Production builds exclude:

  • *_test.sec files;
  • the project-root tests/ tree.

A test compilation may include:

  • ordinary production sources;
  • same-directory *_test.sec white-box tests;
  • tests/ integration/black-box modules;
  • test-only dependencies;
  • compiler-known testing support;
  • generated harness roots;
  • execution metadata.

Modules below tests/ follow ordinary module/import rules and receive no special friend visibility.

Production code may not depend on test-only declarations.

Variants

A variant is a reusable concrete platform/build configuration.

Variants are declared under:

[variant.<name>]

Examples:

[variant.linux-amd64]
os = "linux"
arch = "amd64"
abi = "gnu"

[variant.macos-arm64]
os = "macos"
arch = "arm64"

[variant.windows-amd64]
os = "windows"
arch = "amd64"
abi = "msvc"

A target chooses which declared variants belong to that logical product.

Canonical Operating-System Names

Initial canonical operating-system names include:

linux
windows
macos
freebsd
netbsd
baremetal
freertos

The source/project name for Apple's desktop operating system is macos, not darwin.

The compiler may still lower that target to an internal Darwin target triple.

Canonical Architecture Names

Initial canonical architecture names include:

amd64
arm64
arm32
riscv32

Architecture names belong to the Sec project/target model rather than being arbitrary host-toolchain strings.

Additional Variant Options

A variant may also define values such as:

cpu
features
abi
toolchain
profile

This allows one reusable variant to describe details beyond just OS and architecture.

CPU selection and feature selection become part of the concrete compilation plan and build/cache identity when they affect generated output.

Project Manifests Express Toolchain Intent

The manifest may identify a toolchain class or intent.

Machine-specific SDK paths, compiler installation paths and local filesystem locations belong in user or CI configuration rather than the portable project manifest.

This keeps the repository reproducible across developer machines and build agents.

sec build

Build a target with:

sec build shop

By default this builds every variant configured for target shop.

If the target declares:

variants = [
    "linux-amd64",
    "macos-arm64",
    "windows-amd64",
]

one build invocation attempts all three configured outputs.

Build Filters

A build invocation can select a subset of already configured variants:

sec build shop --variant linux-amd64
sec build shop --os linux
sec build shop --arch amd64
sec build shop --profile debug

Filters select configured variants.

Rule: A command-line filter does not silently create an undeclared variant.

Command-line overrides affect only that invocation and do not rewrite the manifest.

Multi-Variant Build Results

By default the compiler should attempt every selected variant and report an aggregate result.

A --fail-fast option may stop the build after the first failed variant.

The complete command exits unsuccessfully when any requested variant fails.

Diagnostics should identify which target/variant failed:

error[shop/windows-amd64]: platform operation OpenFile is unavailable

Compilation Plans

Every selected target + variant pair produces one concrete compilation plan.

Conceptually:

CompilationPlan {
    Project
    Target
    Variant
    SourceGraph
    OS
    Architecture
    ABI
    CPU
    CPUFeatures
    Profile
    CompilerOptions
    CompileTimeParameters
    BuildNumber
    OutputDirectory
    LinkConfiguration
}

The compilation plan is the resolved immutable build description consumed by later semantic, lowering and linking stages.

Target-Specific Lowering

The compiler should reuse target-independent parsing and semantic work when safe.

Target-dependent selection and semantic completion must happen before target-specific assumptions are frozen into lowering.

Target-specific concerns include:

  • pointer width;
  • alignment;
  • data layout;
  • ABI;
  • calling convention;
  • symbol naming;
  • object format;
  • platform imports;
  • syscalls;
  • linker behavior;
  • CPU instructions and feature availability.

The preferred pipeline is conceptually:

Source
    -> AST
    -> target-independent semantic representation where possible
    -> variant-specific semantic completion and source selection
    -> MLIR/LLVM lowering
    -> target object format
    -> final artifact

Project Build Options

Compiler behavior may be configured under project build settings:

[build]
backend = "mlir"
profile = "release"
warnings = "default"
bounds_checks = true
overflow_checks = true

Compiler options may include categories such as:

  • backend;
  • optimization level;
  • debug information;
  • stripping;
  • LTO;
  • bounds checks;
  • overflow checks;
  • warning level;
  • warnings as errors;
  • recursion policy;
  • allocation policy;
  • stack limit;
  • minimum OS or kernel version;
  • CPU features.

The exact option set is compiler-versioned. Unknown compiler options are errors unless a manifest extension mechanism explicitly permits them.

Profiles

Profiles group reusable compiler settings:

[profile.release]
optimization = "speed"
debug = "line"
strip = true

[profile.debug]
optimization = "none"
debug = "full"
strip = false

A target or variant can select or override the applicable profile according to the configuration precedence rules.

Profiles are build configuration. They do not create a second source-language semantic model.

Compile-Time Parameters

Compile-time parameters are typed program values supplied by build configuration.

[parameters]
telemetry = false
maximum_connections = 1000
product_name = "Shop"

They are not:

  • compiler options;
  • C-style textual macros;
  • arbitrary token substitution.

The exact Sec source syntax used to access compile-time parameters is defined separately.

Compile-Time Parameter Overrides

Target-specific override:

[target.shop.parameters]
maximum_connections = 2000

Variant-specific override:

[variant.windows-amd64.parameters]
native_service = true

Target + variant-specific override:

[target.shop.variant.windows-amd64.parameters]
service_name = "ShopService"

A parameter's type is derived from its original declaration. Every override must preserve that type.

This is invalid:

[parameters]
maximum_connections = 1000

[target.shop.parameters]
maximum_connections = "many"

Compile-Time Parameters Are Not for Secrets

Compile-time parameters may become visible in:

  • generated machine code;
  • IR;
  • object files;
  • debug information;
  • build caches.

Passwords, tokens, private keys and similar secrets belong in runtime configuration or another appropriate secret-management system.

Configuration Precedence

Settings merge from least specific to most specific:

  1. compiler defaults;
  2. project build settings;
  3. selected profile;
  4. reusable variant settings;
  5. target settings;
  6. target-specific variant settings;
  7. command-line overrides.

A more specific value overrides a less specific value only when the setting type and option semantics permit the override.

Command-line overrides never modify sec.toml.

Build Output

The default output layout is:

bin/<target>/<variant>/<profile>/<artifact>

Example:

bin/
    shop/
        linux-amd64/
            release/
                shop

        macos-arm64/
            release/
                shop

        windows-amd64/
            release/
                shop.exe

Platform-appropriate filename extensions are applied by the compiler.

Output separation prevents one variant from overwriting another variant's artifact.

Artifacts

An artifact is a file produced by one target variant.

Examples include:

  • executables;
  • static libraries;
  • shared libraries;
  • object files;
  • MLIR files;
  • LLVM IR files;
  • debug-information files.

A target may define its artifact base name:

[target.shop]
artifact = "shop-server"

Automatic Build Counter

A target may enable an automatic build counter:

[target.shop.build_counter]
enabled = true
scope = "target"

The default scope is target.

A project-wide scope may be configured as:

scope = "project"

Per-target scope is recommended.

One logical target build consumes at most one build number, even when several variants are built together.

shop build 143
    linux-amd64
    macos-arm64
    windows-amd64

All successful artifacts from that logical invocation receive the same build number.

Build-Number Commit Rule

The next build number is reserved for the invocation but is committed only if every requested variant succeeds.

If any requested variant fails:

  • the candidate build number is not committed;
  • the stored counter remains unchanged;
  • the next attempt may reuse the same candidate number.

A filtered build is still a real logical build and consumes one build number on success.

Build-Counter State

The manifest defines counter behavior. The mutable counter value is not written back into sec.toml.

Compiler-owned local state lives under:

.sec/state/build-counters.toml

Example:

[counter.shop]
value = 142

Local counter state should normally be excluded from version control when local counters are used.

Parallel Builds and Counter Safety

Build-counter updates must remain correct under parallel builds.

The implementation must conceptually:

  1. lock the relevant counter;
  2. read the current committed value;
  3. reserve the next candidate value;
  4. build the selected variants;
  5. atomically commit the value only after complete success;
  6. release the lock.

State files must be updated atomically. A partially written build-counter file is not acceptable.

Explicit Build Numbers

CI or release tooling may provide a build number explicitly:

sec build shop --build-number 2841

An explicit build number:

  • is validated;
  • is used by every selected variant;
  • does not automatically advance the local counter;
  • participates in artifact and cache identity.

The initial model requires local state plus explicit CLI build numbers. Additional build-number providers may be added later.

Typed Build Metadata

The compiler should expose typed compile-time build metadata.

Conceptual values include:

build number
project version
target name
variant name
operating system
architecture
profile
source revision when available
dirty-source status when available

The exact Sec source namespace and syntax are defined separately.

Build metadata is typed data, not textual macro substitution.

Project version and build number are separate:

project version: 1.4.0
build number:    143
combined label:  1.4.0+143

The automatic build counter does not modify semantic versioning.

Timestamps Are Not Embedded by Default

Current time is not automatically embedded into every build.

Automatic timestamps reduce reproducibility and depend on local clock state.

Timestamp embedding may be added through an explicit future option rather than being an unavoidable build side effect.

Reproducible Builds

An explicit build number may participate in reproducing a previous build configuration.

Whenever the build number is embedded in an artifact, it is part of compilation/cache identity.

Rule: A reproducible build must not silently allocate a new automatic build number.

Build Cache Identity

A variant cache key must include every input that may affect generated output.

At minimum this includes:

  • compiler version;
  • project identity;
  • target identity;
  • variant identity;
  • operating system;
  • architecture;
  • ABI;
  • CPU and features;
  • selected profile;
  • compiler options;
  • compile-time parameters;
  • build number when embedded;
  • source hashes;
  • dependency hashes;
  • selected platform-module hashes;
  • target directives.

An artifact from one variant must never be reused as though it were an artifact for an incompatible variant.

Native Libraries and Link Metadata Belong to the Build Plan

Native libraries, object files, import libraries, frameworks and search paths are project/package/build metadata resolved into the active compilation plan.

FFI declarations define symbol and ABI semantics.

They do not repeat linker dependency metadata through per-function @library annotations.

This keeps foreign symbol declarations separate from target-specific linking policy.

sec init

sec init creates or extends a project safely.

Its required behavior is:

  • additive;
  • idempotent;
  • conflict-aware;
  • transactional;
  • non-destructive.

It must never:

  • overwrite an existing user file;
  • replace an existing manifest;
  • create a nested manifest inside an existing Sec project.

Creating a New Project

When no containing project exists:

sec init

creates a new project in the selected directory.

A normal application profile creates at least:

.sec/sec.toml
cmd/<project-name>/main.sec
bin/
internal/

internal is a recommended initial structure, not a requirement that all projects use that architecture.

A minimal profile may instead create:

.sec/sec.toml
main.sec

with a project-root command target.

Running sec init in an Existing Project

When the upward project search finds an existing manifest:

sec init

validates and safely extends that project rather than creating another project.

When the existing project is already complete for the requested operation, the command succeeds without changes.

Being already initialized is not itself an error.

Adding Modules

Create a normal source module with:

sec init module domain/orders

This creates:

domain/orders/orders.sec

containing:

module orders

A normal source module is not added to the manifest unless it is independently declared as a build target.

An internal module may be created with:

sec init module internal/storage

which creates:

internal/storage/storage.sec

containing:

module storage

Adding a Command Target

Create a command target with:

sec init command worker

This creates:

cmd/worker/main.sec

with an entry module such as:

module main

fn main() int {
    return 0
}

and extends the manifest additively:

[target.worker]
kind = "command"
source = "cmd/worker"
artifact = "worker"

The target may inherit the project's default variant set.

Adding Other Target Kinds

Initial forms may include:

sec init library protocol
sec init firmware controller
sec init test integration

Each command creates only the source structure and manifest entry appropriate for that target kind.

It must not create unrelated boilerplate or rewrite existing user structure.

Initialization Is Idempotent

Running the same operation repeatedly must not duplicate files or manifest sections:

sec init command worker
sec init command worker

The second invocation is a successful no-op when the existing target is compatible.

Existing Manifest Content Must Be Preserved

When .sec/sec.toml already exists, sec init must:

  • parse and validate it;
  • preserve project identity;
  • preserve project UUID;
  • preserve project name;
  • preserve comments;
  • preserve unknown sections;
  • preserve user ordering and formatting when practical;
  • add only requested missing sections or keys;
  • reject incompatible existing declarations.

Project tools must not deserialize and rewrite the complete TOML document in a way that destroys comments or user formatting.

Syntax-aware edits or precise source patches are the preferred model.

Existing Files Are Never Silently Replaced

Initialization follows this policy:

Existing state Behavior
File missing Create it
Generated file already identical No-op
Compatible user file exists Preserve it
Conflicting user file exists Report an error and change nothing

Example:

error: cmd/worker/main.sec already exists but does not define a valid command entry module

no files were changed

sec init Is Transactional

Before writing anything, the command must:

  1. discover the project;
  2. read and validate the manifest;
  3. inspect existing files;
  4. calculate the complete change plan;
  5. detect every known conflict.

If any planned operation conflicts, no operation is applied.

The tool must not create several files and directories and only then discover a later conflict that leaves the project half-modified.

Dry Run

Initialization should support:

sec init --dry-run

and equivalent dry-run behavior for initialization subcommands.

Example output:

Planned changes:

  create cmd/worker/
  create cmd/worker/main.sec
  add [target.worker] to .sec/sec.toml

No existing files will be overwritten.

Dry run computes the same conflict-aware change plan without applying it.

Project Architecture Is Not Prescribed

Sec does not require one application architecture.

A reasonable application layout might be:

cmd/
    shop/
        main.sec

internal/
    domain/
    application/
    adapters/

A library might instead use:

publicmodule/
internal/
    implementation/

The compiler should not infer business meaning from directory names such as domain, application or adapters.

The general recommendation is:

Organize modules by responsibility and reason for change.

Directory names such as utils, helpers, common, misc and shared may attract mentor-style advice when they accumulate unrelated responsibilities, but that is not a language error.

Compiler and Project Validation

Project tooling validates at least:

  • exactly one project manifest exists;
  • no nested project manifest exists;
  • source-directory module names are consistent;
  • normal module names match the source-directory component;
  • root-module declarations match manifest-defined root-module rules;
  • dotted module declarations are rejected;
  • internal is not used as a module name;
  • internal import visibility is enforced;
  • reserved directories are used correctly;
  • source files do not exist directly in cmd, bin or an internal marker directory;
  • target names are unique;
  • variant names are unique;
  • target source paths exist;
  • referenced variants exist;
  • target and variant settings are compatible;
  • compiler options are known and valid;
  • compile-time parameter override types match;
  • output paths do not collide;
  • build-counter configuration is valid;
  • counter state updates are atomic;
  • sec init changes are conflict-free before application.

Diagnostics

Project diagnostics should explain:

  • the violated project rule;
  • the relevant path or manifest section;
  • the expected structure or value;
  • a safe corrective action.

Nested project

nested Sec project manifest is not allowed

project manifest:
    project/.sec/sec.toml

nested manifest:
    project/server/.sec/sec.toml

help: declare server as a target in the root project manifest

Reserved source directory

Sec source files may not be placed directly in reserved directory `cmd`

help: create a target directory such as `cmd/server`
help: move reusable code to a normal module

Parameter type mismatch

compile-time parameter `maximum_connections` has inconsistent types

project value: int
target value:  string

Variant-specific build error

error[shop/windows-amd64]: platform operation OpenFile is unavailable

Best Practices

  • Keep one .sec/sec.toml at the project root.
  • Represent applications, tools, libraries and firmware images as targets rather than nested projects.
  • Let imports discover ordinary modules; do not mirror the entire source tree in the manifest.
  • Keep reusable code out of cmd/<target> entry modules.
  • Use reusable variants for recurring platform configurations.
  • Use target + variant combinations to generate multiple platform outputs from one logical product.
  • Keep machine-specific SDK paths out of the portable manifest.
  • Keep compile-time program parameters separate from compiler options.
  • Never put secrets in compile-time parameters.
  • Use explicit build numbers in CI/release workflows when reproducibility matters.
  • Keep generated artifacts below bin and compiler-owned mutable state below .sec.
  • Use sec init --dry-run when reviewing structural changes to an existing project.
  • Organize source modules by responsibility rather than forcing one prescribed application architecture.

Summary

  • A Sec project is the complete source tree governed by one .sec/sec.toml.
  • Nested Sec projects are not supported.
  • Applications, tools, libraries and firmware products inside one project are represented as targets.
  • A module is a source namespace; a project is the build/configuration boundary.
  • A target is one logical buildable product.
  • A variant is one concrete platform/build configuration for a target.
  • An artifact is one file produced by a target variant.
  • Ordinary source modules are discovered through directories and imports and do not require manifest entries.
  • The target source identifies the entry module; imports determine the remaining source graph.
  • Project-root .sec source files are allowed.
  • A root library module uses project.module when provided, otherwise a valid project.name.
  • A minimal root command target may use module main with source = ".".
  • cmd, bin and .sec are reserved project-root directories.
  • cmd contains child entry-target modules and cannot contain direct .sec source files.
  • bin is generated output and is never a source/import root.
  • .sec stores the manifest and compiler-owned project state/cache.
  • internal is optional but carries mandatory access semantics when present.
  • Ordinary organizational names such as domain, services and modules have no special language semantics.
  • Project tools preserve existing project identity, UUID, name, comments and compatible manifest content.
  • Project-wide analysis settings live under [analysis].
  • lsp_depth controls tooling budget/precision and does not change language safety semantics.
  • Targets are declared with [target.<name>].
  • Initial target kinds are command, library, firmware and test.
  • The target source and target kind do not change per platform variant.
  • Different entry modules or different logical products require different targets.
  • sec test uses a dedicated TestCompilationPlan.
  • Production builds exclude *_test.sec and the project-root tests/ tree.
  • Variants are declared with [variant.<name>].
  • Canonical OS names include linux, windows, macos, freebsd, netbsd, baremetal and freertos.
  • The Sec project name for macOS is macos, not darwin.
  • Canonical architecture names include amd64, arm64, arm32 and riscv32.
  • Variants may additionally specify CPU, feature, ABI, toolchain and profile intent.
  • Machine-specific SDK/toolchain paths belong in user or CI configuration rather than the portable project manifest.
  • sec build <target> builds every configured variant for that target by default.
  • Build filters select declared variants and do not create undeclared variants.
  • By default all selected variants are attempted; --fail-fast may stop on the first failure.
  • The build command fails if any requested variant fails.
  • Every target + variant pair produces one concrete CompilationPlan.
  • Target-independent semantic work should be reused when safe.
  • Target-dependent layout, ABI, platform source and lowering are completed per variant.
  • Compiler options and compile-time program parameters are separate concepts.
  • Unknown compiler options are errors unless an explicit extension mechanism permits them.
  • Profiles group reusable compiler settings.
  • Compile-time parameters are typed values, not textual preprocessor macros.
  • Target, variant and target+variant parameter overrides must preserve the original parameter type.
  • Compile-time parameters must not contain secrets.
  • Configuration precedence runs from compiler defaults through increasingly specific project/variant/target settings to command-line overrides.
  • Command-line overrides do not rewrite the manifest.
  • Default artifacts live under bin/<target>/<variant>/<profile>/<artifact>.
  • Different variants must never overwrite one another's output.
  • A target may enable an automatic build counter.
  • One logical multi-variant build receives one build number.
  • A failed multi-variant build does not commit the candidate build number.
  • Mutable build-counter state is stored outside sec.toml under .sec/state/.
  • Parallel build-counter updates must be locked and atomically committed.
  • An explicit --build-number applies to every selected variant and does not automatically advance the local counter.
  • Build metadata is typed data, not macro substitution.
  • Project version and build number are distinct values.
  • Current time is not automatically embedded into builds.
  • A reproducible build must not silently allocate a new automatic build number.
  • Build cache identity includes every input that can affect generated output.
  • Artifacts from incompatible variants must never share cache identity.
  • Native linker dependencies are build-plan metadata rather than per-FFI-function @library annotations.
  • sec init is additive, idempotent, conflict-aware, transactional and non-destructive.
  • sec init searches upward for an existing project before creating anything.
  • Running sec init inside an existing project extends or validates that project rather than creating a nested one.
  • sec init module path creates a normal module without adding it to the manifest unless it is also a target.
  • sec init command name creates an entry module and adds the corresponding target manifest section.
  • Library, firmware and test target initialization use target-kind-specific structures.
  • Repeated compatible init commands are successful no-ops.
  • Existing user files are never silently overwritten.
  • A conflicting init plan changes nothing.
  • Manifest edits preserve comments and compatible user formatting when practical.
  • sec init --dry-run reports the complete planned change set without writing it.
  • Sec does not require one application architecture.
  • The general architecture recommendation is to organize modules by responsibility and reason for change.