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
11 changes: 5 additions & 6 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ jobs:
- name: Check TypeScript
run: pnpm run build

# Placeholder for ESLint/Prettier when added
# - name: Run ESLint
# run: pnpm run lint

# - name: Check Formatting
# run: pnpm run format:check
- name: Run ESLint
run: pnpm run lint

- name: Check Formatting
run: pnpm run format:check
27 changes: 24 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,34 @@ jobs:
- name: Build
run: pnpm run build

- name: Test
run: pnpm run test
- name: Test with Coverage
run: pnpm run test:coverage

- name: Merge Coverage Reports
if: matrix.node-version == '20.x'
run: |
mkdir -p coverage
# Collect Jest lcov reports
for dir in packages/*/coverage; do
if [ -f "$dir/lcov.info" ]; then
pkg=$(basename $(dirname "$dir"))
echo "Collecting coverage from $pkg"
cat "$dir/lcov.info" >> coverage/lcov.info
fi
done
# Collect Vitest lcov reports
for dir in apps/*/coverage; do
if [ -f "$dir/lcov.info" ]; then
app=$(basename $(dirname "$dir"))
echo "Collecting coverage from app/$app"
cat "$dir/lcov.info" >> coverage/lcov.info
fi
done

- name: Upload Coverage
if: matrix.node-version == '20.x'
uses: codecov/codecov-action@v5
continue-on-error: true
with:
files: ./coverage/coverage-final.json
files: ./coverage/lcov.info
Comment on lines +42 to +68
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI merges coverage/**/lcov.info into a single coverage/lcov.info, but Vitest coverage config in this repo doesn’t specify an lcov reporter. If Vitest doesn’t emit lcov.info by default, this step will silently upload incomplete coverage. Consider either configuring Vitest coverage reporters to include lcov (recommended) or changing the merge/upload step to use a format Vitest reliably produces (e.g., coverage-final.json/JSON + a merger tool).

Copilot uses AI. Check for mistakes.
fail_ci_if_error: false
75 changes: 75 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,81 @@ describe('CachePlugin', () => {
});
```

### Coverage

Each package has a `test:coverage` script that runs tests with coverage reporting:

```bash
# Run coverage for a specific package
pnpm --filter @objectos/cache test:coverage

# Run coverage for all packages (aggregated via Turborepo)
pnpm test:coverage
```

**Coverage thresholds** are enforced per package:

| Metric | Server Packages | Frontend (apps/web) |
|------------|:--------------:|:-------------------:|
| Branches | 70% | 60% |
| Functions | 70% | 60% |
| Lines | 80% | 70% |
| Statements | 80% | 70% |

CI automatically collects coverage from all packages and uploads to Codecov.

### Snapshot Testing Guidelines

Snapshot tests capture the output of a component or function and compare it against a stored reference. Use them judiciously:

#### When to Use Snapshots

- **Serialized output**: JSON responses, generated schema, config objects
- **Error messages**: Validate that error messages remain consistent
- **Complex transformations**: Metadata transforms, template rendering output

#### When NOT to Use Snapshots

- **Random/dynamic values**: Timestamps, UUIDs, incrementing IDs — these change every run
- **Large objects**: Snapshots over ~50 lines become difficult to review in PRs
- **UI components**: Prefer behavioral tests (`getByRole`, assertions on visible text) over HTML snapshots

#### Best Practices

```typescript
// ✅ GOOD: Small, focused snapshot
it('should generate correct schema for object', () => {
const schema = generateSchema(objectMeta);
expect(schema).toMatchSnapshot();
});

// ✅ GOOD: Inline snapshot for small expected values
it('should format error message', () => {
const error = formatError({ code: 'NOT_FOUND', object: 'contacts' });
expect(error).toMatchInlineSnapshot(`"Object 'contacts' not found"`);
});

// ❌ BAD: Snapshot of a large, frequently-changing object
it('should render the entire page', () => {
const html = render(<DashboardPage />);
expect(html).toMatchSnapshot(); // Too large, hard to review
});
```

#### Updating Snapshots

When a snapshot legitimately changes (e.g., you added a field to a schema):

```bash
# Jest
pnpm --filter @objectos/graphql test -- -u

