oris-skills 3.0.2 → 3.0.3
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/.cursor-plugin/plugin.json +1 -1
- package/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/references/conventions.md +6 -7
- package/scripts/tests/test-routing-lifecycle.mjs +52 -2
- package/scripts/tests/test-skill-self-contained.mjs +41 -23
- package/scripts/tests/test-skill-style.mjs +3 -2
- package/skills/oris-flow/SKILL.md +7 -31
- package/skills/oris-flow/agents/openai.yaml +2 -2
- package/skills/oris-flow/references/question-navigator.md +82 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oris-skills",
|
|
3
3
|
"description": "Oris Skills: one entry point (/oris-flow) and a guided discovery-to-implementation flow. Cross-model: Cursor, Claude Code, Codex.",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.3",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Davide Baldassarre"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.0.3 - 2026-07-14
|
|
4
|
+
|
|
5
|
+
- **Native route questions restored.** Ambiguous `/oris-flow` requests now traverse a
|
|
6
|
+
bounded, outcome-based navigator through Cursor `AskQuestion` or Claude
|
|
7
|
+
`AskUserQuestion`; text fallback is used only when no question tool is available.
|
|
8
|
+
- **Question capability is detected, not inferred from mode.** Cursor Agent Mode can use
|
|
9
|
+
its native question UI when the runtime exposes it.
|
|
10
|
+
- **Release drift is blocked.** Package and Cursor plugin versions must match, and real
|
|
11
|
+
temporary Cursor and Claude installs verify self-contained references and version
|
|
12
|
+
markers.
|
|
13
|
+
|
|
3
14
|
## 3.0.1 - 2026-07-10
|
|
4
15
|
|
|
5
16
|
The lean core: one skill, one durable store, evidence on both sides of the repo boundary.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oris-skills",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Oris Skills: one entry point (/oris-flow) and a guided discovery-to-implementation flow for Cursor, Claude Code, and Codex.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Davide Baldassarre",
|
|
@@ -27,15 +27,14 @@ The `oris-skills` CLI is NOT installed globally. ALWAYS invoke it as `npx oris-s
|
|
|
27
27
|
## Questions
|
|
28
28
|
|
|
29
29
|
- ASK through the platform's question tool — Claude `AskUserQuestion`, Cursor `AskQuestion`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
as a lettered list.
|
|
30
|
+
— whenever it is present in the current tool list. Never infer availability from the
|
|
31
|
+
platform mode. A question turn = ONE call to it. Chat text is a fallback, NOT a choice:
|
|
32
|
+
use it ONLY when no question tool is present or the question is open-ended.
|
|
34
33
|
- Oris gates and interview questions ALWAYS qualify for the tool: the answer decides the
|
|
35
34
|
next step. NEVER skip the tool because an answer "looks like a sensible default".
|
|
36
|
-
- FIT
|
|
37
|
-
MORE
|
|
38
|
-
text
|
|
35
|
+
- FIT both platforms: every question has 2–4 explicit options, including meta-options.
|
|
36
|
+
MORE choices → split them into successive native questions; never flatten them to chat
|
|
37
|
+
text while the tool is present.
|
|
39
38
|
- ONE question per turn. Recommended answer FIRST.
|
|
40
39
|
- VISIBILITY: assume the user sees ONLY what the question tool itself renders — chat text
|
|
41
40
|
emitted in the same turn as the tool call can be hidden by the platform UI. Therefore
|
|
@@ -17,6 +17,22 @@ function exists(relativePath) {
|
|
|
17
17
|
return fs.existsSync(path.join(root, relativePath));
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
function routeDestinations(text) {
|
|
21
|
+
return [...text.matchAll(/^\|\s*[a-z-]+\s*\|[^\n]*\|\s*`(skills\/oris-flow\/references\/[a-z-]+\.md)`\s*\|$/gm)]
|
|
22
|
+
.map((match) => match[1]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function navigatorNodes(text) {
|
|
26
|
+
const nodes = new Map();
|
|
27
|
+
const matches = [...text.matchAll(/^### `([a-z-]+)`\r?\n([\s\S]*?)(?=^### `|^## |(?![\s\S]))/gm)];
|
|
28
|
+
for (const match of matches) {
|
|
29
|
+
const options = [...match[2].matchAll(/^- `[^`]+` → `(node|route|explain):([a-z-]+)`/gm)]
|
|
30
|
+
.map((option) => ({ type: option[1], target: option[2] }));
|
|
31
|
+
nodes.set(match[1], options);
|
|
32
|
+
}
|
|
33
|
+
return nodes;
|
|
34
|
+
}
|
|
35
|
+
|
|
20
36
|
function runCli(args, homeDir) {
|
|
21
37
|
return childProcess.spawnSync(process.execPath, ["scripts/oris-skills.mjs", ...args], {
|
|
22
38
|
cwd: root,
|
|
@@ -40,18 +56,46 @@ test("plugin manifest skills all exist and match front-matter names", () => {
|
|
|
40
56
|
|
|
41
57
|
test("oris-flow route table destinations exist and routing stays in-chat", () => {
|
|
42
58
|
const text = read("skills/oris-flow/SKILL.md");
|
|
43
|
-
const destinations =
|
|
44
|
-
assert.
|
|
59
|
+
const destinations = routeDestinations(text);
|
|
60
|
+
assert.equal(destinations.length, 16, "route table must list all 16 destinations");
|
|
45
61
|
for (const destination of destinations) assert.equal(exists(destination), true, destination);
|
|
46
62
|
assert.deepEqual(destinations, [...new Set(destinations)], "route destinations must be unique");
|
|
47
63
|
assert.match(text, /NEVER tell the user to type another command/i);
|
|
48
64
|
assert.match(text, /route to the interview owner/i);
|
|
49
65
|
assert.match(text, /references\/conventions\.md/);
|
|
66
|
+
assert.match(text, /references\/question-navigator\.md/);
|
|
67
|
+
assert.doesNotMatch(text, /plain-text lettered list|present it as a plain-text/i);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("question navigator covers every route within the portable option cap", () => {
|
|
71
|
+
const skill = read("skills/oris-flow/SKILL.md");
|
|
72
|
+
const navigator = read("skills/oris-flow/references/question-navigator.md");
|
|
73
|
+
const routes = routeDestinations(skill).map((destination) => path.basename(destination, ".md")).sort();
|
|
74
|
+
const nodes = navigatorNodes(navigator);
|
|
75
|
+
assert.ok(nodes.has("root"), "navigator starts at root");
|
|
76
|
+
|
|
77
|
+
const leaves = [];
|
|
78
|
+
for (const [name, options] of nodes) {
|
|
79
|
+
assert.ok(options.length >= 2 && options.length <= 4, `${name} has 2-4 options`);
|
|
80
|
+
assert.deepEqual(
|
|
81
|
+
options.filter((option) => option.type === "explain"),
|
|
82
|
+
[{ type: "explain", target: name }],
|
|
83
|
+
`${name} has one explain option returning to itself`,
|
|
84
|
+
);
|
|
85
|
+
for (const option of options) {
|
|
86
|
+
if (option.type === "node") assert.ok(nodes.has(option.target), `${name} targets existing node ${option.target}`);
|
|
87
|
+
if (option.type === "route") leaves.push(option.target);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
assert.deepEqual(leaves.sort(), routes, "every route appears exactly once as a navigator leaf");
|
|
50
91
|
});
|
|
51
92
|
|
|
52
93
|
test("shared conventions centralize question, language, and gate rules", () => {
|
|
53
94
|
const conventions = read("references/conventions.md");
|
|
54
95
|
assert.match(conventions, /ONE question per turn/i);
|
|
96
|
+
assert.match(conventions, /whenever it is present in the current tool list/i);
|
|
97
|
+
assert.match(conventions, /2–4 explicit options/i);
|
|
98
|
+
assert.doesNotMatch(conventions, /Cursor Agent Mode|Cursor `AskQuestion`\s*\(Plan Mode\)/i);
|
|
55
99
|
assert.match(conventions, /Explain the options.*Spiega le opzioni/s);
|
|
56
100
|
assert.match(conventions, /NEVER write documents, code, settings, Git, or DevOps without explicit user confirmation/i);
|
|
57
101
|
assert.match(conventions, /`Basta domande — procedi`/);
|
|
@@ -64,6 +108,12 @@ test("shared conventions centralize question, language, and gate rules", () => {
|
|
|
64
108
|
assert.equal(exists("references/questions.md"), false, "questions.md was merged into conventions.md");
|
|
65
109
|
});
|
|
66
110
|
|
|
111
|
+
test("package and plugin expose one release version", () => {
|
|
112
|
+
const packageJson = JSON.parse(read("package.json"));
|
|
113
|
+
const plugin = JSON.parse(read(".cursor-plugin/plugin.json"));
|
|
114
|
+
assert.equal(plugin.version, packageJson.version);
|
|
115
|
+
});
|
|
116
|
+
|
|
67
117
|
test("every skill points at conventions instead of repeating shared rules", () => {
|
|
68
118
|
const manifest = JSON.parse(read(".cursor-plugin/plugin.json"));
|
|
69
119
|
for (const entry of manifest.skills) {
|
|
@@ -28,38 +28,56 @@ function markdownFiles(dir) {
|
|
|
28
28
|
// A standalone skill (Claude/Cursor) has no bundle root above it, so every reference it
|
|
29
29
|
// points to must resolve inside the skill folder — the regression that broke
|
|
30
30
|
// `references/conventions.md` at runtime.
|
|
31
|
-
test("installed Claude
|
|
31
|
+
test("installed Cursor and Claude skills are self-contained and version-aligned", () => {
|
|
32
32
|
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), "oris-self-contained-"));
|
|
33
33
|
try {
|
|
34
|
+
fs.mkdirSync(path.join(homeDir, ".cursor"), { recursive: true });
|
|
34
35
|
fs.mkdirSync(path.join(homeDir, ".claude"), { recursive: true });
|
|
35
|
-
const result = runCli(["install", "--force"], homeDir);
|
|
36
|
+
const result = runCli(["install", "--force", "--no-mcp", "--agents", "cursor,claude"], homeDir);
|
|
36
37
|
assert.equal(result.status, 0, result.stderr);
|
|
37
38
|
|
|
38
|
-
const
|
|
39
|
-
|
|
39
|
+
const packageVersion = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8")).version;
|
|
40
|
+
const installManifest = JSON.parse(
|
|
41
|
+
fs.readFileSync(path.join(homeDir, ".oris", "oris-skills", ".oris-skills-install.json"), "utf8"),
|
|
42
|
+
);
|
|
43
|
+
assert.equal(installManifest.version, packageVersion, "bundle manifest matches package version");
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
assert.ok(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
for (const agent of ["cursor", "claude"]) {
|
|
46
|
+
const skill = path.join(homeDir, `.${agent}`, "skills", "oris-flow");
|
|
47
|
+
assert.ok(fs.existsSync(skill), `${agent} oris-flow skill was installed`);
|
|
48
|
+
|
|
49
|
+
for (const name of ["conventions.md", "doc-policy.md", "question-navigator.md"]) {
|
|
50
|
+
assert.ok(
|
|
51
|
+
fs.existsSync(path.join(skill, "references", name)),
|
|
52
|
+
`${agent} bundles ${name}`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
const files = markdownFiles(skill);
|
|
57
|
+
const pathToken = /(?:references|templates|agents)\/[A-Za-z0-9._/-]+\.(?:md|json|toml)/g;
|
|
58
|
+
const missing = [];
|
|
59
|
+
let bundlePrefixLeaks = 0;
|
|
60
|
+
for (const file of files) {
|
|
61
|
+
const text = fs.readFileSync(file, "utf8");
|
|
62
|
+
if (text.includes("skills/oris-flow/")) bundlePrefixLeaks += 1;
|
|
63
|
+
for (const cited of text.match(pathToken) ?? []) {
|
|
64
|
+
if (!fs.existsSync(path.join(skill, cited))) missing.push(`${path.basename(file)} → ${cited}`);
|
|
65
|
+
}
|
|
59
66
|
}
|
|
67
|
+
assert.equal(bundlePrefixLeaks, 0, `${agent} has no bundle-root path leaks`);
|
|
68
|
+
assert.deepEqual(missing, [], `${agent} cited references resolve`);
|
|
69
|
+
|
|
70
|
+
const navigator = fs.readFileSync(path.join(skill, "references", "question-navigator.md"), "utf8");
|
|
71
|
+
const leaves = [...navigator.matchAll(/`route:([a-z-]+)`/g)].map((match) => match[1]);
|
|
72
|
+
assert.equal(leaves.length, 16, `${agent} navigator keeps all route leaves`);
|
|
73
|
+
for (const match of navigator.matchAll(/^### `([a-z-]+)`\r?\n([\s\S]*?)(?=^### `|^## |(?![\s\S]))/gm)) {
|
|
74
|
+
const options = match[2].match(/^- `[^`]+` → `/gm) ?? [];
|
|
75
|
+
assert.ok(options.length >= 2 && options.length <= 4, `${agent} ${match[1]} keeps 2-4 options`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const marker = JSON.parse(fs.readFileSync(path.join(skill, ".oris-skills-managed.json"), "utf8"));
|
|
79
|
+
assert.equal(marker.version, packageVersion, `${agent} marker matches package version`);
|
|
60
80
|
}
|
|
61
|
-
assert.equal(bundlePrefixLeaks, 0, "no `skills/oris-flow/` paths remain in the standalone skill");
|
|
62
|
-
assert.deepEqual(missing, [], "every cited reference resolves inside the skill");
|
|
63
81
|
} finally {
|
|
64
82
|
fs.rmSync(homeDir, { recursive: true, force: true });
|
|
65
83
|
}
|
|
@@ -50,8 +50,9 @@ test("skill style: oris-flow", () => {
|
|
|
50
50
|
|
|
51
51
|
test("every route reference carries the style and resolves its handles", () => {
|
|
52
52
|
const skillText = fs.readFileSync(path.join(skillsRoot, "oris-flow", "SKILL.md"), "utf8");
|
|
53
|
-
const routes = [...skillText.matchAll(
|
|
54
|
-
|
|
53
|
+
const routes = [...skillText.matchAll(/^\|\s*[a-z-]+\s*\|[^\n]*\|\s*`skills\/oris-flow\/references\/([a-z-]+\.md)`\s*\|$/gm)]
|
|
54
|
+
.map((match) => match[1]);
|
|
55
|
+
assert.equal(routes.length, 16, `router table lists all routes (found ${routes.length})`);
|
|
55
56
|
assert.deepEqual(routes, [...new Set(routes)], "route destinations are unique");
|
|
56
57
|
const referencesDir = path.join(skillsRoot, "oris-flow", "references");
|
|
57
58
|
for (const file of routes) {
|
|
@@ -47,8 +47,7 @@ Match the desired outcome to ONE route, then apply its reference:
|
|
|
47
47
|
3. CHANGED spec on a feature that already has task docs or code → change, not discover —
|
|
48
48
|
change owns the delta and the history. Spec unchanged but code/reality moved on and the
|
|
49
49
|
task docs lag behind → docs, not change.
|
|
50
|
-
4. BROKEN behavior → fix. NEW planned work → implement.
|
|
51
|
-
fix" gets exactly one follow-up question to split them.
|
|
50
|
+
4. BROKEN behavior → fix. NEW planned work → implement.
|
|
52
51
|
5. EMPTY directory or from-scratch intent → new. Existing repo never touched by Oris
|
|
53
52
|
(no `AGENTS.md`, no `.oris-flow/`) → recommend setup first; respect the user's choice.
|
|
54
53
|
6. COMMIT staged/working changes with the standard → commit. OPEN or update a pull request
|
|
@@ -58,34 +57,11 @@ Match the desired outcome to ONE route, then apply its reference:
|
|
|
58
57
|
8. CONTINUE elsewhere — session ending, context full, "pass this to another agent" →
|
|
59
58
|
handoff.
|
|
60
59
|
|
|
61
|
-
##
|
|
60
|
+
## Low-confidence navigator
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
- Setup repository
|
|
68
|
-
- New project from scratch
|
|
69
|
-
- Capture an idea or bug as a work item (triage)
|
|
70
|
-
- Understand / define behavior (discovery)
|
|
71
|
-
- Acceptance criteria
|
|
72
|
-
- Technical plan
|
|
73
|
-
- Implement or fix
|
|
74
|
-
- Verify acceptance criteria
|
|
75
|
-
- Spec changed: update feature docs
|
|
76
|
-
- Architecture review
|
|
77
|
-
- Update docs
|
|
78
|
-
- Commit changes
|
|
79
|
-
- Open a pull request
|
|
80
|
-
- Hand off this session (continue elsewhere)
|
|
81
|
-
- Help
|
|
82
|
-
- Explain the options / Spiega le opzioni
|
|
83
|
-
|
|
84
|
-
IF "Explain the options" → ONE message that contains BOTH: one explanation line per
|
|
85
|
-
option, THEN the full lettered list again below the explanations. Re-asking without the
|
|
86
|
-
explanations visible in that same message is the failure this rule exists to prevent.
|
|
87
|
-
Every other label maps to its route in the table above; "Implement or fix" is the one
|
|
88
|
-
label that splits, with exactly one follow-up question (Precedence 4).
|
|
62
|
+
IF intent is unclear → READ `skills/oris-flow/references/question-navigator.md` and APPLY
|
|
63
|
+
it in the same chat. It owns the native, outcome-based route selection; the router does
|
|
64
|
+
not carry or flatten its menu.
|
|
89
65
|
|
|
90
66
|
## Never
|
|
91
67
|
|
|
@@ -93,9 +69,9 @@ label that splits, with exactly one follow-up question (Precedence 4).
|
|
|
93
69
|
- Write anything — the route's reference owns every gate.
|
|
94
70
|
- Hand the user a command or skill name to type — enter the route yourself.
|
|
95
71
|
- Route to implement while the plan itself is in question.
|
|
96
|
-
- Keep interviewing here:
|
|
72
|
+
- Keep interviewing here: unclear intent belongs to the question navigator.
|
|
97
73
|
|
|
98
74
|
## Done when
|
|
99
75
|
|
|
100
|
-
- [ ] One route entered and applied in the same chat
|
|
76
|
+
- [ ] One route entered and applied in the same chat.
|
|
101
77
|
- [ ] No writes happened before the route's own gate.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Oris Flow"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "Use $oris-flow to enter the right Oris
|
|
3
|
+
short_description: "Route, build, and verify with Oris"
|
|
4
|
+
default_prompt: "Use $oris-flow to enter the right Oris route."
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Question Navigator
|
|
2
|
+
|
|
3
|
+
Choose one route when the user's intent is unclear. This is a deep routing module, not
|
|
4
|
+
a route: selecting a leaf enters that route in the same chat.
|
|
5
|
+
|
|
6
|
+
RULES: `references/conventions.md`.
|
|
7
|
+
|
|
8
|
+
## Protocol
|
|
9
|
+
|
|
10
|
+
START at `root`. ASK exactly the options of the current node through the platform's
|
|
11
|
+
question tool. A `node:` target opens that node; a `route:` target enters the referenced
|
|
12
|
+
route immediately.
|
|
13
|
+
|
|
14
|
+
IF no question tool is present → show only the current node as a lettered list, accept
|
|
15
|
+
one answer, then continue through the same tree. Never flatten multiple nodes.
|
|
16
|
+
|
|
17
|
+
IF `explain` is selected → re-ask the same node with every option's description and
|
|
18
|
+
consequence visible inside the question call.
|
|
19
|
+
|
|
20
|
+
## Tree
|
|
21
|
+
|
|
22
|
+
### `root`
|
|
23
|
+
- `Understand or decide` → `node:understand` — Clarify behavior, code, or planned work.
|
|
24
|
+
- `Build or verify` → `node:build` — Implement, repair, or check real behavior.
|
|
25
|
+
- `Manage or deliver` → `node:manage` — Start, document, publish, continue, or get help.
|
|
26
|
+
- `Explain the options` → `explain:root` — Describe these groups, then re-ask this node.
|
|
27
|
+
|
|
28
|
+
### `understand`
|
|
29
|
+
- `Understand behavior` → `node:behavior` — Define, test, or change product behavior.
|
|
30
|
+
- `Decide the solution` → `node:solution` — Plan implementation or review architecture.
|
|
31
|
+
- `Capture work for later` → `route:triage` — Create an agent-ready work item without doing it.
|
|
32
|
+
- `Explain the options` → `explain:understand` — Describe these outcomes, then re-ask this node.
|
|
33
|
+
|
|
34
|
+
### `behavior`
|
|
35
|
+
- `Define desired behavior` → `route:discover` — Interview and document product behavior.
|
|
36
|
+
- `Define acceptance criteria` → `route:criteria` — Write testable business scenarios.
|
|
37
|
+
- `Update a changed specification` → `route:change` — Apply a confirmed behavior delta.
|
|
38
|
+
- `Explain the options` → `explain:behavior` — Describe these routes, then re-ask this node.
|
|
39
|
+
|
|
40
|
+
### `solution`
|
|
41
|
+
- `Create a technical plan` → `route:plan` — Produce an execution-ready implementation plan.
|
|
42
|
+
- `Review architecture` → `route:architecture` — Find deepening and refactor opportunities.
|
|
43
|
+
- `Explain the options` → `explain:solution` — Describe these routes, then re-ask this node.
|
|
44
|
+
|
|
45
|
+
### `build`
|
|
46
|
+
- `Implement planned work` → `route:implement` — Build from a plan or confirmed scope.
|
|
47
|
+
- `Fix broken behavior` → `route:fix` — Diagnose and repair a regression or failed check.
|
|
48
|
+
- `Verify acceptance criteria` → `route:verify` — Check criteria against the real product.
|
|
49
|
+
- `Explain the options` → `explain:build` — Describe these routes, then re-ask this node.
|
|
50
|
+
|
|
51
|
+
### `manage`
|
|
52
|
+
- `Start or prepare a project` → `node:start` — Bootstrap or map a repository.
|
|
53
|
+
- `Document or deliver work` → `node:deliver` — Update docs, commit, or open a pull request.
|
|
54
|
+
- `Continue or get help` → `node:continue` — Transfer context or troubleshoot Oris.
|
|
55
|
+
- `Explain the options` → `explain:manage` — Describe these outcomes, then re-ask this node.
|
|
56
|
+
|
|
57
|
+
### `start`
|
|
58
|
+
- `New project from scratch` → `route:new` — Bootstrap an empty or scaffold-only repository.
|
|
59
|
+
- `Set up an existing repository` → `route:setup` — Map an existing repository for Oris.
|
|
60
|
+
- `Explain the options` → `explain:start` — Describe these routes, then re-ask this node.
|
|
61
|
+
|
|
62
|
+
### `deliver`
|
|
63
|
+
- `Update task documentation` → `route:docs` — Align task docs with current reality.
|
|
64
|
+
- `Commit changes` → `route:commit` — Package changes with the Oris Git standard.
|
|
65
|
+
- `Open or update a pull request` → `route:pr` — Publish the branch for review.
|
|
66
|
+
- `Explain the options` → `explain:deliver` — Describe these routes, then re-ask this node.
|
|
67
|
+
|
|
68
|
+
### `continue`
|
|
69
|
+
- `Hand off this session` → `route:handoff` — Package state for another session or agent.
|
|
70
|
+
- `Get Oris help` → `route:help` — Explain installation, usage, or troubleshooting.
|
|
71
|
+
- `Explain the options` → `explain:continue` — Describe these routes, then re-ask this node.
|
|
72
|
+
|
|
73
|
+
## Never
|
|
74
|
+
|
|
75
|
+
- Ask about a route the user's clear intent already selected.
|
|
76
|
+
- Present options from more than one node in a single question.
|
|
77
|
+
- Enter two routes, or stop between a leaf selection and its route.
|
|
78
|
+
|
|
79
|
+
## Done when
|
|
80
|
+
|
|
81
|
+
- [ ] One leaf selected through native questions, or the same node-by-node text fallback.
|
|
82
|
+
- [ ] The selected route entered in the same chat.
|