New:Socket for Asana Is Now Available.Learn more
Get Started

gatecraft

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gatecraft - npm Package Compare versions

Comparing version
1.0.0
to
1.0.1
+1
-1
package.json
{
"name": "gatecraft",
"version": "1.0.0",
"version": "1.0.1",
"description": "The AI Engineering Operating System — install a complete engineering loop, quality gates, and 26 specialist roles into any repository. Hidden, gitignored, zero dependencies.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -29,2 +29,41 @@ # CHANGELOG.md — History of the Gatecraft

## [1.0.1] — 2026-08-05
Two fixes to `--share` mode, the option that lets a team commit project knowledge
while keeping the framework kernel out of git. Both were found by installing
gatecraft into gatecraft.
**What you must do.** If you installed with `--share` on 1.0.0, run
`npx gatecraft@latest doctor` and check what it now says. If your `.gitignore`
already excluded `.ai/` before you installed, your project memory was never
actually being committed — the install said it was. Remove that rule and commit
`.ai/PROJECT_CONTEXT.md`, `.ai/DECISIONS.md`, and `.ai/memory/` to start sharing
them for real. If you followed the earlier `git rm -r --cached .ai` advice from
`doctor`, check whether that commit removed shared files your teammates needed.
### Fixed
- `gatecraft doctor` treated a `--share` install as if it were hidden. It reported
every shared project file as accidentally committed and advised
`git rm -r --cached .ai` — a command that untracks precisely the files `--share`
exists to share, deleting them for every teammate on the next commit. The advice
was the defect. `doctor` now distinguishes project-owned files from
framework-owned ones and reports only genuinely leaked framework files, naming
them individually rather than by wildcard.
- `gatecraft init --share` reported `project memory shared` whether or not the
share worked. Git will not re-include a file inside an excluded directory, so a
pre-existing `.ai/` or `/.ai/` rule in `.gitignore` makes every negation the
installer writes inert. The install would claim success while committing nothing,
and a team could discover months later that no context had ever been shared.
`init` now detects the conflicting rule, reports its line number and text, and
states plainly that project memory is not shared.
### Changed
- Share-mode tests now assert what `git` would actually commit rather than that the
`.gitignore` contains a negation. The previous test passed against both bugs.
---
## [1.0.0] — 2026-08-04

@@ -31,0 +70,0 @@

@@ -367,1 +367,82 @@ # DECISIONS.md — Architecture Decision Records

whether the documents drifted, and which sections were never read.)*
---
## ADR-0002: Share mode commits project knowledge, hides the framework kernel
**Date:** 2026-08-05
**Status:** Accepted
**Deciders:** CTO, System Architect
**Tags:** git, collaboration, installation
### Context and Problem
A developer installs gatecraft with `--yes`, filling in PROJECT_CONTEXT.md and recording
decisions in `.ai/DECISIONS.md` and `.ai/memory/`. A teammate clones the repository
and gets AGENTS.md pointing at `.ai/` — which is not there, because the default `--hidden`
mode gitignores the entire directory. Running `init` gives them a fresh empty framework,
not the one carrying the first developer's work.
The framework ships 16,338 lines across 35 files. Of those, 13,477 lines (13 files) are
framework-owned — SYSTEM.md, KNOWLEDGE.md, PROMPTS.md, the shipped kernel that does
not change per project. The other 2,861 lines (22 files) are project-owned — context,
decisions, memory, and working directories that *do* accumulate project-specific facts.
A team needs the project half shared and the framework half local. Committing all of
`.ai/` bloats every diff with 13k lines of stable prose; hiding all of it loses the
decisions and memory the first developer invested.
### Decision
Add `--share` mode alongside the existing `--hidden` default. Share mode writes a
selective `.gitignore` block:
```gitignore
.ai/*
!.ai/PROJECT_CONTEXT.md
!.ai/DECISIONS.md
!.ai/memory/
!.ai/architecture/
!.ai/.gatecraft-manifest.json
```
The framework-owned files stay out of git; the project-owned files and the manifest are
committed. A teammate cloning the repo gets the shared context and can run
`gatecraft doctor --fix` to restore the 13 missing framework files without overwriting
the 13 project files that travelled.
### Consequences
**Positive:**
- Context and decisions propagate to the team on clone, not lost to each developer's local `.ai/`.
- Diffs stay clean — the 13k-line kernel is never committed.
- Version skew is detectable: the manifest records the framework version, so `status`
can warn a teammate if their local CLI is ahead or behind.
**Negative:**
- A pre-existing `.ai/` or `/.ai/` rule in `.gitignore` silently defeats every negation
(git cannot re-include a file inside an excluded directory). `init --share` now checks
for this conflict and warns loudly rather than falsely claiming success.
- The manifest is now committed, which exposes the framework version and installation
timestamp to the repository. Not sensitive, but visible.
### Alternatives Considered
1. **Commit nothing (status quo before this ADR).** Simple, but loses all project
knowledge on clone.
2. **Commit everything.** Also simple, but 13k lines in every diff is untenable.
3. **Add `gatecraft sync` to push/pull shared content to a backend.** Adds a dependency
and a new failure mode; rejected for v1.
4. **Treat `.ai/` like `.vscode/` — personal notes only.** Makes AGENTS.md a lie (it
claims the framework is shared), and forces every developer to re-fill context
independently.
### Revisit Triggers
- A team reports that shared memory drifted from the codebase and became stale faster
than local memory would have.
- Version skew (different CLI versions across a team) causes a manifest conflict that
blocks a pull request.
- Six months: measure whether filled-in context actually reduces the "agent guessed
wrong about the stack" error class.
# AI Engineering Operating System (Gatecraft)
Version 1.0.0 — see [VERSION.md](VERSION.md) and [CHANGELOG.md](CHANGELOG.md).
Version 1.0.1 — see [VERSION.md](VERSION.md) and [CHANGELOG.md](CHANGELOG.md).