# Vitest
pnpm --filter @objectos/permissions test -- --update
```

**Always review snapshot diffs** in your PR before committing. Never blindly update snapshots.

## Documentation

### Building Docs
Expand Down
39 changes: 19 additions & 20 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
# ObjectOS Roadmap

> **Version**: 13.0.0
> **Version**: 14.0.0
> **Date**: February 12, 2026
> **Status**: Phase P — Developer Experience ⬜ In Progress
> **Status**: Phase P — Developer Experience ✅ Complete
> **Spec SDK**: `@objectstack/spec@3.0.0`
> **ObjectUI**: `@object-ui/*@2.0.0`

---

## Executive Summary

ObjectOS is a metadata-driven enterprise runtime platform built on the ObjectStack protocol. With all 19 server-side plugins fully implemented, spec compliance at 100%, and the Admin Console operational with 31 pages (including record create/edit), **Phases A–O are complete**. The platform has completed **Phase OPlatform Expansion**, delivering GraphQL subscriptions/DataLoader, Plugin Marketplace, AI Agent Framework, Analytics Engine, and Dynamic Plugin Loading (Module Federation).
ObjectOS is a metadata-driven enterprise runtime platform built on the ObjectStack protocol. With all 19 server-side plugins fully implemented, spec compliance at 100%, and the Admin Console operational with 31 pages (including record create/edit), **Phases A–P are complete**. The platform has completed **Phase PDeveloper Experience**, delivering documentation accuracy, code quality tooling, test infrastructure standardization, and developer onboarding improvements.

The integration of **@object-ui** (6 packages at v2.0.0) marks a strategic shift: the Admin Console's Business App Shell now leverages @object-ui's `SchemaRenderer` for metadata-driven UI rendering, replacing hand-built components with protocol-compliant controls.

**Phase P — Developer Experience** is now the active focus: improving onboarding documentation, standardizing package tooling, adding missing README files, and establishing consistent code quality infrastructure across all 20 packages.
**All roadmap phases are now complete.** The platform is production-ready with comprehensive developer tooling, coverage reporting, plugin scaffolding, and environment health checks.

> **@objectstack/\* v3.0.0 Upgrade**: All ObjectStack SDK packages upgraded to v3.0.0 — the new major version aligns the protocol spec, runtime, CLI, client, and all plugins to the 3.x series.

### What Changed

| Before (Plan v12.0) | After (Plan v13.0 — This Roadmap) |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------- |
| Phase P.1 partially complete (P.1.1–P.1.3) | Phase P.1 Documentation ✅ complete (quickstart, troubleshooting, API reference added) |
| No code quality tooling (linting, formatting) | Phase P.2 Code Quality ✅ complete (ESLint + Prettier + .editorconfig + Husky + lint-staged) |
| Only 1 package had `clean`/`type-check` scripts | All 20 packages now have `lint`, `clean`, `type-check` scripts |
| No pre-commit hooks | Husky + lint-staged enforce lint & format on every commit |
| Before (Plan v13.0) | After (Plan v14.0 — This Roadmap) |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| P.3.2–P.3.4 incomplete (coverage, CI, snapshots) | Phase P.3 Test Infrastructure ✅ complete (coverage thresholds, CI aggregation, guidelines) |
| P.4.2–P.4.3 incomplete (plugin template, doctor) | Phase P.4 Developer Onboarding ✅ complete (plugin scaffold, doctor checks) |
| Phase P still in progress | **All phases A–P complete** — platform fully developed |

---

Expand Down Expand Up @@ -105,7 +104,7 @@ The integration of **@object-ui** (6 packages at v2.0.0) marks a strategic shift
| **M** | **Technical Debt Resolution** | **Feb–Sep 2026** | **✅ Complete** |
| **N** | **Enterprise Features** | **Feb 2026** | **✅ Complete** |
| **O** | **Platform Expansion** | **Feb 2026** | **✅ Complete** |
| **P** | **Developer Experience** | **Feb–Apr 2026** | **⬜ In Progress** |
| **P** | **Developer Experience** | **Feb–Apr 2026** | **✅ Complete** |

### Phase G Outcomes

Expand Down Expand Up @@ -409,7 +408,7 @@ A comprehensive scan of the entire codebase identified the following improvement
| Tooling | No ESLint or Prettier configuration across the monorepo | 🔴 | ✅ Fixed |
| Tooling | No `.editorconfig` for consistent formatting | 🟡 | ✅ Fixed |
| Tooling | No pre-commit hooks (Husky/lint-staged) | 🟡 | ✅ Fixed |
| Consistency | Mixed test frameworks — 16 packages use Jest, 4 use Vitest | 🟡 | ⬜ P.3 |
| Consistency | Mixed test frameworks — 16 packages use Jest, 4 use Vitest | 🟡 | ⬜ P.3 (ADR-001: Vitest selected, migration tracked separately) |
| Consistency | Only 1 package has `clean`/`type-check` scripts; others missing | 🟡 | ✅ Fixed |
| Consistency | No package has a `lint` script defined | 🟡 | ✅ Fixed |

Expand Down Expand Up @@ -440,17 +439,17 @@ A comprehensive scan of the entire codebase identified the following improvement
| # | Task | Priority | Status |
| ----- | ----------------------------------------------------------------- | :------: | :----: |
| P.3.1 | Evaluate test framework unification (Jest vs Vitest) — choose one | 🟡 | ✅ |
| P.3.2 | Add coverage reporting with minimum thresholds per package | 🟡 | |
| P.3.3 | Add test coverage aggregation to CI pipeline | 🟢 | |
| P.3.4 | Add snapshot testing guidelines to CONTRIBUTING.md | 🟢 | |
| P.3.2 | Add coverage reporting with minimum thresholds per package | 🟡 | |
| P.3.3 | Add test coverage aggregation to CI pipeline | 🟢 | |
| P.3.4 | Add snapshot testing guidelines to CONTRIBUTING.md | 🟢 | |

### P.4 — Developer Onboarding (v2.4.0 — Target: April 2026)

| # | Task | Priority | Status |
| ----- | ---------------------------------------------------------------------------------- | :------: | :----: |
| P.4.1 | Create `DEVELOPMENT.md` with step-by-step local setup guide | 🟡 | ✅ |
| P.4.2 | Add `pnpm create:plugin` template with README, test scaffold, and CI config | 🟡 | |
| P.4.3 | Add interactive `objectstack doctor` checks for common environment issues | 🟢 | |
| P.4.2 | Add `pnpm create:plugin` template with README, test scaffold, and CI config | 🟡 | |
| P.4.3 | Add interactive `objectstack doctor` checks for common environment issues | 🟢 | |
| P.4.4 | Create architecture decision records (ADR) directory for key decisions | 🟢 | ✅ |
| P.4.5 | Add GitHub issue templates for bug reports, feature requests, and plugin proposals | 🟢 | ✅ |

Expand Down Expand Up @@ -532,13 +531,13 @@ A comprehensive scan of the entire codebase identified the following improvement

- Phase P.3: Test Infrastructure Standardization
- Framework unification decision: Vitest selected (ADR-001) ✅
- Coverage reporting and CI integration
- Coverage reporting and CI integration

### v2.4.0 — Developer Experience: Onboarding (Target: April 2026)

- Phase P.4: Developer Onboarding
- DEVELOPMENT.md step-by-step local setup guide ✅
- Plugin creation template improvements
- Plugin creation template improvements
- ADR directory with ADR-001 (Vitest standardization) ✅
- GitHub issue templates (bug report, feature request, plugin proposal) ✅

Expand Down Expand Up @@ -723,5 +722,5 @@ User Action → React Component → @object-ui/react SchemaRenderer
---

<div align="center">
<sub>ObjectOS v12.0.0 Roadmap — Developer Experience | Built with @objectstack/spec@3.0.0</sub>
<sub>ObjectOS v14.0.0 Roadmap — All Phases Complete | Built with @objectstack/spec@3.0.0</sub>
</div>
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"preview": "vite preview",
"lint": "eslint .",
"test": "vitest run",
"test:coverage": "vitest run --coverage",
"test:watch": "vitest"
},
"dependencies": {
Expand Down
11 changes: 11 additions & 0 deletions apps/web/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,16 @@ export default defineConfig({
setupFiles: ['./src/test/setup.ts'],
include: ['src/**/*.test.{ts,tsx}'],
css: false,
coverage: {
provider: 'v8',
include: ['src/**/*.{ts,tsx}'],
exclude: ['src/**/*.d.ts', 'src/test/**'],
thresholds: {
branches: 60,
functions: 60,
lines: 70,
statements: 70,
},
},
Comment on lines +19 to +29
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage thresholds were added, but Vitest coverage config doesn’t specify an lcov reporter. Since CI aggregates **/coverage/lcov.info, ensure this app’s Vitest coverage output includes lcov.info (e.g., add an lcov reporter) or adjust the CI upload format.

