@noir-ai/cli 1.9.3-beta.1 → 1.9.4-beta.1

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/README.md CHANGED
@@ -30,7 +30,7 @@ noir init # scaffolds .noir/ + host wiring + skills where suppo
30
30
  # 2. Open the project in Claude Code (the v1 host) → it auto-spawns the Noir MCP server.
31
31
  ```
32
32
 
33
- `noir init` defaults to Claude: it creates `.noir/` (project id, `config.yml`, `NOIR.md`, the SQLite store), root `.mcp.json`, a managed `CLAUDE.md` `@import` block, and the **34 native `noir-*` skills** (33 builtins + 1 integration) in `.claude/skills/`. Pass `--host` for agents-md, Gemini, Cursor, or OpenCode; only Claude and Cursor emit skills. There is no plugin and no marketplace — `noir init` / `noir sync` overwrite the managed `noir-*` namespace idempotently.
33
+ `noir init` defaults to Claude: it creates `.noir/` (project id, `config.yml`, `NOIR.md`, the SQLite store), root `.mcp.json`, a managed `CLAUDE.md` `@import` block, and the **27 native `noir-*` skills** (26 builtins + 1 integration) in `.claude/skills/`. Pass `--host` for agents-md, Gemini, Cursor, or OpenCode; only Claude and Cursor emit skills. There is no plugin and no marketplace — `noir init` / `noir sync` overwrite the managed `noir-*` namespace idempotently.
34
34
 
35
35
  ## Commands
36
36
 
package/dist/bin.js CHANGED
@@ -777,13 +777,15 @@ async function status(opts) {
777
777
  // src/commands/task.ts
778
778
  import { PHASES } from "@noir-ai/workflow";
779
779
  var PHASE_SKILL = {
780
- intake: "noir-intake",
781
- clarify: "noir-clarify",
780
+ // C3 curation (2026-08-10): intake+clarify merged into brainstorming;
781
+ // execute → executing-plans; verify → verifying; document → wrap.
782
+ intake: "noir-brainstorming",
783
+ clarify: "noir-brainstorming",
782
784
  spec: "noir-spec",
783
- plan: "noir-plan",
784
- execute: "noir-execute",
785
- verify: "noir-verify",
786
- document: "noir-document"
785
+ plan: "noir-planning",
786
+ execute: "noir-executing-plans",
787
+ verify: "noir-verifying",
788
+ document: "noir-wrap"
787
789
  };
788
790
  function skillFor(phase) {
789
791
  if (typeof phase !== "string") return null;
@@ -1906,41 +1908,38 @@ async function memoryConsolidate(opts) {
1906
1908
  import { claudeAdapter } from "@noir-ai/adapters";
1907
1909
  import { loadProjectInfo as loadProjectInfo6 } from "@noir-ai/core";
1908
1910
  import {
1911
+ buildRegistry,
1909
1912
  discoverAll,
1910
- emitSkillsToDir
1913
+ emitSkillsToDir,
1914
+ lintSkill
1911
1915
  } from "@noir-ai/skills";
1912
1916
  var CATEGORY = {
1913
- "noir-brainstorm": "discovery",
1914
- "noir-intake": "discovery",
1915
- "noir-clarify": "discovery",
1916
- "noir-explore": "discovery",
1917
+ "noir-brainstorming": "discovery",
1918
+ "noir-sync": "discovery",
1919
+ "noir-checkpoint": "discovery",
1920
+ "noir-exploring": "discovery",
1917
1921
  "noir-spec": "spec",
1918
- "noir-plan": "plan",
1919
- "noir-execute": "execute",
1920
- "noir-tdd": "execute",
1921
- "noir-debug": "execute",
1922
+ "noir-planning": "plan",
1923
+ "noir-prd": "plan",
1924
+ "noir-executing-plans": "execute",
1925
+ "noir-test-driven-development": "execute",
1926
+ "noir-systematic-debugging": "execute",
1922
1927
  "noir-subagent": "execute",
1923
1928
  "noir-parallel": "execute",
1924
- "noir-verify": "verify",
1925
- "noir-review": "verify",
1929
+ "noir-verifying": "verify",
1926
1930
  "noir-security": "verify",
1927
- "noir-test": "verify",
1928
- "noir-document": "document",
1931
+ "noir-wrap": "document",
1929
1932
  "noir-readme": "document",
1930
- "noir-commit": "git",
1931
- "noir-branch": "git",
1932
- "noir-pr": "git",
1933
+ "noir-shipping": "git",
1933
1934
  "noir-worktree": "git",
1934
1935
  "noir-recall": "memory",
1935
1936
  "noir-remember": "memory",
1936
- "noir-checkpoint": "memory",
1937
1937
  "noir-context": "context",
1938
1938
  "noir-frontend": "domain",
1939
1939
  "noir-backend": "domain",
1940
1940
  "noir-doctor": "meta",
1941
- "noir-skill-author": "meta",
1942
- "noir-sync": "meta",
1943
- "noir-wrap": "meta"
1941
+ "noir-writing-skills": "meta",
1942
+ "noir-rules": "meta"
1944
1943
  };
1945
1944
  function categoryOf(name) {
1946
1945
  const mapped = CATEGORY[name];
@@ -1949,7 +1948,9 @@ function categoryOf(name) {
1949
1948
  }
1950
1949
  function toRow(s, kind = "builtin") {
1951
1950
  const description = typeof s.frontmatter.description === "string" ? s.frontmatter.description : "";
1952
- return { name: s.name, category: categoryOf(s.name), description, kind };
1951
+ const status2 = s.skillMd.includes("> **Stub:**") ? "stub" : "full";
1952
+ const category = s.frontmatter.metadata?.category?.trim() || categoryOf(s.name);
1953
+ return { name: s.name, category, description, kind, status: status2 };
1953
1954
  }
1954
1955
  function truncate(text, max) {
1955
1956
  if (text.length <= max) return text;
@@ -1990,9 +1991,10 @@ async function skillsList(opts) {
1990
1991
  Skill: r.name,
1991
1992
  Kind: r.kind,
1992
1993
  Category: r.category,
1994
+ Status: r.status,
1993
1995
  Description: truncate(r.description, 80)
1994
1996
  })),
1995
- ["Skill", "Kind", "Category", "Description"],
1997
+ ["Skill", "Kind", "Category", "Status", "Description"],
1996
1998
  opts
1997
1999
  );
1998
2000
  }
@@ -2039,6 +2041,76 @@ async function skillsSync(opts) {
2039
2041
  );
2040
2042
  }
2041
2043
  }
2044
+ async function skillsLint(opts) {
2045
+ let skills;
2046
+ try {
2047
+ const all = discoverAll();
2048
+ skills = [...all.builtins, ...all.integrations].map(lintSkill);
2049
+ } catch (err) {
2050
+ fail(
2051
+ EXIT.ERROR,
2052
+ `skills lint: could not lint skills (${err instanceof Error ? err.message : String(err)})`,
2053
+ opts
2054
+ );
2055
+ }
2056
+ const errored = skills.filter((s) => s.errors.length > 0);
2057
+ const warned = skills.filter((s) => s.warnings.length > 0 && s.errors.length === 0);
2058
+ const data = { count: skills.length, errored: errored.length, skills };
2059
+ if (opts.json === true) {
2060
+ process.stdout.write(`${JSON.stringify({ ok: errored.length === 0, data })}
2061
+ `);
2062
+ return;
2063
+ }
2064
+ if (errored.length === 0) {
2065
+ log(`noir skills lint \u2014 ${skills.length} skills, all validate clean.`, opts);
2066
+ } else {
2067
+ warn(
2068
+ `noir skills lint \u2014 ${errored.length} skill${errored.length === 1 ? "" : "s"} FAIL validation:`,
2069
+ opts
2070
+ );
2071
+ }
2072
+ for (const s of errored) {
2073
+ for (const e of s.errors) warn(` ${s.name}: ${e}`, opts);
2074
+ }
2075
+ if (warned.length > 0) {
2076
+ info(` ${warned.length} skill${warned.length === 1 ? "" : "s"} carry lint warnings:`, opts);
2077
+ for (const s of warned) {
2078
+ for (const w of s.warnings) info(` ${s.name}: ${w}`, opts);
2079
+ }
2080
+ }
2081
+ }
2082
+ async function skillsRegistry(opts) {
2083
+ let reg;
2084
+ try {
2085
+ reg = buildRegistry();
2086
+ } catch (err) {
2087
+ fail(
2088
+ EXIT.ERROR,
2089
+ `skills registry: could not build registry (${err instanceof Error ? err.message : String(err)})`,
2090
+ opts
2091
+ );
2092
+ }
2093
+ const data = { count: reg.length, skills: reg };
2094
+ if (opts.json === true) {
2095
+ process.stdout.write(`${JSON.stringify({ ok: true, data })}
2096
+ `);
2097
+ return;
2098
+ }
2099
+ log(`noir skills registry \u2014 ${reg.length} skills.`, opts);
2100
+ table(
2101
+ reg.map((r) => ({
2102
+ Skill: r.name,
2103
+ Kind: r.kind,
2104
+ Category: r.category,
2105
+ Version: r.version,
2106
+ Status: r.status,
2107
+ Refs: String(r.referenceCount),
2108
+ Lines: String(r.lines)
2109
+ })),
2110
+ ["Skill", "Kind", "Category", "Version", "Status", "Refs", "Lines"],
2111
+ opts
2112
+ );
2113
+ }
2042
2114
 
2043
2115
  // src/bin.ts
2044
2116
  function buildPaletteCommandsForTui() {
@@ -2385,8 +2457,14 @@ function createProgram() {
2385
2457
  skillsGrp.command("sync").description("re-emit skills to the host skills dir").action(async (...args) => {
2386
2458
  await skillsSync(toCliOptions(actionGlobals(args)));
2387
2459
  });
2460
+ skillsGrp.command("lint").description("structural quality gate over the shipped pack (C3)").action(async (...args) => {
2461
+ await skillsLint(toCliOptions(actionGlobals(args)));
2462
+ });
2463
+ skillsGrp.command("registry").description("emit the runtime-derived skill registry (C3)").action(async (...args) => {
2464
+ await skillsRegistry(toCliOptions(actionGlobals(args)));
2465
+ });
2388
2466
  skillsGrp.action(() => {
2389
- throw new NoirCliError(EXIT.USAGE, "Usage: noir skills list|sync");
2467
+ throw new NoirCliError(EXIT.USAGE, "Usage: noir skills list|sync|lint|registry");
2390
2468
  });
2391
2469
  const taskGrp = program2.command("task").description("workflow task control");
2392
2470
  taskGrp.command("new").description("start a new workflow task").requiredOption("--slug <slug>", "task slug").option("--mode <mode>", "full | quick").action(async (...args) => {