@njeybe/nativ 2.0.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -1
- package/README.md +30 -1
- package/dist/commands/task.d.ts +6 -0
- package/dist/commands/task.js +20 -2
- package/dist/commands/validate.js +14 -0
- package/dist/core/code-shape.d.ts +26 -0
- package/dist/core/code-shape.js +126 -0
- package/dist/core/model-routing.d.ts +6 -0
- package/dist/core/model-routing.js +49 -0
- package/dist/core/spec-slices.d.ts +27 -0
- package/dist/core/spec-slices.js +194 -0
- package/dist/core/verifier.d.ts +8 -1
- package/dist/core/verifier.js +26 -2
- package/dist/index.js +3 -0
- package/dist/mcp/server.js +16 -4
- package/dist/runner/agent-supervisor.js +39 -20
- package/dist/scanner/types.d.ts +7 -0
- package/dist/scanner/types.js +8 -0
- package/package.json +2 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/agents/architect.md +38 -1
- package/plugin/agents/verifier.md +1 -0
- package/plugin/agents/worker.md +2 -1
- package/plugin/skills/nativ/SKILL.md +14 -0
- package/templates/AGENTS.md +81 -67
- package/templates/GEMINI.md +21 -6
- package/templates/claude-agents/architect.md +65 -28
- package/templates/claude-agents/verifier.md +29 -28
- package/templates/claude-agents/worker.md +27 -26
- package/templates/dot-ai/subagents/flutter-developer.md +84 -11
- package/templates/dot-ai/subagents/frontend.md +83 -126
- package/templates/dot-ai/ui_specs.md +214 -78
package/dist/core/verifier.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { exec } from 'node:child_process';
|
|
4
|
+
import { checkCodeShape, formatCodeShapeReport } from './code-shape.js';
|
|
4
5
|
export function loadMasterPlan(targetDir) {
|
|
5
6
|
const planPath = path.join(targetDir, '.ai', 'master_plan.json');
|
|
6
7
|
if (!fs.existsSync(planPath)) {
|
|
@@ -76,6 +77,27 @@ export async function executeVerification(command, cwd, timeoutMs = 120_000) {
|
|
|
76
77
|
});
|
|
77
78
|
});
|
|
78
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Run the code-shape check on a task's target files and print a short summary to stderr.
|
|
82
|
+
* In 'warn' mode (default) the result is untouched; in 'block' mode issues fail it with a reason.
|
|
83
|
+
*/
|
|
84
|
+
export function applyCodeShape(result, targetDir, task) {
|
|
85
|
+
if (result.skipped || !result.success)
|
|
86
|
+
return result;
|
|
87
|
+
const report = checkCodeShape(targetDir, task.targetFiles || []);
|
|
88
|
+
if (report.mode === 'off')
|
|
89
|
+
return result;
|
|
90
|
+
result.codeShape = report;
|
|
91
|
+
const summary = formatCodeShapeReport(report);
|
|
92
|
+
if (summary)
|
|
93
|
+
console.error(summary);
|
|
94
|
+
if (report.mode === 'block' && report.issues.length > 0) {
|
|
95
|
+
result.success = false;
|
|
96
|
+
result.exitCode = 1;
|
|
97
|
+
result.error = `Code shape check failed: ${report.issues.length} issue(s) (codeStyle.mode is "block")`;
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
79
101
|
/**
|
|
80
102
|
* Run verification for a single specific task in the plan.
|
|
81
103
|
*/
|
|
@@ -128,7 +150,8 @@ export async function verifyTask(taskId, targetDirArg, options = {}) {
|
|
|
128
150
|
},
|
|
129
151
|
};
|
|
130
152
|
}
|
|
131
|
-
const
|
|
153
|
+
const raw = await executeVerification(foundTask.verificationCommand, targetDir, options.timeout);
|
|
154
|
+
const result = applyCodeShape(raw, targetDir, foundTask);
|
|
132
155
|
return {
|
|
133
156
|
taskId: foundTask.id,
|
|
134
157
|
title: foundTask.title,
|
|
@@ -217,7 +240,8 @@ export async function verifyBatch(targetDirArg, options = {}) {
|
|
|
217
240
|
let skipped = 0;
|
|
218
241
|
let totalDuration = 0;
|
|
219
242
|
for (const { task, milestone } of candidates) {
|
|
220
|
-
const
|
|
243
|
+
const raw = await executeVerification(task.verificationCommand, targetDir, options.timeout);
|
|
244
|
+
const vResult = applyCodeShape(raw, targetDir, task);
|
|
221
245
|
totalDuration += vResult.durationMs;
|
|
222
246
|
if (vResult.skipped) {
|
|
223
247
|
skipped++;
|
package/dist/index.js
CHANGED
|
@@ -126,6 +126,9 @@ export function createProgram() {
|
|
|
126
126
|
.option('-d, --description <text>', 'Task description')
|
|
127
127
|
.option('--fast-path', 'Route to the fast-path milestone (created on first use) and flag the task as fast path')
|
|
128
128
|
.option('--deps <ids>', 'Comma-separated dependency task IDs')
|
|
129
|
+
.option('--spec-refs <refs>', 'Comma-separated spec anchors, e.g. ui_specs.md#appointment-list')
|
|
130
|
+
.option('--complexity <level>', 'Task complexity: simple, standard or complex')
|
|
131
|
+
.option('--accept <text>', 'Acceptance ("done when") line; repeatable or "|"-separated', (value, prev = []) => [...prev, value])
|
|
129
132
|
.option('--json', 'Output the created task as JSON')
|
|
130
133
|
.action(async (title, targetDir, options) => {
|
|
131
134
|
await runTaskAdd(title, targetDir, options);
|
package/dist/mcp/server.js
CHANGED
|
@@ -103,8 +103,11 @@ export function createMcpServer(targetDirArg) {
|
|
|
103
103
|
targetFiles: z.array(z.string()).optional().describe('Files the task may modify'),
|
|
104
104
|
dependencies: z.array(z.string()).optional().describe('Task IDs that must be completed first'),
|
|
105
105
|
fastPath: z.boolean().optional().describe('Route to the fast-path track'),
|
|
106
|
+
specRefs: z.array(z.string()).optional().describe('Spec anchors, e.g. ui_specs.md#appointment-list'),
|
|
107
|
+
complexity: z.string().optional().describe('simple, standard or complex'),
|
|
108
|
+
acceptanceCriteria: z.array(z.string()).optional().describe('Plain-language "done when" lines'),
|
|
106
109
|
},
|
|
107
|
-
}, ({ title, description, assignedSubagent, milestone, verificationCommand, targetFiles, dependencies, fastPath }) => captureOutput(() => runTaskAdd(title, targetDir, {
|
|
110
|
+
}, ({ title, description, assignedSubagent, milestone, verificationCommand, targetFiles, dependencies, fastPath, specRefs, complexity, acceptanceCriteria }) => captureOutput(() => runTaskAdd(title, targetDir, {
|
|
108
111
|
description,
|
|
109
112
|
agent: assignedSubagent,
|
|
110
113
|
milestone,
|
|
@@ -112,6 +115,9 @@ export function createMcpServer(targetDirArg) {
|
|
|
112
115
|
files: targetFiles,
|
|
113
116
|
deps: dependencies,
|
|
114
117
|
fastPath,
|
|
118
|
+
specRefs,
|
|
119
|
+
complexity,
|
|
120
|
+
accept: acceptanceCriteria,
|
|
115
121
|
json: true,
|
|
116
122
|
})));
|
|
117
123
|
registerNativTool('task_start', {
|
|
@@ -119,13 +125,19 @@ export function createMcpServer(targetDirArg) {
|
|
|
119
125
|
inputSchema: { taskId: z.string().min(1).describe('Task ID, e.g. task-12') },
|
|
120
126
|
}, ({ taskId }) => captureOutput(() => runTaskStart(taskId, targetDir)));
|
|
121
127
|
registerNativTool('task_complete', {
|
|
122
|
-
description: "Mark a task as completed (
|
|
128
|
+
description: "Mark a task as completed (always executes its verificationCommand; verification cannot be skipped over MCP). Advances the milestone when all its tasks are done.",
|
|
123
129
|
inputSchema: {
|
|
124
130
|
taskId: z.string().min(1).describe('Task ID, e.g. task-12'),
|
|
125
131
|
notes: z.string().optional().describe('Completion notes or summary'),
|
|
126
|
-
skipVerify: z.
|
|
132
|
+
skipVerify: z.unknown().optional().describe('Not accepted: only a human at a terminal may skip'),
|
|
127
133
|
},
|
|
128
|
-
}, ({ taskId, notes, skipVerify }) => captureOutput(() =>
|
|
134
|
+
}, ({ taskId, notes, skipVerify }) => captureOutput(async () => {
|
|
135
|
+
// Kept in the schema so a stray value is refused instead of silently dropped.
|
|
136
|
+
if (skipVerify !== undefined) {
|
|
137
|
+
throw new Error('skipVerify is not allowed over MCP. Only a human at a terminal can skip verification.');
|
|
138
|
+
}
|
|
139
|
+
await runTaskComplete(taskId, targetDir, { notes });
|
|
140
|
+
}));
|
|
129
141
|
registerNativTool('verify', {
|
|
130
142
|
description: "Run verification commands on demand for a task, milestone, or all completed tasks without changing task status.",
|
|
131
143
|
inputSchema: {
|
|
@@ -8,6 +8,8 @@ import { loadMasterPlan, executeVerification } from '../core/verifier.js';
|
|
|
8
8
|
import { cacheHitRate, computeActualCostUsd, emptyActualUsage, mergeActualUsage, recordRunnerUsage, } from '../core/telemetry.js';
|
|
9
9
|
import { mergeAgentWorktree } from '../core/worktree-merge.js';
|
|
10
10
|
import { resolveProjectRoot, linkWorktreeAiDirectory, safeUnlinkWorktreeAiDirectory, linkWorktreeNodeModules, safeUnlinkWorktreeNodeModules, } from '../core/root-resolver.js';
|
|
11
|
+
import { resolveSpecSlices } from '../core/spec-slices.js';
|
|
12
|
+
import { resolveWorkerModel, toNativeModelId } from '../core/model-routing.js';
|
|
11
13
|
import { buildDesiredConfig, cliString, configuredInvocation, resolveCliInvocation } from '../core/setup-assets.js';
|
|
12
14
|
export const ACTIVE_RUNNER_STATUSES = [
|
|
13
15
|
'spawning_worktree',
|
|
@@ -377,28 +379,41 @@ export function supportsServerFallback(model) {
|
|
|
377
379
|
}
|
|
378
380
|
// Frozen so the tools + system prefix stays byte-identical and cacheable across
|
|
379
381
|
// turns and runs: nothing per-task, per-run, or time-dependent belongs here.
|
|
380
|
-
const NATIVE_SYSTEM_PROMPT = `You are an autonomous engineering agent dispatched by nativ, the middle tier of a three-tier development pipeline. You complete one task from .ai/master_plan.json on your own, with no human watching each step.
|
|
381
|
-
|
|
382
|
-
Your environment:
|
|
383
|
-
- The working directory is the task's workspace root. Each bash command runs in a fresh POSIX shell started there, so \`cd\` and exported variables do not persist between commands; chain with && when you need them.
|
|
384
|
-
- Use str_replace_based_edit_tool with paths relative to the workspace root. Files under .ai/, node_modules/ and .git/ are read-only.
|
|
385
|
-
- Commands are checked against an allowlist of executables. Command substitution, background jobs, absolute paths, parent-directory paths, secret files and publishing (git push, npm publish) are rejected with a reason; adjust and continue.
|
|
386
|
-
|
|
387
|
-
How to work:
|
|
388
|
-
1. Run \`nativ task start <taskId>\` before changing code.
|
|
389
|
-
2. Change only the files in the task's targetFiles. Follow the contracts in .ai/ exactly: table and column names, routes and schemas, and design tokens. Match the style of the surrounding code.
|
|
390
|
-
3. Run the task's verificationCommand. If it fails, fix the cause and run it again; you have at most three fix attempts. If it still fails, run \`git checkout -- <targetFiles>\`, then \`nativ task block <taskId> --reason "Verification failed after 3 attempts: <short error>"\`, and stop.
|
|
391
|
-
4. If a contract in .ai/ lacks something the task needs, do not edit it. Run \`nativ task escalate <taskId> --type schema_flaw --details "<the gap>"\` and stop.
|
|
392
|
-
5. When verification passes, run \`nativ task complete <taskId>\`.
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
382
|
+
const NATIVE_SYSTEM_PROMPT = `You are an autonomous engineering agent dispatched by nativ, the middle tier of a three-tier development pipeline. You complete one task from .ai/master_plan.json on your own, with no human watching each step.
|
|
383
|
+
|
|
384
|
+
Your environment:
|
|
385
|
+
- The working directory is the task's workspace root. Each bash command runs in a fresh POSIX shell started there, so \`cd\` and exported variables do not persist between commands; chain with && when you need them.
|
|
386
|
+
- Use str_replace_based_edit_tool with paths relative to the workspace root. Files under .ai/, node_modules/ and .git/ are read-only.
|
|
387
|
+
- Commands are checked against an allowlist of executables. Command substitution, background jobs, absolute paths, parent-directory paths, secret files and publishing (git push, npm publish) are rejected with a reason; adjust and continue.
|
|
388
|
+
|
|
389
|
+
How to work:
|
|
390
|
+
1. Run \`nativ task start <taskId>\` before changing code.
|
|
391
|
+
2. Change only the files in the task's targetFiles. Follow the contracts in .ai/ exactly: table and column names, routes and schemas, and design tokens. Match the style of the surrounding code.
|
|
392
|
+
3. Run the task's verificationCommand. If it fails, fix the cause and run it again; you have at most three fix attempts. If it still fails, run \`git checkout -- <targetFiles>\`, then \`nativ task block <taskId> --reason "Verification failed after 3 attempts: <short error>"\`, and stop.
|
|
393
|
+
4. If a contract in .ai/ lacks something the task needs, do not edit it. Run \`nativ task escalate <taskId> --type schema_flaw --details "<the gap>"\` and stop.
|
|
394
|
+
5. When verification passes, run \`nativ task complete <taskId>\`.
|
|
395
|
+
|
|
396
|
+
Code style (the project's own formatter or linter config wins): lines 100 characters or fewer, hard max 120; functions about 40 lines, files about 300; split a growing UI file into components, one per file; comments at most 2 lines, say why not what, plain everyday words, no restating the code, no banner comments, no commented-out code; match the surrounding code.
|
|
397
|
+
|
|
398
|
+
Secrets: never open .env files (.env.example is fine), *.pem, *.key or .nativ/*.local.json, and never print environment variables. For database structure use \`nativ db status|inspect|diff --json\`; never read table data.
|
|
399
|
+
|
|
396
400
|
When you finish or get blocked, end with a short plain-English summary: what changed, the verification result, and anything the operator must decide. Do not call a tool in that final message.`;
|
|
397
401
|
const NATIVE_TOOLS = [
|
|
398
402
|
{ type: 'bash_20250124', name: 'bash' },
|
|
399
403
|
{ type: 'text_editor_20250728', name: 'str_replace_based_edit_tool', max_characters: NATIVE_TOOL_OUTPUT_LIMIT },
|
|
400
404
|
];
|
|
401
|
-
function
|
|
405
|
+
function buildSpecSlicesBlock(task, rootDir) {
|
|
406
|
+
if (!rootDir || !task.specRefs?.length)
|
|
407
|
+
return '';
|
|
408
|
+
const { slices, warnings } = resolveSpecSlices(rootDir, task.specRefs);
|
|
409
|
+
if (!slices.length && !warnings.length)
|
|
410
|
+
return '';
|
|
411
|
+
const parts = slices.map((s) => `<slice ref="${s.ref}" file="${s.file}"${s.truncated ? ' truncated="true"' : ''}>\n${s.text}\n</slice>`);
|
|
412
|
+
if (warnings.length)
|
|
413
|
+
parts.push(`<warnings>\n${warnings.join('\n')}\n</warnings>`);
|
|
414
|
+
return `<spec_slices>\n${parts.join('\n')}\n</spec_slices>\nThe spec slices above are the parts of the contracts this task refers to. Read a whole contract only when a slice is missing, truncated or does not answer your question.`;
|
|
415
|
+
}
|
|
416
|
+
function buildNativeTaskPrompt(task, roleGuide, useWorktree, rootDir) {
|
|
402
417
|
const spec = {
|
|
403
418
|
id: task.id,
|
|
404
419
|
title: task.title,
|
|
@@ -413,6 +428,7 @@ function buildNativeTaskPrompt(task, roleGuide, useWorktree) {
|
|
|
413
428
|
`Execute task ${task.id}.`,
|
|
414
429
|
`<task>\n${JSON.stringify(spec, null, 2)}\n</task>`,
|
|
415
430
|
roleGuide ? `<role_guide path=".ai/subagents/${task.assignedSubagent}.md">\n${roleGuide}\n</role_guide>` : '',
|
|
431
|
+
buildSpecSlicesBlock(task, rootDir),
|
|
416
432
|
'Load only the contract slice your role needs (.ai/api_contracts.json, .ai/db_schema.json, .ai/ui_specs.md, .ai/context.md) with the editor view command.',
|
|
417
433
|
useWorktree
|
|
418
434
|
? 'You are in an isolated git worktree on the agent branch. After `nativ task complete` succeeds, commit the target files there (`git add <targetFiles> && git commit -m "<type>(<scope>): <summary>"`) so the operator can merge the branch.'
|
|
@@ -786,7 +802,9 @@ export class AgentSupervisor extends EventEmitter {
|
|
|
786
802
|
this.assertDependenciesMet(task);
|
|
787
803
|
const engine = normalizeEngine(options.runnerEngine, this.defaultEngine);
|
|
788
804
|
const thinkingBudget = normalizeThinkingBudget(options.thinkingBudget);
|
|
789
|
-
const
|
|
805
|
+
const explicitModel = normalizeModel(options.model);
|
|
806
|
+
const routedModel = explicitModel ? null : resolveWorkerModel(this.rootDir, task);
|
|
807
|
+
const requestedModel = explicitModel ?? (routedModel && engine === 'cli' ? routedModel : null);
|
|
790
808
|
const timeoutSeconds = this.normalizeTimeout(options.timeoutSeconds);
|
|
791
809
|
const useWorktree = options.useWorktree !== false;
|
|
792
810
|
const worktreeDir = useWorktree ? path.join(this.rootDir, '.worktrees', `task-${taskId}`) : this.rootDir;
|
|
@@ -798,7 +816,8 @@ export class AgentSupervisor extends EventEmitter {
|
|
|
798
816
|
if (process.platform === 'win32' && this.toolShell === true) {
|
|
799
817
|
throw new SupervisorError('BASH_NOT_FOUND', 'The native engine runs the model\'s commands in bash, which was not found. Install Git for Windows (it ships Git Bash) or set NATIV_BASH_PATH to bash.exe.');
|
|
800
818
|
}
|
|
801
|
-
const model = requestedModel ??
|
|
819
|
+
const model = requestedModel ??
|
|
820
|
+
(routedModel ? toNativeModelId(routedModel, DEFAULT_NATIVE_MODEL) : this.defaultNativeModel);
|
|
802
821
|
thinking = resolveNativeThinking(model, thinkingBudget);
|
|
803
822
|
native = {
|
|
804
823
|
client: this.createAnthropicClient(),
|
|
@@ -1312,7 +1331,7 @@ export class AgentSupervisor extends EventEmitter {
|
|
|
1312
1331
|
const { thinking } = native;
|
|
1313
1332
|
const fallback = supportsServerFallback(native.model);
|
|
1314
1333
|
const messages = [
|
|
1315
|
-
{ role: 'user', content: buildNativeTaskPrompt(run.task, this.readRoleGuide(run.task), useWorktree) },
|
|
1334
|
+
{ role: 'user', content: buildNativeTaskPrompt(run.task, this.readRoleGuide(run.task), useWorktree, this.rootDir) },
|
|
1316
1335
|
];
|
|
1317
1336
|
for (let turn = 1;; turn++) {
|
|
1318
1337
|
if (run.settled)
|
package/dist/scanner/types.d.ts
CHANGED
|
@@ -37,7 +37,14 @@ export interface MasterPlanTask {
|
|
|
37
37
|
* (e.g. via `nativ task add --fast-path`). Absent or false means a planned task.
|
|
38
38
|
*/
|
|
39
39
|
fastPath?: boolean;
|
|
40
|
+
/** Spec anchors, e.g. "ui_specs.md#appointment-list" or "api_contracts.json#/paths/~1appointments". */
|
|
41
|
+
specRefs?: string[];
|
|
42
|
+
complexity?: TaskComplexity;
|
|
43
|
+
/** Plain-language "done when" lines. */
|
|
44
|
+
acceptanceCriteria?: string[];
|
|
40
45
|
}
|
|
46
|
+
export type TaskComplexity = 'simple' | 'standard' | 'complex';
|
|
47
|
+
export declare const TASK_COMPLEXITIES: readonly TaskComplexity[];
|
|
41
48
|
/** Lists every structural problem with a task; empty when the task is valid. */
|
|
42
49
|
export declare function validateMasterPlanTask(task: unknown): string[];
|
|
43
50
|
export interface MasterPlanMilestone {
|
package/dist/scanner/types.js
CHANGED
|
@@ -16,6 +16,7 @@ export function isSubagentType(value) {
|
|
|
16
16
|
return SUBAGENT_TYPES.includes(value);
|
|
17
17
|
}
|
|
18
18
|
export const TASK_STATUSES = ['pending', 'in_progress', 'completed', 'blocked'];
|
|
19
|
+
export const TASK_COMPLEXITIES = ['simple', 'standard', 'complex'];
|
|
19
20
|
/** Lists every structural problem with a task; empty when the task is valid. */
|
|
20
21
|
export function validateMasterPlanTask(task) {
|
|
21
22
|
if (!task || typeof task !== 'object' || Array.isArray(task))
|
|
@@ -46,5 +47,12 @@ export function validateMasterPlanTask(task) {
|
|
|
46
47
|
errors.push(`${label}: "notes" must be a string`);
|
|
47
48
|
if (t.fastPath !== undefined && typeof t.fastPath !== 'boolean')
|
|
48
49
|
errors.push(`${label}: "fastPath" must be a boolean`);
|
|
50
|
+
for (const field of ['specRefs', 'acceptanceCriteria']) {
|
|
51
|
+
if (t[field] !== undefined && !isStringArray(t[field]))
|
|
52
|
+
errors.push(`${label}: "${field}" must be an array of strings`);
|
|
53
|
+
}
|
|
54
|
+
if (t.complexity !== undefined && !TASK_COMPLEXITIES.includes(t.complexity)) {
|
|
55
|
+
errors.push(`${label}: "complexity" must be one of ${TASK_COMPLEXITIES.join(', ')}`);
|
|
56
|
+
}
|
|
49
57
|
return errors;
|
|
50
58
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@njeybe/nativ",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Role-based multi-agent workflow harness: Claude Code by default, other AI agents pluggable",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"prepare": "npm run build",
|
|
23
23
|
"prepublishOnly": "npm run build && node scripts/sync-plugin.mjs --check",
|
|
24
24
|
"start": "node bin/cli.js",
|
|
25
|
-
"test": "node tests/test-task-router.mjs && node tests/test-contract-generator.mjs && node tests/test-verify-gatekeeper.mjs && node tests/test-mcp-server.mjs && node tests/test-data-studio.mjs && node tests/test-fragmented-env.mjs && node tests/test-env-example-detection.mjs && node tests/test-contract-governor.mjs && node tests/test-worktree-lifecycle.mjs && node tests/test-agent-supervisor.mjs && node tests/test-concurrency-locks.mjs && node tests/test-telemetry-engine.mjs && node tests/test-benchmark-suite.mjs && node tests/test-providers.mjs && node tests/test-tier1-liaison.mjs && node tests/test-enforcement.mjs && node tests/test-setup-doctor.mjs && node tests/test-update.mjs && node tests/test-validate.mjs && node tests/test-plugin-manifest.mjs && node tests/test-v2-e2e.mjs && npx tsx tests/test-studio-pipeline-api.mjs && npx tsx tests/test-studio-light-ui.mjs"
|
|
25
|
+
"test": "node tests/test-task-router.mjs && node tests/test-task-fields.mjs && node tests/test-design-templates.mjs && node tests/test-spec-slices.mjs && node tests/test-contract-generator.mjs && node tests/test-verify-gatekeeper.mjs && node tests/test-mcp-server.mjs && node tests/test-data-studio.mjs && node tests/test-fragmented-env.mjs && node tests/test-env-example-detection.mjs && node tests/test-contract-governor.mjs && node tests/test-worktree-lifecycle.mjs && node tests/test-agent-supervisor.mjs && node tests/test-concurrency-locks.mjs && node tests/test-telemetry-engine.mjs && node tests/test-benchmark-suite.mjs && node tests/test-providers.mjs && node tests/test-tier1-liaison.mjs && node tests/test-enforcement.mjs && node tests/test-setup-doctor.mjs && node tests/test-update.mjs && node tests/test-validate.mjs && node tests/test-plugin-manifest.mjs && node tests/test-code-shape.mjs && node tests/test-model-routing.mjs && node tests/test-v2-e2e.mjs && npx tsx tests/test-studio-pipeline-api.mjs && npx tsx tests/test-studio-light-ui.mjs"
|
|
26
26
|
},
|
|
27
27
|
"keywords": [
|
|
28
28
|
"ai",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nativ",
|
|
3
3
|
"displayName": "nativ",
|
|
4
|
-
"version": "2.0
|
|
4
|
+
"version": "2.2.0",
|
|
5
5
|
"description": "Role-based multi-agent workflow for Claude Code: architect, worker and verifier agents, task-scope enforcement, and the nativ MCP server.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "JB Natividad"
|
|
@@ -14,13 +14,50 @@ Your job is design, not implementation. You turn a feature request or an escalat
|
|
|
14
14
|
## How you work
|
|
15
15
|
|
|
16
16
|
1. Orient: read `.ai/context.md`, then only the contract you are changing. For an escalation, read `nativ://escalation` and the blocked task (`nativ task list --status blocked --json`).
|
|
17
|
-
2.
|
|
17
|
+
2. **Pick the design track first** and record it in `.ai/ui_specs.md` under Planning Level. STOP and ask the owner to confirm it:
|
|
18
|
+
- **Experience-First (Outside-In):** UI flows and screen data needs drive the API contracts and the database schema. Order: UI specs, then API contracts, then database schema.
|
|
19
|
+
- **Data-First (Inside-Out):** the core database schema or pipeline models drive the API contracts and the UI views. Order: database schema, then API contracts, then UI specs.
|
|
20
|
+
|
|
21
|
+
Recommend Experience-First for user-facing products and Data-First for data pipelines or when the schema already exists. Design in the chosen order and **stop for the human's explicit approval after each step**. Do not start the next until the previous is approved.
|
|
18
22
|
3. Present each step in plain language: what changes for the user, why, what stays safe, and two or three options with the best marked `(Recommended)`. No raw stack traces.
|
|
19
23
|
4. After approval, write the contract. Claude Code will ask the human to confirm every write under `.ai/`; that prompt is the approval gate, so never try to route around it.
|
|
20
24
|
5. Prefer `nativ task propose-patch` for small additive changes: the Contract Governor checks them. Any `[DROPPED]` or `[DESTRUCTIVE]` change needs the human's explicit yes first.
|
|
21
25
|
6. Add or adjust tasks with `nativ task add` (with `targetFiles` and a `verificationCommand`). Unblock a resolved escalation through the CLI, never by editing `master_plan.json`.
|
|
22
26
|
7. Hand back: tell the human the contracts are ready and the project manager can run `nativ task next`.
|
|
23
27
|
|
|
28
|
+
## UI and UX design procedure
|
|
29
|
+
|
|
30
|
+
Use this for the UI step of the chosen track. Keep every message compact. Write the result into `.ai/ui_specs.md` under its existing headings.
|
|
31
|
+
|
|
32
|
+
1. **Planning level.** Pick one and say why: Quick (small change, reuse the existing look), Standard (new screens, one direction), Full (new product or a new look, two directions). The owner can override it.
|
|
33
|
+
2. **Start from the scan.** Use the deterministic scan in `.ai/context.md`. Do not read files one by one to learn the stack.
|
|
34
|
+
3. **Discovery.** Ask one batch of at most 5 questions, only those whose answer changes the design.
|
|
35
|
+
4. **Reuse check.** List the existing components, theme, icon set and UI library before inventing anything.
|
|
36
|
+
5. **Content first.** Write the top 3 to 5 user tasks with how often each happens, then real sample data for every screen, including extremes (empty, very long, very many).
|
|
37
|
+
6. **User flows.** One line per flow, with the tap or click count.
|
|
38
|
+
7. **Design brief (Standard and Full).** Before any direction, fill the Design Brief section of `.ai/ui_specs.md`: who uses it, the job they are doing, tone in three words, things to avoid. Also record the primary platform (web, mobile or both) there.
|
|
39
|
+
8. **Two directions (Full only).** Exactly two distinct design directions. Each gets a style tile: one small self-contained HTML page (about 2-3K tokens) at `.ai/design/direction-a.html` and `.ai/design/direction-b.html`. Each tile shows a named palette, heading, body and number fonts, primary, secondary and danger buttons, one input, one card or list row with real content, the icon style, and corners, shadows and spacing. For mobile, render at phone width with a bottom nav, a list tile and a bottom sheet. Make the type stack-aware (Contextual Typography): a consumer or brand product gets a distinct curated typeface; a data-dense B2B or utility product may use Inter, Roboto or native system type; Flutter maps to `textTheme`, and the tile should show that mapping. Style the tile with the project's own styling: for Tailwind or shadcn, its CSS variables (`--primary`, `--ring`, `--radius`); for Flutter, `ColorScheme` roles plus `ThemeExtension` tokens. Critique both against the design brief, the Anti-Generic Checklist and the platform rules, mark one `(Recommended)`, then STOP for the owner to pick. Keep the chosen tile as `.ai/design/style-tile.html` and delete the other.
|
|
40
|
+
9. **Wireframes.** Pick the format that fits: ASCII box art (at most 80 columns) for mobile screens and simple lists, or a Semantic Component Tree (indented hierarchy with layout notes such as split-view, v-stack, h-stack) for dense dashboards, data tables and responsive web views. Regions labeled by component, real content. One per key screen on desktop, plus mobile for the primary screen. Primary platform first. STOP for approval.
|
|
41
|
+
10. **Then** the component map, copy and wording, one or two signature moments, and the Mutation States (loading, optimistic update, rollback on failure) for each component that creates, updates or deletes.
|
|
42
|
+
|
|
43
|
+
Token limits: exactly two directions, style tiles only in Full, compact wireframes, questions batched.
|
|
44
|
+
|
|
45
|
+
## Task breakdown
|
|
46
|
+
|
|
47
|
+
- About one component or endpoint per task, at most 5 files.
|
|
48
|
+
- `acceptanceCriteria` in plain words, including which states apply (loading, empty, error).
|
|
49
|
+
- `specRefs` point to exact sections, such as `ui_specs.md#appointment-list` or an `api_contracts.json` route.
|
|
50
|
+
- `complexity` is `simple`, `standard` or `complex`.
|
|
51
|
+
- Dependencies make parallel-safe work explicit: tasks that touch different files and need no result from each other have none between them.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
nativ task add "Appointment list" --agent frontend \
|
|
55
|
+
--spec-refs "ui_specs.md#appointment-list,api_contracts.json#GET /appointments" \
|
|
56
|
+
--complexity standard \
|
|
57
|
+
--accept "Shows name and time per row" --accept "Empty and error states shown" \
|
|
58
|
+
--files src/components/AppointmentList.tsx --deps task-3 --verify "npm test"
|
|
59
|
+
```
|
|
60
|
+
|
|
24
61
|
## Limits
|
|
25
62
|
|
|
26
63
|
- Do not implement application code. A trivial fix is acceptable; anything larger becomes a task for a worker.
|
|
@@ -18,6 +18,7 @@ You did not write this code, and that is the point: check it as a skeptic would.
|
|
|
18
18
|
- table, column, route and schema names match `.ai/db_schema.json` and `.ai/api_contracts.json`
|
|
19
19
|
- only the task's `targetFiles` changed, and no tests were deleted or weakened
|
|
20
20
|
- no secrets, connection strings or data in code, logs, tests or commits
|
|
21
|
+
- the `## Code style` rules in `AGENTS.md` are followed (lines over 120 characters, comments over 2 lines, oversized files or UI files with several components); report violations as findings
|
|
21
22
|
- errors are handled and inputs are validated at the boundary
|
|
22
23
|
4. Report in short findings, most serious first. For each: the file and line, what is wrong, and why it matters. Separate confirmed problems from suspicions and say which is which.
|
|
23
24
|
5. If you find nothing, say what you checked so the result can be trusted.
|
package/plugin/agents/worker.md
CHANGED
|
@@ -14,8 +14,9 @@ You are given one task id. Do that task and nothing else.
|
|
|
14
14
|
## Steps
|
|
15
15
|
|
|
16
16
|
1. `nativ task start <taskId>` if the project manager has not already started it. Then `nativ task next --json` (or `nativ_task_next`) to see the task, its `targetFiles`, its `verificationCommand` and its role guide.
|
|
17
|
-
2. Load only what the task needs: `.ai/subagents/<assignedSubagent>.md` and the contract slice `AGENTS.md` lists for that role.
|
|
17
|
+
2. Load only what the task needs: `.ai/subagents/<assignedSubagent>.md` and the contract slice `AGENTS.md` lists for that role. If the task has `specSlices`, read those first. Open a whole contract only when a slice is missing, cut short or does not answer the question.
|
|
18
18
|
3. Change **only** the files in `targetFiles`. Match the style of the surrounding code and follow the contracts exactly: table and column names, routes and schemas, design tokens.
|
|
19
|
+
Follow the `## Code style` rules in `AGENTS.md`: short lines, small functions, one UI component per file, brief plain comments.
|
|
19
20
|
4. Run the `verificationCommand`. If it fails, fix the cause and run it again. You have three fix attempts.
|
|
20
21
|
5. If it still fails: `git checkout -- <targetFiles>`, then `nativ task block <taskId> --reason "Verification failed after 3 attempts: <short error>"`, then stop and report.
|
|
21
22
|
6. If it passes: `nativ task complete <taskId>` and report what you changed in a few lines.
|
|
@@ -31,6 +31,7 @@ The vendor behind a role does not matter. The boundary does, and it is enforced:
|
|
|
31
31
|
- `database`, `db-migration`: `.ai/db_schema.json`
|
|
32
32
|
- `devops-agent`: `.ai/context.md`
|
|
33
33
|
- `qa-tester`, `security-auditor`: the target files and `.ai/api_contracts.json`
|
|
34
|
+
- If the task has `specSlices`, read those first. Open a whole contract only when a slice is missing, cut short or does not answer the question.
|
|
34
35
|
3. Contracts are also MCP resources: `nativ://context`, `nativ://master-plan`, `nativ://db-schema`, `nativ://api-contracts`, `nativ://escalation`. They are read-only.
|
|
35
36
|
|
|
36
37
|
## Task loop
|
|
@@ -42,8 +43,21 @@ The vendor behind a role does not matter. The boundary does, and it is enforced:
|
|
|
42
43
|
5. When verification passes: `nativ task complete <taskId>`. The gatekeeper re-runs the check. Do not use `--no-verify`.
|
|
43
44
|
6. `nativ task next` for the following task.
|
|
44
45
|
|
|
46
|
+
When the project manager hands a task to a `nativ:worker` through the Agent tool, it passes the task's `recommendedModel` (haiku, sonnet or opus) as the `model` parameter. If the task has none, the worker's default applies.
|
|
47
|
+
|
|
45
48
|
Independent tasks can run in parallel in isolated worktrees: `nativ worktree create <taskId>`, then `nativ worktree merge <taskId>` once verified.
|
|
46
49
|
|
|
50
|
+
## Code style
|
|
51
|
+
|
|
52
|
+
Applies to every worker. A project's own formatter or linter config wins over these defaults.
|
|
53
|
+
|
|
54
|
+
- Lines: aim for 100 characters or fewer, hard maximum 120.
|
|
55
|
+
- Functions: about 40 lines. Files: about 300 lines.
|
|
56
|
+
- A growing UI file is split into components, one component per file.
|
|
57
|
+
- Comments: at most 2 lines, explain why (not what), in plain everyday words with no technical jargon.
|
|
58
|
+
- Do not restate the code in a comment. No banner or divider comments. No commented-out code.
|
|
59
|
+
- Match the surrounding code.
|
|
60
|
+
|
|
47
61
|
## When the contract is wrong
|
|
48
62
|
|
|
49
63
|
If a contract is missing something the task needs, do **not** edit it and do not work around it. Run:
|
package/templates/AGENTS.md
CHANGED
|
@@ -1,67 +1,81 @@
|
|
|
1
|
-
# nativ Agent Directive
|
|
2
|
-
|
|
3
|
-
This project uses the **nativ** role-based workflow. Every agent, whatever tool or model it runs on, follows this file. The state lives in `.ai/`; the `nativ` CLI and its MCP tools are the only supported way to change it.
|
|
4
|
-
|
|
5
|
-
## Roles
|
|
6
|
-
|
|
7
|
-
| Role | Who | May do | May not do |
|
|
8
|
-
| :--- | :--- | :--- | :--- |
|
|
9
|
-
| **Architect** | the `architect` subagent, or a session started with `NATIV_ROLE=architect` | Design the database, API and UI contracts; resolve escalations; write `.ai/` after the human approves | Write application code beyond a trivial fix |
|
|
10
|
-
| **Project Manager** | the main Claude Code session | Run the task loop, delegate to workers, run verification, report to the human | Edit `.ai/`, or implement tasks itself when a worker can |
|
|
11
|
-
| **Worker** | the `worker` subagent (one task, one role guide) | Change the files in the task's `targetFiles` | Touch anything else, edit contracts, run destructive commands |
|
|
12
|
-
| **Verifier** | the `verifier` subagent | Read code, run tests and checks, report findings | Edit files |
|
|
13
|
-
|
|
14
|
-
The vendor behind a role does not matter. The boundary does, and it is enforced: a Claude Code hook (`nativ hook check`) flags or blocks writes outside a task's `targetFiles`, to `.ai/`, and to secret files.
|
|
15
|
-
|
|
16
|
-
## Orientation (do this first, load nothing else up front)
|
|
17
|
-
|
|
18
|
-
1. Run `nativ task next --json` (MCP: `nativ_task_next`).
|
|
19
|
-
2. Load only the slice the task needs:
|
|
20
|
-
- role guide: `.ai/subagents/<assignedSubagent>.md`
|
|
21
|
-
- `backend`: `.ai/api_contracts.json` and `.ai/db_schema.json`
|
|
22
|
-
- `frontend`, `flutter-developer`: `.ai/ui_specs.md` and `.ai/api_contracts.json`
|
|
23
|
-
- `database`, `db-migration`: `.ai/db_schema.json`
|
|
24
|
-
- `devops-agent`: `.ai/context.md`
|
|
25
|
-
- `qa-tester`, `security-auditor`: the target files and `.ai/api_contracts.json`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
##
|
|
66
|
-
|
|
67
|
-
|
|
1
|
+
# nativ Agent Directive
|
|
2
|
+
|
|
3
|
+
This project uses the **nativ** role-based workflow. Every agent, whatever tool or model it runs on, follows this file. The state lives in `.ai/`; the `nativ` CLI and its MCP tools are the only supported way to change it.
|
|
4
|
+
|
|
5
|
+
## Roles
|
|
6
|
+
|
|
7
|
+
| Role | Who | May do | May not do |
|
|
8
|
+
| :--- | :--- | :--- | :--- |
|
|
9
|
+
| **Architect** | the `architect` subagent, or a session started with `NATIV_ROLE=architect` | Design the database, API and UI contracts; resolve escalations; write `.ai/` after the human approves | Write application code beyond a trivial fix |
|
|
10
|
+
| **Project Manager** | the main Claude Code session | Run the task loop, delegate to workers, run verification, report to the human | Edit `.ai/`, or implement tasks itself when a worker can |
|
|
11
|
+
| **Worker** | the `worker` subagent (one task, one role guide) | Change the files in the task's `targetFiles` | Touch anything else, edit contracts, run destructive commands |
|
|
12
|
+
| **Verifier** | the `verifier` subagent | Read code, run tests and checks, report findings | Edit files |
|
|
13
|
+
|
|
14
|
+
The vendor behind a role does not matter. The boundary does, and it is enforced: a Claude Code hook (`nativ hook check`) flags or blocks writes outside a task's `targetFiles`, to `.ai/`, and to secret files.
|
|
15
|
+
|
|
16
|
+
## Orientation (do this first, load nothing else up front)
|
|
17
|
+
|
|
18
|
+
1. Run `nativ task next --json` (MCP: `nativ_task_next`).
|
|
19
|
+
2. Load only the slice the task needs:
|
|
20
|
+
- role guide: `.ai/subagents/<assignedSubagent>.md`
|
|
21
|
+
- `backend`: `.ai/api_contracts.json` and `.ai/db_schema.json`
|
|
22
|
+
- `frontend`, `flutter-developer`: `.ai/ui_specs.md` and `.ai/api_contracts.json`
|
|
23
|
+
- `database`, `db-migration`: `.ai/db_schema.json`
|
|
24
|
+
- `devops-agent`: `.ai/context.md`
|
|
25
|
+
- `qa-tester`, `security-auditor`: the target files and `.ai/api_contracts.json`
|
|
26
|
+
- If the task has `specSlices`, read those first. Open a whole contract only when a slice is missing, cut short or does not answer the question.
|
|
27
|
+
3. Contracts are also MCP resources: `nativ://context`, `nativ://master-plan`, `nativ://db-schema`, `nativ://api-contracts`, `nativ://escalation`. They are read-only.
|
|
28
|
+
|
|
29
|
+
## Task loop
|
|
30
|
+
|
|
31
|
+
1. `nativ task start <taskId>`. Never edit `.ai/master_plan.json` by hand.
|
|
32
|
+
2. Change only the task's `targetFiles`. Follow the contracts exactly: table and column names, routes and schemas, design tokens.
|
|
33
|
+
3. Run the task's `verificationCommand` (or `nativ verify <taskId>`). You have **three** fix attempts.
|
|
34
|
+
4. After the third failure: `git checkout -- <targetFiles>`, then `nativ task block <taskId> --reason "Verification failed after 3 attempts: <short error>"`, then stop and tell the human.
|
|
35
|
+
5. When verification passes: `nativ task complete <taskId>`. The gatekeeper re-runs the check. Do not use `--no-verify`.
|
|
36
|
+
6. `nativ task next` for the following task.
|
|
37
|
+
|
|
38
|
+
When the project manager hands a task to a `nativ:worker` through the Agent tool, it passes the task's `recommendedModel` (haiku, sonnet or opus) as the `model` parameter. If the task has none, the worker's default applies.
|
|
39
|
+
|
|
40
|
+
Independent tasks can run in parallel in isolated worktrees: `nativ worktree create <taskId>`, then `nativ worktree merge <taskId>` once verified.
|
|
41
|
+
|
|
42
|
+
## Code style
|
|
43
|
+
|
|
44
|
+
Applies to every worker. A project's own formatter or linter config wins over these defaults.
|
|
45
|
+
|
|
46
|
+
- Lines: aim for 100 characters or fewer, hard maximum 120.
|
|
47
|
+
- Functions: about 40 lines. Files: about 300 lines.
|
|
48
|
+
- A growing UI file is split into components, one component per file.
|
|
49
|
+
- Comments: at most 2 lines, explain why (not what), in plain everyday words with no technical jargon.
|
|
50
|
+
- Do not restate the code in a comment. No banner or divider comments. No commented-out code.
|
|
51
|
+
- Match the surrounding code.
|
|
52
|
+
|
|
53
|
+
## When the contract is wrong
|
|
54
|
+
|
|
55
|
+
If a contract is missing something the task needs, do **not** edit it and do not work around it. Run:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
nativ task escalate <taskId> --type schema_flaw --details "what is missing"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Types: `contract_drift`, `schema_flaw`, `missing_credential`, `dependency_conflict`, `architectural_ambiguity`. Then stop work on that task. The architect resolves it after the human decides. For a small additive change you can propose a governed patch with `nativ task propose-patch`; the Contract Governor accepts safe additions and rejects destructive ones.
|
|
62
|
+
|
|
63
|
+
If the enforcement hook warns that a file is outside the task scope, treat it as this situation: escalate instead of editing.
|
|
64
|
+
|
|
65
|
+
## Talking to the human
|
|
66
|
+
|
|
67
|
+
The human is the product owner, not a log reader. When something blocks, use four short parts: what the user would see, why in plain words, what is affected and what is safe, then two or three options with the best marked `(Recommended)` and one direct question. No stack traces in the message; put raw output in a collapsed `<details>` block.
|
|
68
|
+
|
|
69
|
+
## Air-gap (critical)
|
|
70
|
+
|
|
71
|
+
Credentials exist only in `.env*` files and inside the local `nativ` process. Work with structure, never secrets.
|
|
72
|
+
|
|
73
|
+
- Never open, print, search or copy `.env`, `.env.*` (except `.env.example`), `.nativ/*.local.json`, `*.pem`, `*.key`. Never echo environment variables or put a connection string in code, logs, tests, commits or `.ai/`.
|
|
74
|
+
- For databases use the masked, structure-only commands: `nativ db status --json`, `nativ db inspect --json`, `nativ db diff --target contract`. Never read row data.
|
|
75
|
+
- Do not run `nativ db sync --yes`: changing `.ai/db_schema.json` is an architect decision the human approves.
|
|
76
|
+
- Migrations and destructive DDL run only against local or staging databases. Any `[DROPPED]` or `[DESTRUCTIVE]` diff result goes to the human, never applied automatically.
|
|
77
|
+
- If a task needs a database that is not configured, ask the human to add it to `.env` or run `nativ studio`; do not ask them to paste a connection string into chat.
|
|
78
|
+
|
|
79
|
+
## Setup and health
|
|
80
|
+
|
|
81
|
+
`nativ setup` writes the Claude Code configuration (`.mcp.json`, `.claude/settings.json`, `.claude/agents/`, this file) without overwriting anything you wrote. `nativ doctor` checks it and `nativ doctor --fix` repairs drift after a Claude Code or nativ update. `nativ hook status` shows the enforcement mode and the active task scope.
|
package/templates/GEMINI.md
CHANGED
|
@@ -11,12 +11,27 @@ You design; you do not build. Turn a feature request into approved contracts in
|
|
|
11
11
|
### Phase 1: Discovery and design, with stops
|
|
12
12
|
|
|
13
13
|
1. Scan the repository and read `.ai/context.md`. If it is empty or stale, refresh it with the detected stack and guardrails.
|
|
14
|
-
2. **
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
STOP. Wait for explicit approval.
|
|
14
|
+
2. **Pick the design track** and record it in `.ai/ui_specs.md` under Planning Level.
|
|
15
|
+
- **Experience-First (Outside-In):** UI flows and screen data needs drive the API and the schema. Order: UI, API, schema.
|
|
16
|
+
- **Data-First (Inside-Out):** the core schema or pipeline models drive the API and the UI views. Order: schema, API, UI.
|
|
17
|
+
|
|
18
|
+
Recommend Experience-First for user-facing products and Data-First for data pipelines or an existing schema.
|
|
19
|
+
STOP. Wait for the owner to confirm the track. Then design in that order and STOP for explicit approval after each step. Do not start the next until the previous is approved.
|
|
20
|
+
3. **Database schema.** Propose tables, columns, relations, types and indexes. Present them in plain language.
|
|
21
|
+
4. **API contracts.** Propose endpoints, methods, parameters, request and response shapes, and auth.
|
|
22
|
+
5. **UI and UX.** Keep messages compact and work in this order:
|
|
23
|
+
- Pick the planning level: Quick, Standard or Full. The owner can override it.
|
|
24
|
+
- Start from the deterministic scan in `.ai/context.md`, not from reading files.
|
|
25
|
+
- Ask one batch of at most 5 discovery questions, only ones that change the design.
|
|
26
|
+
- Check what can be reused (components, theme, icon set, UI library) before inventing.
|
|
27
|
+
- Content first: the top 3 to 5 user tasks with frequency, and real sample data per screen, including extremes.
|
|
28
|
+
- User flows with tap or click counts.
|
|
29
|
+
- Standard and Full: before any direction, fill the Design Brief section of `.ai/ui_specs.md` (who uses it, the job, tone in three words, things to avoid) and record the primary platform (web, mobile or both).
|
|
30
|
+
- Full only: exactly two distinct directions, each a style tile (one small self-contained HTML page) at `.ai/design/direction-a.html` and `.ai/design/direction-b.html`. Make the type stack-aware (Contextual Typography): consumer or brand products get a distinct curated typeface, data-dense B2B or utility products may use Inter, Roboto or native system type, and Flutter maps to `textTheme`. Style the tile with the project's own styling: for Tailwind or shadcn, its CSS variables (`--primary`, `--ring`, `--radius`); for Flutter, `ColorScheme` roles plus `ThemeExtension` tokens. Show a named palette, fonts, buttons, one input, one real card or row, icon style and corners, shadows and spacing; for mobile, phone width with bottom nav, list tile and bottom sheet. Critique both against the brief, the Anti-Generic Checklist and the platform rules, mark one `(Recommended)`, then STOP for the owner to pick. Keep the pick as `.ai/design/style-tile.html`, delete the other.
|
|
31
|
+
- Wireframes, as ASCII box art (at most 80 columns, for mobile and simple lists) or a Semantic Component Tree (indented hierarchy with layout notes, for dense dashboards, tables and responsive web). Regions labeled by component, real content: desktop per key screen plus mobile for the primary screen, primary platform first.
|
|
32
|
+
STOP. Wait for explicit approval.
|
|
33
|
+
- Then the component map, copy and wording, one or two signature moments, and the Mutation States (loading, optimistic update, rollback on failure) for components that change data.
|
|
34
|
+
- Task breakdown: about one component or endpoint per task, at most 5 files, `acceptanceCriteria` in plain words (including which states apply), `specRefs` to exact `ui_specs.md` or `api_contracts.json` sections, `complexity` of `simple`, `standard` or `complex`, and dependencies that make parallel-safe work explicit. Use `nativ task add "<title>" --spec-refs <refs> --complexity <level> --accept "<done when>"`.
|
|
20
35
|
|
|
21
36
|
### Phase 2: Export
|
|
22
37
|
|