@@ -5,0 +5,0 @@ The Gatecraft is a technology-agnostic operating system for AI coding agents and the

# VERSION.md — Versioning and Compatibility
**Current version: 1.0.0**
**Current version: 1.0.1**

@@ -150,2 +150,3 @@ This file governs the version of the AI Engineering Operating System itself — the

| 1.0.0 | 15 | 12 | Twelve-stage loop; ten scoring dimensions; 90/100 threshold; Security veto | Initial release |
| 1.0.1 | 15 | 12 | Unchanged | Installer fixes only. No document, directory, or kernel change; no override can be affected. |

@@ -152,0 +153,0 @@ Record each release here. The columns are the things an override can depend on, so a

@@ -130,9 +130,35 @@ 'use strict';

// 5. Accidentally committed.
//
// In share mode, tracked project files are the entire point — context,
// decisions, and memory are committed so a teammate gets them on clone. Only
// the framework half is meant to stay out of git, so this warns on that half
// alone. Warning on everything would be worse than noise here: the suggested
// `git rm -r --cached .ai` would untrack exactly the files the mode exists to
// share, and the next `git commit` would delete them for everyone else.
const staged = checkGitStaged(root);
if (shouldHide && staged && staged.length) {
add(
'warn',
`${staged.length} file(s) under .ai/ are tracked by git despite being installed hidden`,
'git rm -r --cached .ai # then commit'
);
const offenders =
m.mode === 'share'
? staged.filter((f) => {
const rel = f.replace(/^\.ai\//, '');
// The manifest is shared deliberately: it is what tells a teammate's
// CLI that an install already exists here. It is not PROJECT_OWNED
// (that list governs what upgrade refuses to overwrite, and the
// manifest is our bookkeeping, not the user's document), so it needs
// naming separately rather than reclassifying and changing upgrade.
if (rel === '.gatecraft-manifest.json') return false;
return !payload.isProjectOwned(rel);
})
: staged;
if (offenders.length) {
add(
'warn',
m.mode === 'share'
? `${offenders.length} framework file(s) under .ai/ are tracked by git — only project files are meant to be shared`
: `${offenders.length} file(s) under .ai/ are tracked by git despite being installed hidden`,
m.mode === 'share'
? `git rm --cached ${offenders.slice(0, 3).join(' ')} # then commit`
: 'git rm -r --cached .ai # then commit'
);
}
}

@@ -139,0 +165,0 @@

@@ -186,3 +186,17 @@ 'use strict';

m.gitignore.mode = mode;
if (mode === 'share') ui.ok('.gitignore — framework hidden, project memory shared');
if (mode === 'share') {
// Only claim the share worked if git will honour it. An existing rule
// that excludes the whole directory makes every negation we just wrote
// inert, and reporting success anyway is how a team discovers months
// later that none of their context was ever committed.
const conflict = gitignore.conflictingRule(root);
if (conflict) {
ui.warn('.gitignore — framework hidden, but project memory is NOT shared');
ui.note(`line ${conflict.line} (${conflict.text}) excludes all of .ai/`);
ui.note('git cannot re-include a file inside an excluded directory');
ui.note(`remove that line to share project memory as --share intends`);
} else {
ui.ok('.gitignore — framework hidden, project memory shared');
}
}
else ui.ok(`.gitignore — ${r.created ? 'created, ' : ''}.ai/ hidden from git`);

@@ -189,0 +203,0 @@ } else {

@@ -83,2 +83,39 @@ 'use strict';

module.exports = { BEGIN, END, ensure, remove, isIgnored, findBlock };
/**
* Find a rule *outside* our block that excludes the whole `.ai/` directory.
*
* This matters only for share mode, and it matters absolutely. Git will not
* re-include a file inside an excluded directory: once `.ai/` itself is
* excluded, `!.ai/DECISIONS.md` is dead text. So a user who already had `.ai/`
* in their .gitignore gets a `--share` install whose every negation is inert,
* shares nothing, and says nothing about it — the failure this project is
* supposed to prevent, arriving silently. gatecraft's own repository has such a
* line, which is how this was found.
*
* Returns { line, text } for reporting, or null when there is no conflict.
*/
function conflictingRule(root) {
const p = paths(root).gitignore;
if (!fsx.exists(p)) return null;
const text = fsx.read(p);
const found = findBlock(text);
return (
fsx
.lines(text)
.map((raw, i) => ({ raw, i }))
.filter(({ raw, i }) => {
if (!found) return true;
// Offsets are cheaper to compare than re-parsing: skip our own lines.
const at = fsx.lines(text).slice(0, i).join('\n').length;
return at < found.start || at >= found.end;
})
.map(({ raw, i }) => ({ t: raw.trim(), line: i + 1, raw }))
// A directory exclusion, not a single-file one. `.ai/**` and `.ai/*` also
// exclude the directory contents wholesale, so they belong here too.
.filter(({ t }) => ['.ai', '.ai/', '/.ai', '/.ai/', '.ai/*', '.ai/**', '/.ai/*', '/.ai/**'].includes(t))
.map(({ line, raw }) => ({ line, text: raw.trim() }))[0] || null
);
}
module.exports = { BEGIN, END, ensure, remove, isIgnored, findBlock, conflictingRule };