Copilot uses AI. Check for mistakes.
},
});
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"build": "turbo run build",
"build:vercel": "turbo run build --filter=@objectos/web...",
"test": "turbo run test --concurrency=3",
"test:coverage": "turbo run test:coverage --concurrency=3",
"lint": "turbo run lint",
"clean": "turbo run clean",
"type-check": "turbo run type-check --continue",
Expand All @@ -38,7 +39,7 @@
"objectstack:validate": "objectstack validate",
"objectstack:compile": "objectstack compile",
"objectstack:info": "objectstack info",
"objectstack:doctor": "objectstack doctor",
"objectstack:doctor": "node scripts/doctor.mjs",
"generate": "objectstack generate",
"generate:object": "objectstack generate object",
"generate:flow": "objectstack generate flow",
Expand All @@ -47,7 +48,7 @@
"generate:agent": "objectstack generate agent",
"generate:dashboard": "objectstack generate dashboard",
"generate:app": "objectstack generate app",
"create:plugin": "objectstack create plugin",
"create:plugin": "node scripts/create-plugin.mjs",
"create:example": "objectstack create example",
"web:dev": "pnpm --filter @objectos/web dev",
"web:build": "pnpm --filter @objectos/web build",
Expand Down
10 changes: 9 additions & 1 deletion packages/agent/jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,13 @@ module.exports = {
},
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts']
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts'],
coverageThreshold: {
global: {
branches: 70,
functions: 70,
lines: 80,
statements: 80,
},
},
};
1 change: 1 addition & 0 deletions packages/agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --clean && tsc --emitDeclarationOnly --declaration",
"test": "jest --forceExit --passWithNoTests",
"test:coverage": "jest --coverage --forceExit --passWithNoTests",
"lint": "eslint src/",
"clean": "rm -rf dist",
"type-check": "tsc --noEmit"
Expand Down
10 changes: 9 additions & 1 deletion packages/analytics/jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,13 @@ module.exports = {
},
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts']
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts'],
coverageThreshold: {
global: {
branches: 70,
functions: 70,
lines: 80,
statements: 80,
},
},
};
1 change: 1 addition & 0 deletions packages/analytics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --clean && tsc --emitDeclarationOnly --declaration",
"test": "jest --forceExit --passWithNoTests",
"test:coverage": "jest --coverage --forceExit --passWithNoTests",
"lint": "eslint src/",
"clean": "rm -rf dist",
"type-check": "tsc --noEmit"
Expand Down
10 changes: 9 additions & 1 deletion packages/audit/jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ module.exports = {
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts'
]
],
coverageThreshold: {
global: {
branches: 70,
functions: 70,
lines: 80,
statements: 80,
},
},
};
1 change: 1 addition & 0 deletions packages/audit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --clean && tsc --emitDeclarationOnly --declaration",
"test": "jest --forceExit --passWithNoTests",
"test:coverage": "jest --coverage --forceExit --passWithNoTests",
"lint": "eslint src/",
"clean": "rm -rf dist",
"type-check": "tsc --noEmit"
Expand Down
10 changes: 9 additions & 1 deletion packages/auth/jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ module.exports = {
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts'
]
],
coverageThreshold: {
global: {
branches: 70,
functions: 70,
lines: 80,
statements: 80,
},
},
};
1 change: 1 addition & 0 deletions packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --clean && tsc --emitDeclarationOnly --declaration",
"test": "jest --forceExit --passWithNoTests",
"test:coverage": "jest --coverage --forceExit --passWithNoTests",
"test:integration": "vitest run",
"lint": "eslint src/",
"clean": "rm -rf dist",
Expand Down
Loading
Loading