@frehilm/ordna-core 0.1.4 → 0.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/README.md +34 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -1
- package/dist/config.js.map +1 -1
- package/dist/git.d.ts +10 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +14 -27
- package/dist/git.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +18 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js.map +1 -1
- package/dist/storage/auto-detect.d.ts +82 -0
- package/dist/storage/auto-detect.d.ts.map +1 -0
- package/dist/storage/auto-detect.js +158 -0
- package/dist/storage/auto-detect.js.map +1 -0
- package/dist/storage/auto-push.d.ts +36 -0
- package/dist/storage/auto-push.d.ts.map +1 -0
- package/dist/storage/auto-push.js +100 -0
- package/dist/storage/auto-push.js.map +1 -0
- package/dist/storage/backend.d.ts +86 -0
- package/dist/storage/backend.d.ts.map +1 -0
- package/dist/storage/backend.js +14 -0
- package/dist/storage/backend.js.map +1 -0
- package/dist/storage/backends/file.d.ts +31 -0
- package/dist/storage/backends/file.d.ts.map +1 -0
- package/dist/storage/backends/file.js +213 -0
- package/dist/storage/backends/file.js.map +1 -0
- package/dist/storage/backends/hybrid.d.ts +39 -0
- package/dist/storage/backends/hybrid.d.ts.map +1 -0
- package/dist/storage/backends/hybrid.js +270 -0
- package/dist/storage/backends/hybrid.js.map +1 -0
- package/dist/storage/backends/namespace.d.ts +55 -0
- package/dist/storage/backends/namespace.d.ts.map +1 -0
- package/dist/storage/backends/namespace.js +907 -0
- package/dist/storage/backends/namespace.js.map +1 -0
- package/dist/storage/file-io.d.ts +38 -0
- package/dist/storage/file-io.d.ts.map +1 -0
- package/dist/storage/file-io.js +69 -0
- package/dist/storage/file-io.js.map +1 -0
- package/dist/storage/git-ref.d.ts +77 -0
- package/dist/storage/git-ref.d.ts.map +1 -0
- package/dist/storage/git-ref.js +184 -0
- package/dist/storage/git-ref.js.map +1 -0
- package/dist/storage/markdown.d.ts +17 -0
- package/dist/storage/markdown.d.ts.map +1 -0
- package/dist/storage/markdown.js +17 -0
- package/dist/storage/markdown.js.map +1 -0
- package/dist/storage/sync-ref.d.ts +82 -0
- package/dist/storage/sync-ref.d.ts.map +1 -0
- package/dist/storage/sync-ref.js +191 -0
- package/dist/storage/sync-ref.js.map +1 -0
- package/dist/store.d.ts +56 -8
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +93 -115
- package/dist/store.js.map +1 -1
- package/dist/watcher.d.ts +33 -1
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +12 -30
- package/dist/watcher.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -117,6 +117,40 @@ webPort: 7420 # consumed by @frehilm/ordna-web
|
|
|
117
117
|
|
|
118
118
|
The last entry of `statuses` is the **terminal status** for the dependency gate.
|
|
119
119
|
|
|
120
|
+
## Storage modes
|
|
121
|
+
|
|
122
|
+
Ordna ships three storage backends. Pick one with a single config key:
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
storage: file # default
|
|
126
|
+
# storage: hybrid # files + synced ID allocator + audit log in git
|
|
127
|
+
# storage: namespace # tasks as git refs; working tree stays clean
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
| Mode | Where tasks live | Working tree | Requires git | Use case |
|
|
131
|
+
|---|---|---|---|---|
|
|
132
|
+
| `file` | `tasks/*.md` | yes | no | Single-machine, agent-friendly, the default. |
|
|
133
|
+
| `hybrid` | `tasks/*.md` + `refs/ordna/state` (next-id + audit log) | yes | yes | Multi-machine collaboration; prevents two offline writers picking the same ID. |
|
|
134
|
+
| `namespace` | `refs/ordna/tasks/<id>` (blobs only) | untouched | yes | Decentralised, working-tree-clean, sync via standard `git push`/`fetch`. |
|
|
135
|
+
|
|
136
|
+
`schema: backlog` is only supported with `storage: file`. `hybrid` and `namespace` require a git repository.
|
|
137
|
+
|
|
138
|
+
### Auto-detection
|
|
139
|
+
|
|
140
|
+
When no `.ordna/config.yaml` exists, Ordna inspects the directory and picks a mode:
|
|
141
|
+
|
|
142
|
+
1. `refs/ordna/tasks/*` refs exist → `namespace`
|
|
143
|
+
2. `refs/ordna/state` ref exists → `hybrid`
|
|
144
|
+
3. `tasks/*.md` files exist → `file`
|
|
145
|
+
4. cwd is a git repo (none of the above) → prompts the user (TUI modal, web setup page, CLI 1/2/3 on TTY)
|
|
146
|
+
5. else (no git, no signals) → silently runs in `file` mode
|
|
147
|
+
|
|
148
|
+
Confident detections (1–3) auto-write `.ordna/config.yaml` so the choice is durable across runs and visible to anyone reading the repo.
|
|
149
|
+
|
|
150
|
+
### `ORDNA_STORAGE` env var
|
|
151
|
+
|
|
152
|
+
Set `ORDNA_STORAGE=file|hybrid|namespace` to override both the config file and auto-detection for a single process invocation. Useful for CI (predictable storage mode, no on-disk side effects) and for tests pinning a specific mode against arbitrary directories.
|
|
153
|
+
|
|
120
154
|
## Backlog.md compatibility
|
|
121
155
|
|
|
122
156
|
Ordna reads [Backlog.md](https://github.com/MrLesk/Backlog.md) repos out of the box. The parser normalizes both field sets:
|
package/dist/config.d.ts
CHANGED
|
@@ -7,6 +7,20 @@ export declare const configSchema: z.ZodObject<{
|
|
|
7
7
|
idPrefix: z.ZodDefault<z.ZodString>;
|
|
8
8
|
zeroPaddedIds: z.ZodDefault<z.ZodNumber>;
|
|
9
9
|
webPort: z.ZodDefault<z.ZodNumber>;
|
|
10
|
+
storage: z.ZodDefault<z.ZodEnum<["file", "hybrid", "namespace"]>>;
|
|
11
|
+
namespace: z.ZodDefault<z.ZodObject<{
|
|
12
|
+
pollIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
autoFetchIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
14
|
+
autoRenumberOnConflict: z.ZodDefault<z.ZodBoolean>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
pollIntervalMs: number;
|
|
17
|
+
autoFetchIntervalMs: number;
|
|
18
|
+
autoRenumberOnConflict: boolean;
|
|
19
|
+
}, {
|
|
20
|
+
pollIntervalMs?: number | undefined;
|
|
21
|
+
autoFetchIntervalMs?: number | undefined;
|
|
22
|
+
autoRenumberOnConflict?: boolean | undefined;
|
|
23
|
+
}>>;
|
|
10
24
|
}, "strip", z.ZodTypeAny, {
|
|
11
25
|
tasksDir: string;
|
|
12
26
|
schema: "ordna" | "backlog";
|
|
@@ -14,6 +28,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
14
28
|
idPrefix: string;
|
|
15
29
|
zeroPaddedIds: number;
|
|
16
30
|
webPort: number;
|
|
31
|
+
namespace: {
|
|
32
|
+
pollIntervalMs: number;
|
|
33
|
+
autoFetchIntervalMs: number;
|
|
34
|
+
autoRenumberOnConflict: boolean;
|
|
35
|
+
};
|
|
36
|
+
storage: "file" | "hybrid" | "namespace";
|
|
17
37
|
}, {
|
|
18
38
|
tasksDir?: string | undefined;
|
|
19
39
|
schema?: "ordna" | "backlog" | undefined;
|
|
@@ -21,6 +41,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
21
41
|
idPrefix?: string | undefined;
|
|
22
42
|
zeroPaddedIds?: number | undefined;
|
|
23
43
|
webPort?: number | undefined;
|
|
44
|
+
namespace?: {
|
|
45
|
+
pollIntervalMs?: number | undefined;
|
|
46
|
+
autoFetchIntervalMs?: number | undefined;
|
|
47
|
+
autoRenumberOnConflict?: boolean | undefined;
|
|
48
|
+
} | undefined;
|
|
49
|
+
storage?: "file" | "hybrid" | "namespace" | undefined;
|
|
24
50
|
}>;
|
|
25
51
|
export type OrdnaConfig = z.infer<typeof configSchema>;
|
|
26
52
|
export declare const DEFAULT_CONFIG: OrdnaConfig;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,eAAO,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkCvB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAEvD,eAAO,MAAM,cAAc,EAAE,WAAoC,CAAC;AAIlE,MAAM,WAAW,iBAAiB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,WAAW,CA6BvE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,SAAgB,GAAG,MAAM,CAEhF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,CAEjE"}
|
package/dist/config.js
CHANGED
|
@@ -9,6 +9,33 @@ export const configSchema = z.object({
|
|
|
9
9
|
idPrefix: z.string().default("T"),
|
|
10
10
|
zeroPaddedIds: z.number().int().min(0).max(10).default(3),
|
|
11
11
|
webPort: z.number().int().min(1).max(65535).default(7420),
|
|
12
|
+
// T-031: storage mode selector. "file" (current default) keeps the
|
|
13
|
+
// existing on-disk layout. "hybrid" adds a sync ref for the next-id
|
|
14
|
+
// allocator + audit log. "namespace" (T-032) stores tasks as git
|
|
15
|
+
// blobs under `refs/ordna/tasks/<id>` with no working-tree presence.
|
|
16
|
+
storage: z.enum(["file", "hybrid", "namespace"]).default("file"),
|
|
17
|
+
// T-032: namespace-mode tuning. Polling interval for the watcher
|
|
18
|
+
// (refs have no kernel-level change-notification path, so polling
|
|
19
|
+
// is the only reliable mechanism). Default 1s. `autoFetchIntervalMs`
|
|
20
|
+
// runs `git fetch origin '+refs/ordna/tasks/*:refs/ordna/tasks/*'`
|
|
21
|
+
// in the background so other machines' updates land without manual
|
|
22
|
+
// pulls; set to 0 to disable auto-fetch entirely (manual fetch via
|
|
23
|
+
// the TUI / web button still works). `autoRenumberOnConflict`
|
|
24
|
+
// controls whether a push-rejection on a colliding create silently
|
|
25
|
+
// reallocates a fresh ID for the local task (true, default) or
|
|
26
|
+
// surfaces a loud error (false, for projects where stable IDs in
|
|
27
|
+
// commit messages / external links are load-bearing).
|
|
28
|
+
namespace: z
|
|
29
|
+
.object({
|
|
30
|
+
pollIntervalMs: z.number().int().min(50).default(1000),
|
|
31
|
+
autoFetchIntervalMs: z.number().int().min(0).default(60000),
|
|
32
|
+
autoRenumberOnConflict: z.boolean().default(true),
|
|
33
|
+
})
|
|
34
|
+
.default({
|
|
35
|
+
pollIntervalMs: 1000,
|
|
36
|
+
autoFetchIntervalMs: 60000,
|
|
37
|
+
autoRenumberOnConflict: true,
|
|
38
|
+
}),
|
|
12
39
|
});
|
|
13
40
|
export const DEFAULT_CONFIG = configSchema.parse({});
|
|
14
41
|
const CONFIG_PATH = ".ordna/config.yaml";
|
|
@@ -20,7 +47,20 @@ export function loadConfig(options = {}) {
|
|
|
20
47
|
const raw = readFileSync(configFile, "utf8");
|
|
21
48
|
fromFile = parseYaml(raw) ?? {};
|
|
22
49
|
}
|
|
23
|
-
const merged = {
|
|
50
|
+
const merged = {
|
|
51
|
+
...fromFile,
|
|
52
|
+
...(options.overrides ?? {}),
|
|
53
|
+
};
|
|
54
|
+
// T-033: `ORDNA_STORAGE` is a runtime override — when set to one of
|
|
55
|
+
// the known modes, it wins over whatever the YAML says. CI uses
|
|
56
|
+
// this to pin storage without writing a file; tests use it to
|
|
57
|
+
// exercise specific modes without polluting the test directory.
|
|
58
|
+
const envStorage = process.env.ORDNA_STORAGE;
|
|
59
|
+
if (envStorage === "file" ||
|
|
60
|
+
envStorage === "hybrid" ||
|
|
61
|
+
envStorage === "namespace") {
|
|
62
|
+
merged.storage = envStorage;
|
|
63
|
+
}
|
|
24
64
|
return configSchema.parse(merged);
|
|
25
65
|
}
|
|
26
66
|
export function resolveTasksDir(config, cwd = process.cwd()) {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IACrC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACrD,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACvE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IACjC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACzD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
import type { StoreContext } from "./store.js";
|
|
2
|
+
/**
|
|
3
|
+
* Commit pending task changes.
|
|
4
|
+
*
|
|
5
|
+
* Delegates to the active backend's optional `commit()` method. The
|
|
6
|
+
* built-in file backend implements it (stages the tasks directory and
|
|
7
|
+
* runs `git commit`); future non-file backends (hybrid keeps it for
|
|
8
|
+
* the file half; namespace deliberately omits it because tasks aren't
|
|
9
|
+
* in the working tree) leave it undefined, in which case this throws
|
|
10
|
+
* a clear error pointing the user at the right sync flow.
|
|
11
|
+
*/
|
|
2
12
|
export declare function commitTasks(ctx: StoreContext, message?: string): Promise<void>;
|
|
3
13
|
//# sourceMappingURL=git.d.ts.map
|
package/dist/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAChC,GAAG,EAAE,YAAY,EACjB,OAAO,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
package/dist/git.js
CHANGED
|
@@ -1,30 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
proc.on("close", (code) => {
|
|
15
|
-
if (code === 0)
|
|
16
|
-
resolve({ stdout, stderr });
|
|
17
|
-
else
|
|
18
|
-
reject(new Error(`git ${args.join(" ")} failed (${code}): ${stderr.trim()}`));
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
export async function commitTasks(ctx, message = "chore(tasks): update") {
|
|
23
|
-
await run(ctx.cwd, ["add", "--", ctx.config.tasksDir]);
|
|
24
|
-
const status = await run(ctx.cwd, ["status", "--porcelain", "--", ctx.config.tasksDir]);
|
|
25
|
-
if (status.stdout.trim().length === 0) {
|
|
26
|
-
throw new Error("No task changes to commit.");
|
|
1
|
+
/**
|
|
2
|
+
* Commit pending task changes.
|
|
3
|
+
*
|
|
4
|
+
* Delegates to the active backend's optional `commit()` method. The
|
|
5
|
+
* built-in file backend implements it (stages the tasks directory and
|
|
6
|
+
* runs `git commit`); future non-file backends (hybrid keeps it for
|
|
7
|
+
* the file half; namespace deliberately omits it because tasks aren't
|
|
8
|
+
* in the working tree) leave it undefined, in which case this throws
|
|
9
|
+
* a clear error pointing the user at the right sync flow.
|
|
10
|
+
*/
|
|
11
|
+
export async function commitTasks(ctx, message) {
|
|
12
|
+
if (!ctx.backend.commit) {
|
|
13
|
+
throw new Error(`Backend "${ctx.backend.kind}" does not support \`ordna commit\`. Use the backend's own sync flow instead.`);
|
|
27
14
|
}
|
|
28
|
-
|
|
15
|
+
return ctx.backend.commit(message);
|
|
29
16
|
}
|
|
30
17
|
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,GAAiB,EACjB,OAAgB;IAEhB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACd,YAAY,GAAG,CAAC,OAAO,CAAC,IAAI,+EAA+E,CAC3G,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export { extractIdFromFilename, formatId, nextId, parseId } from "./ids.js";
|
|
|
4
4
|
export { extractAcceptanceCriteria, findSection, parseTask, parseTaskFile, splitSections, } from "./parser.js";
|
|
5
5
|
export type { AcceptanceItem, Priority, RawFrontmatter, SchemaMode, Section, Task, TaskCreateInput, TaskUpdateInput, } from "./schema.js";
|
|
6
6
|
export { BACKLOG_BODY_HEADINGS, BODY_HEADING_ALIASES, FRONTMATTER_ALIASES, ORDNA_BODY_HEADINGS, frontmatterSchema, priorityEnum, } from "./schema.js";
|
|
7
|
-
export { ARCHIVED_STATUS, createContext, createTask, deleteTask, getTask, isKnownStatus, listTasks, moveTask, updateTask, type ListTasksOptions, type StoreContext, } from "./store.js";
|
|
7
|
+
export { ARCHIVED_STATUS, canFetch, createContext, createTask, deleteTask, fetchTasks, getTask, isKnownStatus, listTasks, moveTask, updateTask, type ListTasksOptions, type StoreContext, } from "./store.js";
|
|
8
|
+
export type { FetchResult } from "./storage/backend.js";
|
|
8
9
|
export { defaultSectionsFor, serializeTask } from "./writer.js";
|
|
9
10
|
export { watchTasks, type TaskEvent, type TaskEventListener, type WatchOptions } from "./watcher.js";
|
|
11
|
+
export { type DetectedMode, NeedsModeSelection, detectStorageMode, ensureStorageConfig, readEnvStorageMode, writeStorageConfig, } from "./storage/auto-detect.js";
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,cAAc,EACd,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,WAAW,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EACN,yBAAyB,EACzB,WAAW,EACX,SAAS,EACT,aAAa,EACb,aAAa,GACb,MAAM,aAAa,CAAC;AACrB,YAAY,EACX,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,EACV,OAAO,EACP,IAAI,EACJ,eAAe,EACf,eAAe,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACT,QAAQ,EACR,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,YAAY,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,cAAc,EACd,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,WAAW,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EACN,yBAAyB,EACzB,WAAW,EACX,SAAS,EACT,aAAa,EACb,aAAa,GACb,MAAM,aAAa,CAAC;AACrB,YAAY,EACX,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,EACV,OAAO,EACP,IAAI,EACJ,eAAe,EACf,eAAe,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,EACf,QAAQ,EACR,aAAa,EACb,UAAU,EACV,UAAU,EACV,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACT,QAAQ,EACR,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,YAAY,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AACrG,OAAO,EACN,KAAK,YAAY,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GAClB,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,8 @@ export { commitTasks } from "./git.js";
|
|
|
3
3
|
export { extractIdFromFilename, formatId, nextId, parseId } from "./ids.js";
|
|
4
4
|
export { extractAcceptanceCriteria, findSection, parseTask, parseTaskFile, splitSections, } from "./parser.js";
|
|
5
5
|
export { BACKLOG_BODY_HEADINGS, BODY_HEADING_ALIASES, FRONTMATTER_ALIASES, ORDNA_BODY_HEADINGS, frontmatterSchema, priorityEnum, } from "./schema.js";
|
|
6
|
-
export { ARCHIVED_STATUS, createContext, createTask, deleteTask, getTask, isKnownStatus, listTasks, moveTask, updateTask, } from "./store.js";
|
|
6
|
+
export { ARCHIVED_STATUS, canFetch, createContext, createTask, deleteTask, fetchTasks, getTask, isKnownStatus, listTasks, moveTask, updateTask, } from "./store.js";
|
|
7
7
|
export { defaultSectionsFor, serializeTask } from "./writer.js";
|
|
8
8
|
export { watchTasks } from "./watcher.js";
|
|
9
|
+
export { NeedsModeSelection, detectStorageMode, ensureStorageConfig, readEnvStorageMode, writeStorageConfig, } from "./storage/auto-detect.js";
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,cAAc,EACd,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,eAAe,GAGf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EACN,yBAAyB,EACzB,WAAW,EACX,SAAS,EACT,aAAa,EACb,aAAa,GACb,MAAM,aAAa,CAAC;AAWrB,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACT,QAAQ,EACR,UAAU,GAGV,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,cAAc,EACd,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,eAAe,GAGf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EACN,yBAAyB,EACzB,WAAW,EACX,SAAS,EACT,aAAa,EACb,aAAa,GACb,MAAM,aAAa,CAAC;AAWrB,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,EACf,QAAQ,EACR,aAAa,EACb,UAAU,EACV,UAAU,EACV,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACT,QAAQ,EACR,UAAU,GAGV,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,UAAU,EAA6D,MAAM,cAAc,CAAC;AACrG,OAAO,EAEN,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GAClB,MAAM,0BAA0B,CAAC"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -22,8 +22,25 @@ export interface Task {
|
|
|
22
22
|
updated_at: string;
|
|
23
23
|
sections: Section[];
|
|
24
24
|
extra_frontmatter: Record<string, unknown>;
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* On-disk location of the task file.
|
|
27
|
+
*
|
|
28
|
+
* Set by the file and hybrid backends (tasks live as `.md` files).
|
|
29
|
+
* **Unset** by the namespace backend — tasks there live as git
|
|
30
|
+
* blobs at `refs/ordna/tasks/<id>` with no working-tree presence.
|
|
31
|
+
* Consumers must guard against `undefined` (the CLI editor launcher
|
|
32
|
+
* and the create-command path-log already do).
|
|
33
|
+
*/
|
|
34
|
+
filePath?: string;
|
|
26
35
|
rawContent: string;
|
|
36
|
+
/**
|
|
37
|
+
* Most recent previous id this task had, if the namespace backend
|
|
38
|
+
* auto-renumbered it on a push collision. Surfaced as a
|
|
39
|
+
* "previously known as X" banner in the UIs. Populated only by the
|
|
40
|
+
* namespace backend (it reads the state ref's audit log on each
|
|
41
|
+
* `get`/`list`); file and hybrid leave it `undefined`.
|
|
42
|
+
*/
|
|
43
|
+
renamed_from?: string;
|
|
27
44
|
}
|
|
28
45
|
export interface TaskCreateInput {
|
|
29
46
|
title: string;
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAI;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAI;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAUxD,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;CAKtB,CAAC;AAEX,eAAO,MAAM,qBAAqB;;;;;;CAMxB,CAAC;AAEX,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAMzD,CAAC;AAEF,eAAO,MAAM,YAAY,sCAAoC,CAAC;AAE9D,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAgBf,CAAC;AAEhB,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of `detectStorageMode`. Three confident outcomes
|
|
3
|
+
* (`file` / `hybrid` / `namespace`) lead to auto-configuration; `ask`
|
|
4
|
+
* needs a user prompt; `default-file` is the "no signals, no git"
|
|
5
|
+
* fallback that runs in file mode without writing a config (the user
|
|
6
|
+
* might `git init` later).
|
|
7
|
+
*/
|
|
8
|
+
export type DetectedMode = {
|
|
9
|
+
mode: "file" | "hybrid" | "namespace";
|
|
10
|
+
reason: string;
|
|
11
|
+
} | {
|
|
12
|
+
mode: "ask";
|
|
13
|
+
reason: string;
|
|
14
|
+
} | {
|
|
15
|
+
mode: "default-file";
|
|
16
|
+
reason: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Thrown when `ensureStorageConfig` detects a git repo with no storage
|
|
20
|
+
* signals and no config — there's no defensible default, so the
|
|
21
|
+
* consumer must prompt the user. The TUI catches this and shows a
|
|
22
|
+
* modal, the web server catches it and serves a setup page, the CLI
|
|
23
|
+
* one-shots prompt on TTY or fail with a clear hint.
|
|
24
|
+
*/
|
|
25
|
+
export declare class NeedsModeSelection extends Error {
|
|
26
|
+
readonly cwd: string;
|
|
27
|
+
readonly reason: string;
|
|
28
|
+
constructor(cwd: string, reason: string);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Inspect `cwd` for storage signals. Pure detection — never writes,
|
|
32
|
+
* never creates anything. Returns a `DetectedMode` for the caller to
|
|
33
|
+
* act on.
|
|
34
|
+
*
|
|
35
|
+
* Detection order:
|
|
36
|
+
* 1. `refs/ordna/tasks/*` exist → `namespace`
|
|
37
|
+
* 2. `refs/ordna/state` exists → `hybrid`
|
|
38
|
+
* 3. `tasks/*.md` files exist → `file`
|
|
39
|
+
* 4. cwd is a git repo (none of the above) → `ask`
|
|
40
|
+
* 5. else → `default-file`
|
|
41
|
+
*
|
|
42
|
+
* Uses `git for-each-ref` to authoritative-check refs (handles packed
|
|
43
|
+
* refs after `git gc` correctly, where direct filesystem reads of
|
|
44
|
+
* `.git/refs/...` would miss them).
|
|
45
|
+
*/
|
|
46
|
+
export declare function detectStorageMode(cwd: string): Promise<DetectedMode>;
|
|
47
|
+
/**
|
|
48
|
+
* Compose detection + write into one call.
|
|
49
|
+
*
|
|
50
|
+
* - If `ORDNA_STORAGE` is set to a valid mode, return immediately
|
|
51
|
+
* without writing or detecting. The caller relies on `loadConfig`
|
|
52
|
+
* honouring the env var.
|
|
53
|
+
* - If `.ordna/config.yaml` already exists, return immediately.
|
|
54
|
+
* - Otherwise run `detectStorageMode` and:
|
|
55
|
+
* - `file` / `hybrid` / `namespace` → write the config with the
|
|
56
|
+
* detected storage key
|
|
57
|
+
* - `ask` → throw `NeedsModeSelection`
|
|
58
|
+
* - `default-file` → return without writing (let the caller fall
|
|
59
|
+
* back to in-memory file mode; if the user later `git init`s,
|
|
60
|
+
* detection re-evaluates from scratch on next run)
|
|
61
|
+
*/
|
|
62
|
+
export declare function ensureStorageConfig(cwd: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Write a minimal `.ordna/config.yaml` containing the chosen storage
|
|
65
|
+
* mode. Other config keys are left to the schema defaults so the file
|
|
66
|
+
* doesn't pin values the user hasn't deliberately chosen.
|
|
67
|
+
*
|
|
68
|
+
* Idempotent — overwrites an existing config file. Callers that don't
|
|
69
|
+
* want that should check first (see `ensureStorageConfig`).
|
|
70
|
+
*/
|
|
71
|
+
export declare function writeStorageConfig(cwd: string, storage: "file" | "hybrid" | "namespace"): void;
|
|
72
|
+
/**
|
|
73
|
+
* Read `ORDNA_STORAGE` from the environment, validating against the
|
|
74
|
+
* three known modes. Anything else (including unset / empty) returns
|
|
75
|
+
* `null` so the normal detection path runs.
|
|
76
|
+
*
|
|
77
|
+
* Exported so `config.ts` can apply the same override when reading the
|
|
78
|
+
* YAML — keeps the env-var semantics consistent across the two
|
|
79
|
+
* entrypoints.
|
|
80
|
+
*/
|
|
81
|
+
export declare function readEnvStorageMode(): "file" | "hybrid" | "namespace" | null;
|
|
82
|
+
//# sourceMappingURL=auto-detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-detect.d.ts","sourceRoot":"","sources":["../../src/storage/auto-detect.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GACrB;IAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aAE3B,GAAG,EAAE,MAAM;aACX,MAAM,EAAE,MAAM;gBADd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM;CAO/B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA8C1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBpE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GACtC,IAAI,CAKN;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAC/B,MAAM,GACN,QAAQ,GACR,WAAW,GACX,IAAI,CAIN"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { GitRunner } from "./git-ref.js";
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when `ensureStorageConfig` detects a git repo with no storage
|
|
6
|
+
* signals and no config — there's no defensible default, so the
|
|
7
|
+
* consumer must prompt the user. The TUI catches this and shows a
|
|
8
|
+
* modal, the web server catches it and serves a setup page, the CLI
|
|
9
|
+
* one-shots prompt on TTY or fail with a clear hint.
|
|
10
|
+
*/
|
|
11
|
+
export class NeedsModeSelection extends Error {
|
|
12
|
+
cwd;
|
|
13
|
+
reason;
|
|
14
|
+
constructor(cwd, reason) {
|
|
15
|
+
super(`Ordna needs to know which storage mode to use in ${cwd}. ${reason}`);
|
|
16
|
+
this.cwd = cwd;
|
|
17
|
+
this.reason = reason;
|
|
18
|
+
this.name = "NeedsModeSelection";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Inspect `cwd` for storage signals. Pure detection — never writes,
|
|
23
|
+
* never creates anything. Returns a `DetectedMode` for the caller to
|
|
24
|
+
* act on.
|
|
25
|
+
*
|
|
26
|
+
* Detection order:
|
|
27
|
+
* 1. `refs/ordna/tasks/*` exist → `namespace`
|
|
28
|
+
* 2. `refs/ordna/state` exists → `hybrid`
|
|
29
|
+
* 3. `tasks/*.md` files exist → `file`
|
|
30
|
+
* 4. cwd is a git repo (none of the above) → `ask`
|
|
31
|
+
* 5. else → `default-file`
|
|
32
|
+
*
|
|
33
|
+
* Uses `git for-each-ref` to authoritative-check refs (handles packed
|
|
34
|
+
* refs after `git gc` correctly, where direct filesystem reads of
|
|
35
|
+
* `.git/refs/...` would miss them).
|
|
36
|
+
*/
|
|
37
|
+
export async function detectStorageMode(cwd) {
|
|
38
|
+
const isGitRepo = isGitWorkingTree(cwd);
|
|
39
|
+
if (isGitRepo) {
|
|
40
|
+
const git = new GitRunner(cwd);
|
|
41
|
+
const taskRefs = await git.forEachRef("refs/ordna/tasks/*");
|
|
42
|
+
if (taskRefs.length > 0) {
|
|
43
|
+
return {
|
|
44
|
+
mode: "namespace",
|
|
45
|
+
reason: `found ${taskRefs.length} ref(s) under refs/ordna/tasks/`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const stateRefs = await git.forEachRef("refs/ordna/state");
|
|
49
|
+
if (stateRefs.length > 0) {
|
|
50
|
+
return { mode: "hybrid", reason: "found refs/ordna/state" };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// File-mode signal: `tasks/` with at least one `.md` file. Without
|
|
54
|
+
// a loaded config we can only check the default path; non-default
|
|
55
|
+
// `tasksDir` configurations imply a config exists, in which case
|
|
56
|
+
// detection never runs.
|
|
57
|
+
const tasksDir = join(cwd, "tasks");
|
|
58
|
+
if (existsSync(tasksDir)) {
|
|
59
|
+
try {
|
|
60
|
+
const entries = readdirSync(tasksDir, { withFileTypes: true });
|
|
61
|
+
const hasMd = entries.some((e) => e.isFile() && e.name.endsWith(".md"));
|
|
62
|
+
if (hasMd) {
|
|
63
|
+
return { mode: "file", reason: "found tasks/*.md files" };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// readdirSync error (permissions, etc.) — treat as "no signal."
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (isGitRepo) {
|
|
71
|
+
return {
|
|
72
|
+
mode: "ask",
|
|
73
|
+
reason: "no storage signals found, but this is a git repo",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
mode: "default-file",
|
|
78
|
+
reason: "no git, no existing tasks — defaulting to file mode",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Compose detection + write into one call.
|
|
83
|
+
*
|
|
84
|
+
* - If `ORDNA_STORAGE` is set to a valid mode, return immediately
|
|
85
|
+
* without writing or detecting. The caller relies on `loadConfig`
|
|
86
|
+
* honouring the env var.
|
|
87
|
+
* - If `.ordna/config.yaml` already exists, return immediately.
|
|
88
|
+
* - Otherwise run `detectStorageMode` and:
|
|
89
|
+
* - `file` / `hybrid` / `namespace` → write the config with the
|
|
90
|
+
* detected storage key
|
|
91
|
+
* - `ask` → throw `NeedsModeSelection`
|
|
92
|
+
* - `default-file` → return without writing (let the caller fall
|
|
93
|
+
* back to in-memory file mode; if the user later `git init`s,
|
|
94
|
+
* detection re-evaluates from scratch on next run)
|
|
95
|
+
*/
|
|
96
|
+
export async function ensureStorageConfig(cwd) {
|
|
97
|
+
const envMode = readEnvStorageMode();
|
|
98
|
+
if (envMode) {
|
|
99
|
+
// Env var is a runtime override; do not write the config file.
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (configFileExists(cwd)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const detected = await detectStorageMode(cwd);
|
|
106
|
+
switch (detected.mode) {
|
|
107
|
+
case "file":
|
|
108
|
+
case "hybrid":
|
|
109
|
+
case "namespace":
|
|
110
|
+
writeStorageConfig(cwd, detected.mode);
|
|
111
|
+
return;
|
|
112
|
+
case "ask":
|
|
113
|
+
throw new NeedsModeSelection(cwd, detected.reason);
|
|
114
|
+
case "default-file":
|
|
115
|
+
return; // run with in-memory defaults; don't litter
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Write a minimal `.ordna/config.yaml` containing the chosen storage
|
|
120
|
+
* mode. Other config keys are left to the schema defaults so the file
|
|
121
|
+
* doesn't pin values the user hasn't deliberately chosen.
|
|
122
|
+
*
|
|
123
|
+
* Idempotent — overwrites an existing config file. Callers that don't
|
|
124
|
+
* want that should check first (see `ensureStorageConfig`).
|
|
125
|
+
*/
|
|
126
|
+
export function writeStorageConfig(cwd, storage) {
|
|
127
|
+
const configDir = join(cwd, ".ordna");
|
|
128
|
+
if (!existsSync(configDir))
|
|
129
|
+
mkdirSync(configDir, { recursive: true });
|
|
130
|
+
const body = `# Ordna config — auto-written from storage detection.\nstorage: ${storage}\n`;
|
|
131
|
+
writeFileSync(join(configDir, "config.yaml"), body, "utf8");
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Read `ORDNA_STORAGE` from the environment, validating against the
|
|
135
|
+
* three known modes. Anything else (including unset / empty) returns
|
|
136
|
+
* `null` so the normal detection path runs.
|
|
137
|
+
*
|
|
138
|
+
* Exported so `config.ts` can apply the same override when reading the
|
|
139
|
+
* YAML — keeps the env-var semantics consistent across the two
|
|
140
|
+
* entrypoints.
|
|
141
|
+
*/
|
|
142
|
+
export function readEnvStorageMode() {
|
|
143
|
+
const raw = process.env.ORDNA_STORAGE;
|
|
144
|
+
if (raw === "file" || raw === "hybrid" || raw === "namespace")
|
|
145
|
+
return raw;
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
function configFileExists(cwd) {
|
|
149
|
+
return existsSync(join(cwd, ".ordna", "config.yaml"));
|
|
150
|
+
}
|
|
151
|
+
function isGitWorkingTree(cwd) {
|
|
152
|
+
// `.git` can be a directory (regular repo), a file (worktree
|
|
153
|
+
// pointing at the main repo's gitdir), or absent. `existsSync` on
|
|
154
|
+
// `<cwd>/.git` covers all three cases — present (any type) means
|
|
155
|
+
// "this is a git checkout."
|
|
156
|
+
return existsSync(join(cwd, ".git"));
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=auto-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-detect.js","sourceRoot":"","sources":["../../src/storage/auto-detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { GitRunner } from "./git-ref.js";
|
|
2
|
+
/**
|
|
3
|
+
* Fire-and-forget push coalescer. Used by hybrid and namespace modes
|
|
4
|
+
* to keep their refs synced with `origin` without surprising the
|
|
5
|
+
* user with synchronous network calls on every mutation.
|
|
6
|
+
*
|
|
7
|
+
* Semantics:
|
|
8
|
+
* - `schedule()` is sync and never throws. Multiple rapid calls
|
|
9
|
+
* within ~50ms collapse into a single push.
|
|
10
|
+
* - Pushes run in the background. Errors are logged to stderr; the
|
|
11
|
+
* user's command stays successful.
|
|
12
|
+
* - If no `origin` remote is configured at first push time, the
|
|
13
|
+
* queue becomes a permanent no-op (decided once, cached forever).
|
|
14
|
+
* - `flush()` (called from `dispose()`) awaits any pending or
|
|
15
|
+
* in-flight push so the process can exit cleanly.
|
|
16
|
+
*/
|
|
17
|
+
export declare class PushQueue {
|
|
18
|
+
#private;
|
|
19
|
+
private readonly git;
|
|
20
|
+
private readonly refspec;
|
|
21
|
+
private readonly label;
|
|
22
|
+
constructor(git: GitRunner, refspec: string, label?: string);
|
|
23
|
+
/**
|
|
24
|
+
* Mark "a push is wanted." Coalesces with any other calls in the
|
|
25
|
+
* next 50ms. Cheap and synchronous — safe to call from any
|
|
26
|
+
* mutation site.
|
|
27
|
+
*/
|
|
28
|
+
schedule(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Await any pending or in-flight push. Called from
|
|
31
|
+
* `HybridBackend.dispose()` so the last mutation's push completes
|
|
32
|
+
* before the process exits.
|
|
33
|
+
*/
|
|
34
|
+
flush(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=auto-push.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-push.d.ts","sourceRoot":"","sources":["../../src/storage/auto-push.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C;;;;;;;;;;;;;;GAcG;AACH,qBAAa,SAAS;;IAQpB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,MAAM,EACf,KAAK,SAAU;IAGjC;;;;OAIG;IACH,QAAQ,IAAI,IAAI;IAYhB;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA8C5B"}
|