ArchSpine Git Artifact Strategy
This document defines how ArchSpine should treat .spine/ artifacts in a host repository, and how spine init should shape the default Git experience.
Problem
The current product surface is inconsistent:
- repository root
.gitignoreignores local runtime state - repository root
.gitattributesmarks generated snapshot files as generated examples/demo-project/.gitignoreignores almost the entire.spine/treespine publishdescribes.spine/index/**and.spine/atlas/**as distributable snapshot outputsspine initcurrently manages.ignore, but not.gitignoreor.gitattributes
That creates a product ambiguity: is .spine/ a local cache, a committed governance layer, or a distributable repository artifact?
Product Goal
The goal is to make ArchSpine onboarding clean without collapsing the distribution model.
The default user experience should achieve all of the following:
- first-time
spine initshould not create noisy Git churn - users should understand which
.spinefiles are project assets versus local runtime state - teams should be able to commit distributable semantic snapshots without review noise
init,publish, docs, and demo projects should express one consistent model
The product recommendation is now:
Distributable snapshotfor the default, team-oriented pathLocal-firstas the lighter opt-out path for personal or experimental use
User Needs
1. Local adopters
Primary need:
- get value quickly without polluting the repo
Expected default:
- local runtime noise stays out of Git
- if the user wants a lighter footprint, they can opt into
local
2. Team maintainers
Primary need:
- integrate ArchSpine into a real repository workflow
Expected default:
- governance inputs are committed
- generated outputs have explicit Git semantics
- review remains readable
3. Distribution owners
Primary need:
- publish and review semantic snapshot outputs as repository assets
Expected default:
- distributable outputs can live in Git
- generated outputs are marked as generated in review tools
- local runtime state remains excluded
Artifact Model
ArchSpine should formally divide .spine/ outputs into three classes.
1. Control-plane artifacts
Examples:
.spine/config.json.spine/rules/**
Properties:
- human-authored or human-reviewed
- should be committed
- should remain normal review targets
2. Local runtime state
Examples:
.spine/cache.db*.spine/.lock.spine/protected-output-baseline.json- future machine-local cache or lock files
Properties:
- local execution support only
- should not be committed by default
- should be managed by
.gitignore
3. Distributable snapshot artifacts
Examples:
.spine/index/**.spine/atlas/**.spine/manifest.json.spine/languages.json.spine/diagnostics/**when kept as generated outputs
Properties:
- generated by ArchSpine
- may be committed as repository distribution assets
- should be marked as generated in review tooling
- should not be silently forced out of Git by default
Product Decision
ArchSpine will treat .spine/ as a repository control plane plus managed generated outputs, not as a pure local cache directory.
That leads to the following default decisions:
spine initshould manage.gitignorespine initshould manage.gitattributes.gitignoreshould cover local runtime state only.gitattributesshould mark distributable snapshot artifacts as generatedspine initshould not, by default, ignore.spine/index/**or.spine/atlas/**spine publishremains the refresh path for distributable snapshot artifacts
Why Not Ignore All of .spine/
Ignoring most of .spine/ during init would solve short-term local noise, but it would also implicitly redefine product semantics:
- users would infer that generated snapshot artifacts are not repository assets
publishwould continue describing those same artifacts as distributable outputs- demo projects, docs, and Git behavior would continue to disagree
This is a product contradiction, not a small UX issue.
init Default Experience
spine init should optimize for onboarding, but without breaking the distribution model.
Default behavior:
- recommend
Distributable snapshotin the interactive artifact strategy picker - create or update a managed ArchSpine block in
.gitignore - create or update a managed ArchSpine block in
.gitattributes - continue managing
.ignore - leave user-owned file content outside the managed blocks untouched
The default should be described as:
- keep local runtime state out of Git
- keep distributable semantic snapshots review-friendly
Managed File Strategy
Managed file updates should use bounded blocks instead of full-file replacement.
Requirements:
- if the file does not exist, create it
- if a managed block exists, update only that block
- if the file contains unrelated user content, preserve it and append the managed block
- uninit or cleanup flows should remove only the managed block
Proposed Managed Entries
.gitignore
Recommended managed entries:
# >>> ArchSpine managed >>>
.spine/cache.db*
.spine/.lock
.spine/protected-output-baseline.json
.spineignore.local
# <<< ArchSpine managed <<<Rationale:
- these are local runtime or local-only override artifacts
- excluding them improves default repo hygiene
- excluding them does not conflict with
publish
.gitattributes
Recommended managed entries:
# >>> ArchSpine managed >>>
.spine/index/** linguist-generated=true
.spine/atlas/** linguist-generated=true
.spine/manifest.json linguist-generated=true
.spine/languages.json linguist-generated=true
.spine/diagnostics/** linguist-generated=true
# <<< ArchSpine managed <<<Rationale:
- these are generated outputs
- generated classification improves GitHub review experience
- generated classification preserves commit-ability without hiding repository assets
Non-Goals
This proposal does not do the following:
- redefine scan policy
- make
.spine/index/**or.spine/atlas/**local-only artifacts - require every repository to commit distributable snapshots immediately
- introduce a multi-mode init flow in the first implementation step
Future Extension
If later needed, ArchSpine may expose an explicit artifact strategy mode such as:
localdistributable
But the first implementation should not block on mode design. The immediate requirement is to make the default semantics internally consistent.
Execution Plan
Phase 1. Product contract alignment
Produce and approve this model as the canonical decision:
- three artifact classes
.gitignorefor local runtime state.gitattributesfor generated distributable artifactspublishremains the distributable refresh path
Phase 2. Product surface alignment
Update product-facing references so they express the same model:
- root defaults
- demo project defaults
inithelp text and onboarding language- docs that describe Git behavior and publish semantics
Phase 3. Implementation
Add managed sync utilities similar to current .ignore and agent-instruction sync:
syncGitIgnoreFileremoveManagedGitIgnoreFilesyncGitAttributesFileremoveManagedGitAttributesFile
Integrate them into spine init and cleanup flows.
Phase 4. Verification
Add tests for:
- file creation when missing
- bounded update when managed block exists
- append-with-preservation when user content exists
- cleanup removing only managed entries
initstate tracking for managed Git files
Acceptance Criteria
The proposal is complete when all of the following are true:
spine initmanages.gitignore,.gitattributes, and.ignore- root docs, demo defaults, and CLI language all match the same artifact model
- local runtime state is excluded by default
- distributable snapshot outputs are not default-ignored
- generated snapshot outputs are marked as generated for review tooling
- user-owned content in managed files is preserved
Immediate Follow-up Work
After approving this strategy, the next concrete implementation tasks are:
- fix the demo project
.gitignoreto match the product decision - add managed sync helpers and tests
- wire them into
spine init - update docs that currently imply conflicting Git behavior