feat(cli): prepare and validate workspace documents offline
Reuse the runtime catalog and workspace parsers in a standalone helper paired with tht. Add document templates, safe diagnostics, local Evidence checks, native bundle builds, shared CLI fixtures and IT/EN preparation guides. Record the approved document-first specification and ticket breakdown. Refs #43.
This commit is contained in:
+11
@@ -638,6 +638,17 @@ procedura non implica che DWH o provider LLM siano locali o disponibili offline.
|
||||
installazione manuale: verifica dell'host, generazione della configurazione, predisposizione
|
||||
delle credenziali protette e avvio dei servizi. Non è un installer dell'applicazione.
|
||||
|
||||
**Installation preparation** — La predisposizione dei documenti che descrivono i workspace
|
||||
e i parametri dell'installazione, prima di applicarli. Permette all'operatore di raccogliere
|
||||
e correggere le informazioni senza avviare l'applicazione.
|
||||
|
||||
**Installation validation** — La verifica ripetibile della completezza e coerenza dei
|
||||
documenti e delle precondizioni di un'installazione. Distingue ciò che è stato verificato
|
||||
da ciò che richiede un'applicazione già avviata.
|
||||
|
||||
**Installation execution** — L'applicazione dei documenti verificati per predisporre e
|
||||
avviare ThothII. Non raccoglie nuovi parametri dall'operatore durante l'esecuzione.
|
||||
|
||||
**Platform acceptance** — La verifica che una Manual standalone installation possa essere
|
||||
predisposta e avviata su una specifica combinazione di sistema operativo, architettura e runtime,
|
||||
distinta dalla verifica funzionale del collegamento a DWH e provider LLM.
|
||||
|
||||
+8
-1
@@ -1,10 +1,17 @@
|
||||
# Project state
|
||||
|
||||
Updated: 2026-09-15. This is a current snapshot, not a release diary. Stable commands
|
||||
Updated: 2026-09-28. This is a current snapshot, not a release diary. Stable commands
|
||||
and invariants are in [AGENTS.md](AGENTS.md); prior snapshots remain in Git.
|
||||
|
||||
## Current contracts
|
||||
|
||||
- Document-first installation ticket #43 provides offline `tht workspace prepare`
|
||||
and `tht workspace validate` through a native two-executable bundle. Build and
|
||||
test instructions are in [the host CLI guide](tools/tht/README.md). Local validation
|
||||
reuses runtime workspace/catalog parsers and explicitly defers runtime Evidence,
|
||||
database binding and readiness checks. The remainder of the installation tickets,
|
||||
Docker Hub publication and example databases remain pending.
|
||||
|
||||
- React supports full/embedded rendering independently of local/OIDC/upstream auth,
|
||||
with EN/IT UI and immutable session interaction language. See
|
||||
[application shell](docs/architecture/application-shell.md) and
|
||||
|
||||
Generated
+206
@@ -23,6 +23,7 @@
|
||||
"@testcontainers/postgresql": "^12.1.0",
|
||||
"@types/node": "24.13.3",
|
||||
"@types/validator": "13.15.10",
|
||||
"bun": "1.4.2",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.6.0",
|
||||
"vitest": "^2.1.0"
|
||||
@@ -802,6 +803,174 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@oven/bun-darwin-aarch64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.4.2.tgz",
|
||||
"integrity": "sha512-MXdZkP1featqxZ+/VTXWG1BVjM4OGBehVY2Q88EeUj/7L0UMeCGItmyPYTN+wxvlGJ6F66JEtzsw+GvQWewnag==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-darwin-x64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.4.2.tgz",
|
||||
"integrity": "sha512-gZTxZuLjkUhAWjTETu3tw0WhsEdNkJ64daj60ybhPf835a2yollV3yTkK9JozvzKPx4TRFzLSl8C+U525pxVbw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-freebsd-aarch64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-freebsd-aarch64/-/bun-freebsd-aarch64-1.4.2.tgz",
|
||||
"integrity": "sha512-SMNItMw1Z8QeeQVKnw8jA7xQNkeXdP+OPgin4Wi/QTx/B8RHHLnuZfqmFy7NtVeT2NF0kKYppW4WWd2CCYZjhQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-freebsd-x64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-freebsd-x64/-/bun-freebsd-x64-1.4.2.tgz",
|
||||
"integrity": "sha512-THbPKXhO54N0DpFRKZNDZpQ7dpbX0bWASuARckAUS9wRtFIHsiY+uULXJvxJGo2YD1YewvXQ4G8Fj7XT5oBCiw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-aarch64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.4.2.tgz",
|
||||
"integrity": "sha512-3BBP9ovJ2RGHFH6Ae1CAtxNtG1+YY6GD6rmYbsUosoAk9+OEl6zeDQ/k4fBkc6dYOJCtWnx8hUxzNzQATSmvYQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-aarch64-android": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64-android/-/bun-linux-aarch64-android-1.4.2.tgz",
|
||||
"integrity": "sha512-3mZKO2rhsNgbAUtAHC1UKUlF2zTxFraDZT/Elv8wzyH0fJL9h+Iv3TgB9lO63w89PRn3eFe+NRA1bhVgikKNPQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-aarch64-musl": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64-musl/-/bun-linux-aarch64-musl-1.4.2.tgz",
|
||||
"integrity": "sha512-+Sm6y+lSiSFBOtXmnekp5Q6n1tUKlyv71FCPWBc61Cgb14T5eBs8SN/nh4MUCOKzONkI3O+as3MGUgikS4aCBQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-x64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.4.2.tgz",
|
||||
"integrity": "sha512-9/E/UXOTpSo3YsV5g+FhtTd/qTpiWoKuxS12cqtuYA1ssu9fRAoPQnipFgGyck3tWO63iUdxBiygq+kELFawng==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-x64-android": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-android/-/bun-linux-x64-android-1.4.2.tgz",
|
||||
"integrity": "sha512-6HC5tzcC79113n2IHCTJMWv+HsQImv4ZFEK2XpYLxY6HbT8tM4cUM2Zv1bHZBQsS3jv/zYBamDJ1UX7If0d5tw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-linux-x64-musl": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl/-/bun-linux-x64-musl-1.4.2.tgz",
|
||||
"integrity": "sha512-vVTKUg1bnPhRP/Hp73jIVoFh2vPFNYEqYX0ERKfZBOQEEHitNAeukZzzuUDZS0SoDCIpuWUGSpd/CDMbjdR+Uw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-windows-aarch64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-windows-aarch64/-/bun-windows-aarch64-1.4.2.tgz",
|
||||
"integrity": "sha512-8EJ1ST7339WJE3poPW5nBgVW/lWf9HBz4W27ZUNhburKmcBLOByPyE6DP9fHD8FQGm5c+ilUN2hX1mrW0jxq9Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@oven/bun-windows-x64": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.4.2.tgz",
|
||||
"integrity": "sha512-+bN6OuVld/9diT/RLSXSW7JE6CvNE3gL9XsAEjULi1nUsXd6DNO6GuA9jNdNb3r8PdJFnYHr5aypNV1Oj3Rd9g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@pinojs/redact": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
|
||||
@@ -1876,6 +2045,43 @@
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bun": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/bun/-/bun-1.4.2.tgz",
|
||||
"integrity": "sha512-TrSXo6HJfIEaczpb3kjX82I2pL47vK1QUNmHRCUdz9IzaOwa9lzOXSWwu2l18YHE3sNfGRapVLd4nNm+22vVVA==",
|
||||
"cpu": [
|
||||
"arm64",
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
"android",
|
||||
"freebsd",
|
||||
"win32"
|
||||
],
|
||||
"bin": {
|
||||
"bun": "bin/bun.exe",
|
||||
"bunx": "bin/bunx.exe"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oven/bun-darwin-aarch64": "1.4.2",
|
||||
"@oven/bun-darwin-x64": "1.4.2",
|
||||
"@oven/bun-freebsd-aarch64": "1.4.2",
|
||||
"@oven/bun-freebsd-x64": "1.4.2",
|
||||
"@oven/bun-linux-aarch64": "1.4.2",
|
||||
"@oven/bun-linux-aarch64-android": "1.4.2",
|
||||
"@oven/bun-linux-aarch64-musl": "1.4.2",
|
||||
"@oven/bun-linux-x64": "1.4.2",
|
||||
"@oven/bun-linux-x64-android": "1.4.2",
|
||||
"@oven/bun-linux-x64-musl": "1.4.2",
|
||||
"@oven/bun-windows-aarch64": "1.4.2",
|
||||
"@oven/bun-windows-x64": "1.4.2"
|
||||
}
|
||||
},
|
||||
"node_modules/byline": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build:workspace-tools": "node scripts/build-workspace-tools.mjs",
|
||||
"dev": "tsx watch src/server.ts",
|
||||
"prebuild": "node scripts/clean-dist.mjs",
|
||||
"build": "tsc -p tsconfig.json",
|
||||
@@ -31,6 +32,7 @@
|
||||
"@testcontainers/postgresql": "^12.1.0",
|
||||
"@types/node": "24.13.3",
|
||||
"@types/validator": "13.15.10",
|
||||
"bun": "1.4.2",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.6.0",
|
||||
"vitest": "^2.1.0"
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Maintainer-only build. The resulting two-binary bundle needs no extra host runtime.
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { createHash } from "node:crypto";
|
||||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const backend = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const repository = resolve(backend, "..");
|
||||
const native = `${process.platform === "win32" ? "windows" : process.platform}-${process.arch === "x64" ? "amd64" : process.arch}`;
|
||||
const targets = {
|
||||
"windows-amd64": ["windows", "amd64", "bun-windows-x64"],
|
||||
"darwin-amd64": ["darwin", "amd64", "bun-darwin-x64"],
|
||||
"darwin-arm64": ["darwin", "arm64", "bun-darwin-arm64"],
|
||||
"linux-amd64": ["linux", "amd64", "bun-linux-x64"],
|
||||
"linux-arm64": ["linux", "arm64", "bun-linux-arm64"],
|
||||
};
|
||||
const requested = process.argv.slice(2);
|
||||
const selected = requested.length === 1 && requested[0] === "--all" ? Object.keys(targets) : requested.length ? requested : [native];
|
||||
if (selected.some((target) => !targets[target])) {
|
||||
console.error(`Usage: npm run build:workspace-tools -- [${Object.keys(targets).join("|")}|--all]`);
|
||||
process.exit(2);
|
||||
}
|
||||
function run(command, args, cwd = backend, env = process.env) {
|
||||
const result = spawnSync(command, args, { cwd, env, stdio: "inherit" });
|
||||
if (result.error || result.status !== 0) throw new Error(`Build failed: ${command}`);
|
||||
}
|
||||
const revision = spawnSync("git", ["rev-parse", "HEAD"], { cwd: repository, encoding: "utf8" });
|
||||
if (revision.status !== 0) throw new Error("Cannot read build revision");
|
||||
const commit = revision.stdout.trim();
|
||||
const buildTime = new Date().toISOString();
|
||||
const module = "github.com/aritmolab/thothii/tools/tht/internal/version";
|
||||
const bunPackage = JSON.parse(readFileSync(join(backend, "node_modules", "bun", "package.json"), "utf8"));
|
||||
const bun = join(backend, "node_modules", "bun", bunPackage.bin.bun);
|
||||
for (const target of selected) {
|
||||
const [os, arch, bunTarget] = targets[target];
|
||||
const output = join(repository, "dist", "workspace-tools", target);
|
||||
mkdirSync(output, { recursive: true });
|
||||
const extension = os === "windows" ? ".exe" : "";
|
||||
const names = [`tht${extension}`, `tht-workspace-documents${extension}`];
|
||||
run(bun, ["build", "src/workspace-documents-cli.ts", "--compile", `--target=${bunTarget}`, "--outfile", join(output, names[1])]);
|
||||
run("go", ["build", "-trimpath", "-ldflags", `-s -w -X ${module}.semanticVersion=0.0.0-dev -X ${module}.commit=${commit} -X ${module}.buildTime=${buildTime}`, "-o", join(output, names[0]), "./cmd/tht"], join(repository, "tools", "tht"), { ...process.env, CGO_ENABLED: "0", GOOS: os, GOARCH: arch });
|
||||
const hashes = names.map((name) => `${createHash("sha256").update(readFileSync(join(output, name))).digest("hex")} ${name}\n`).join("");
|
||||
writeFileSync(join(output, "SHA256SUMS"), hashes);
|
||||
writeFileSync(join(output, "build.json"), JSON.stringify({ commit, buildTime, target, bun: JSON.parse(readFileSync(join(backend, "package.json"), "utf8")).devDependencies.bun }, null, 2) + "\n");
|
||||
console.log(output);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/** Compiled with its runtime for the host CLI: no installation, Docker or host Node required. */
|
||||
import { runWorkspaceDocuments } from "./workspaces/documents.js";
|
||||
|
||||
const result = runWorkspaceDocuments(process.argv.slice(2));
|
||||
console.log(result.output);
|
||||
process.exitCode = result.status;
|
||||
@@ -44,8 +44,8 @@ const catalogSchema = z.object({
|
||||
});
|
||||
});
|
||||
|
||||
function safeCatalogError(): Error {
|
||||
return new Error("Workspace catalog is invalid");
|
||||
function safeCatalogError(cause?: unknown): Error {
|
||||
return new Error("Workspace catalog is invalid", { cause });
|
||||
}
|
||||
|
||||
export function parseWorkspaceCatalogYaml(source: string): WorkspaceCatalog {
|
||||
@@ -57,7 +57,7 @@ export function parseWorkspaceCatalogYaml(source: string): WorkspaceCatalog {
|
||||
return catalogSchema.parse(document.toJSON()) as WorkspaceCatalog;
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message === "Workspace catalog is invalid") throw error;
|
||||
throw safeCatalogError();
|
||||
throw safeCatalogError(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
import { closeSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { join, resolve } from "node:path";
|
||||
import { parseAllDocuments, stringify } from "yaml";
|
||||
import { ZodError } from "zod";
|
||||
import { CATALOG_PATH, parseWorkspaceCatalogYaml, assertCatalogMatchesDescriptor } from "./catalog.js";
|
||||
import { parseWorkspaceYaml, type WorkspaceDescriptor } from "./schema.js";
|
||||
|
||||
interface Issue { document: string; field: string; code: string; correction: string; line?: number }
|
||||
interface Report {
|
||||
schema_version: 1;
|
||||
scope: "local-documents";
|
||||
ok: boolean;
|
||||
workspaces: { id: string; evidence: "absent" | "local-files" | "remote-deferred" }[];
|
||||
issues: Issue[];
|
||||
deferred_checks: string[];
|
||||
}
|
||||
const MAX_DOCUMENT_BYTES = 1024 * 1024;
|
||||
const usage = "tht workspace prepare --directory NEW_PATH --id ID --name NAME [--language en|it] [--json]\ntht workspace validate --directory PATH [--json]";
|
||||
|
||||
class DocumentError extends Error {
|
||||
constructor(readonly issue: Issue) { super(issue.correction); }
|
||||
}
|
||||
function fail(document: string, field: string, code: string, correction: string): never {
|
||||
throw new DocumentError({ document, field, code, correction });
|
||||
}
|
||||
|
||||
/** Never include parser messages or submitted values: YAML and Zod errors can contain secrets. */
|
||||
function decode<T>(source: string, document: string, parser: (text: string) => T): T {
|
||||
try {
|
||||
const documents = parseAllDocuments(source, { uniqueKeys: true });
|
||||
if (documents.length !== 1) fail(document, "$", "yaml_documents", "Keep exactly one YAML document in this file.");
|
||||
const problem = [...documents[0].errors, ...documents[0].warnings][0];
|
||||
if (problem) {
|
||||
throw new DocumentError({ document, field: "$", code: "yaml_syntax", line: problem.linePos?.[0].line,
|
||||
correction: "Correct YAML syntax, remove duplicate keys and unsupported tags at the indicated line." });
|
||||
}
|
||||
return parser(source);
|
||||
} catch (error) {
|
||||
if (error instanceof DocumentError) throw error;
|
||||
const cause = error instanceof Error && error.cause instanceof ZodError ? error.cause : error;
|
||||
if (cause instanceof ZodError) {
|
||||
const issue = cause.issues[0];
|
||||
// Strict schemas produce paths containing schema-defined keys and array indices only.
|
||||
fail(document, issue.path.join(".") || "$", "schema_invalid",
|
||||
issue.code === "unrecognized_keys" ? "Remove fields not defined by the current workspace/catalog contract."
|
||||
: "Correct this field using workspace schema v4 or catalog schema v1; check type, required value, uniqueness and allowed values.");
|
||||
}
|
||||
fail(document, "$", "schema_invalid", "Use an authored workspace v4 descriptor; remove database configuration and keep it in the PostgreSQL Metadata Catalog.");
|
||||
}
|
||||
}
|
||||
|
||||
function stat(root: string, document: string, directory: boolean) {
|
||||
let info;
|
||||
try { info = lstatSync(join(root, document)); }
|
||||
catch { fail(document, "$", "missing_reference", "Create the referenced local file or directory and grant read access."); }
|
||||
if (info.isSymbolicLink() || (directory ? !info.isDirectory() : !info.isFile())) {
|
||||
fail(document, "$", "unsafe_reference", "Use a regular local file or directory, without symbolic links or special files.");
|
||||
}
|
||||
return info;
|
||||
}
|
||||
function readDocument(root: string, document: string): string {
|
||||
if (stat(root, document, false).size > MAX_DOCUMENT_BYTES) {
|
||||
fail(document, "$", "document_too_large", "Keep YAML documents below the 1 MiB local validation limit.");
|
||||
}
|
||||
try { return readFileSync(join(root, document), "utf8"); }
|
||||
catch { fail(document, "$", "unreadable", "Grant read access to this document and retry validation."); }
|
||||
}
|
||||
function directories(root: string, document: string) {
|
||||
stat(root, document, true);
|
||||
try { return readdirSync(join(root, document), { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name)); }
|
||||
catch { fail(document, "$", "unreadable", "Grant read and traversal access to this directory and retry validation."); }
|
||||
}
|
||||
|
||||
function inspectEvidence(root: string, descriptor: WorkspaceDescriptor): "absent" | "local-files" | "remote-deferred" {
|
||||
const evidence = descriptor.evidence;
|
||||
if (!evidence) return "absent";
|
||||
if (evidence.source.type !== "filesystem") return "remote-deferred";
|
||||
const base = evidence.source.uri;
|
||||
stat(root, base, true);
|
||||
if (evidence.schema_version === 2) stat(root, `${base}/curated`, true);
|
||||
const patterns = evidence.source.patterns ?? ["**/*.md"];
|
||||
const literals = patterns.filter((pattern) => !/[?*\[]/.test(pattern));
|
||||
for (const pattern of literals) {
|
||||
const parts = pattern.split("/");
|
||||
for (let index = 1; index < parts.length; index++) stat(root, `${base}/${parts.slice(0, index).join("/")}`, true);
|
||||
stat(root, `${base}/${pattern}`, false);
|
||||
}
|
||||
// Inventory without following links; curated-unit interpretation remains a runtime check.
|
||||
const pending = [base];
|
||||
let count = 0;
|
||||
while (pending.length) {
|
||||
const current = pending.pop()!;
|
||||
for (const entry of directories(root, current)) {
|
||||
if (++count > 100_000) fail(base, "evidence.source", "inventory_limit", "Reduce the Evidence tree below 100,000 entries before local validation.");
|
||||
const path = `${current}/${entry.name}`;
|
||||
if (entry.isDirectory()) pending.push(path);
|
||||
else {
|
||||
const info = stat(root, path, false);
|
||||
const relative = path.slice(base.length + 1);
|
||||
// Only apply content checks to selections whose meaning is unambiguous locally.
|
||||
// Arbitrary globs are expanded by the canonical Python adapter after startup.
|
||||
const curated = evidence.schema_version === 2 && relative.startsWith("curated/") && relative.endsWith(".md");
|
||||
const selected = curated || literals.includes(relative) || (patterns.includes("**/*.md") && relative.endsWith(".md"));
|
||||
if (selected && info.size > evidence.source.max_bytes) fail(path, "evidence.source.max_bytes", "evidence_too_large", "Reduce the source file or increase the declared max_bytes limit deliberately.");
|
||||
try { closeSync(openSync(join(root, path), "r")); }
|
||||
catch { fail(path, "$", "unreadable", "Grant read access to this Evidence file and retry validation."); }
|
||||
if (curated) {
|
||||
const text = readDocument(root, path);
|
||||
const frontmatter = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
||||
if (!frontmatter) fail(path, "$", "evidence_frontmatter", "Add a YAML frontmatter block delimited by --- to the curated Markdown unit; follow the Curated Evidence contract.");
|
||||
decode(frontmatter[1], path, (source) => parseAllDocuments(source)[0].toJSON());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "local-files";
|
||||
}
|
||||
|
||||
function validate(root: string, report: Report): void {
|
||||
directories(root, ".");
|
||||
const catalog = decode(readDocument(root, CATALOG_PATH), CATALOG_PATH, parseWorkspaceCatalogYaml);
|
||||
const ids = new Set(catalog.workspaces.map((entry) => entry.id));
|
||||
for (const entry of directories(root, ".")) {
|
||||
if (entry.name === ".git") continue;
|
||||
if (entry.isSymbolicLink()) fail(".", "$", "unsafe_reference", "Replace repository-root symbolic links with regular files or directories.");
|
||||
if (entry.isDirectory() && entry.name !== "workspace-docs" && !ids.has(entry.name)) {
|
||||
fail(".", "workspaces", "unlisted_directory", "Every root directory except workspace-docs must match a catalog workspace id; remove or register the extra directory.");
|
||||
}
|
||||
if (entry.name === "workspace-docs") {
|
||||
for (const docs of directories(root, "workspace-docs")) {
|
||||
if (!ids.has(docs.name)) fail("workspace-docs", "$", "unlisted_documentation", "Keep documentation only for workspace ids listed in the catalog.");
|
||||
for (const file of directories(root, `workspace-docs/${docs.name}`)) {
|
||||
const path = `workspace-docs/${docs.name}/${file.name}`;
|
||||
if (!["README.md", "contract.env.example"].includes(file.name)) fail(`workspace-docs/${docs.name}`, "$", "unsupported_documentation", "Keep only README.md and contract.env.example in workspace-docs/<id>. Place Evidence inside the workspace directory.");
|
||||
stat(root, path, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const entry of catalog.workspaces) {
|
||||
const document = `${entry.id}/workspace.yaml`;
|
||||
try {
|
||||
stat(root, entry.id, true);
|
||||
const descriptor = decode(readDocument(root, document), document, parseWorkspaceYaml);
|
||||
try { assertCatalogMatchesDescriptor(entry, descriptor); }
|
||||
catch { fail(document, "workspace", "catalog_mismatch", "Make id, name and description identical in the catalog, descriptor and workspace directory name."); }
|
||||
const evidence = inspectEvidence(root, descriptor);
|
||||
report.workspaces.push({ id: entry.id, evidence });
|
||||
if (evidence !== "absent") report.deferred_checks.push(`${entry.id}:evidence-source-selection`, `${entry.id}:evidence-content-provenance-and-indexing`);
|
||||
if (evidence === "remote-deferred") report.deferred_checks.push(`${entry.id}:remote-evidence-access`);
|
||||
} catch (error) {
|
||||
if (error instanceof DocumentError) report.issues.push(error.issue);
|
||||
else throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function prepare(root: string, options: Map<string, string>): void {
|
||||
const id = options.get("--id");
|
||||
const name = options.get("--name");
|
||||
const language = options.get("--language") ?? "en";
|
||||
const catalog = stringify({ schema_version: 1, workspaces: [{ id, name }] });
|
||||
const descriptor = stringify({ workspace: { schema_version: 4, id, name, language } });
|
||||
decode(catalog, CATALOG_PATH, parseWorkspaceCatalogYaml);
|
||||
decode(descriptor, "workspace.yaml", parseWorkspaceYaml);
|
||||
try { mkdirSync(root); }
|
||||
catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code === "EEXIST") fail(".", "--directory", "destination_exists", "Choose a new directory; preparation never overwrites an existing directory or its documents.");
|
||||
fail(".", "--directory", "destination_unavailable", "Create the parent directory and grant write access, then choose a new destination.");
|
||||
}
|
||||
try {
|
||||
mkdirSync(join(root, id!));
|
||||
mkdirSync(join(root, "workspace-docs", id!), { recursive: true });
|
||||
writeFileSync(join(root, CATALOG_PATH), "# Index of workspace identities. Keep metadata identical to each descriptor.\n" + catalog, { flag: "wx" });
|
||||
writeFileSync(join(root, id!, "workspace.yaml"), "# Authored workspace v4: optional Evidence; database binding belongs to the Metadata Catalog.\n" + descriptor, { flag: "wx" });
|
||||
writeFileSync(join(root, "workspace-docs", id!, "README.md"),
|
||||
"# Workspace documents / Documenti workspace\n\n" +
|
||||
"EN: Edit thoth-workspaces.yaml and <id>/workspace.yaml together. Evidence is optional and absent by default. Add reviewed source material under <id>/evidence only when configured. Database connections and schema belong to the installation Metadata Catalog. No example databases are downloaded.\n\n" +
|
||||
"IT: Modificare insieme thoth-workspaces.yaml e <id>/workspace.yaml. Le Evidence sono facoltative e inizialmente assenti. Inserire materiale verificato in <id>/evidence solo quando configurato. Connessioni e schema dei database appartengono al Metadata Catalog dell'installazione. Nessun database di esempio viene scaricato.\n\n" +
|
||||
"Repeat / Ripetere: `tht workspace validate --directory <repository>`. Local success does not establish runtime readiness or semantic truth / Il successo locale non certifica readiness o verità semantica.\n", { flag: "wx" });
|
||||
} catch {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
fail(".", "$", "prepare_failed", "Preparation could not write the documents; check disk space and permissions, then retry with a new directory.");
|
||||
}
|
||||
}
|
||||
|
||||
export function runWorkspaceDocuments(args: string[]): { status: number; output: string } {
|
||||
const report: Report = { schema_version: 1, scope: "local-documents", ok: false, workspaces: [], issues: [], deferred_checks: ["catalog-database-binding", "database-connectivity", "runtime-preprocessing"] };
|
||||
const json = args.includes("--json");
|
||||
let status = 1;
|
||||
try {
|
||||
const [command, ...rest] = args;
|
||||
if ((command === "prepare" || command === "validate") && rest.length === 1 && rest[0] === "--help") return { status: 0, output: usage };
|
||||
const allowed = command === "prepare" ? ["--directory", "--id", "--name", "--language"] : command === "validate" ? ["--directory"] : [];
|
||||
const options = new Map<string, string>();
|
||||
const seen = new Set<string>();
|
||||
for (let index = 0; index < rest.length; index++) {
|
||||
const key = rest[index];
|
||||
if (seen.has(key)) fail("CLI", "$", "usage", usage);
|
||||
seen.add(key);
|
||||
if (key === "--json") continue;
|
||||
if (!allowed.includes(key) || !rest[index + 1] || rest[index + 1].startsWith("--")) fail("CLI", "$", "usage", usage);
|
||||
options.set(key, rest[++index]);
|
||||
}
|
||||
if (!allowed.length || !options.has("--directory") || (command === "prepare" && (!options.has("--id") || !options.has("--name")))) fail("CLI", "$", "usage", usage);
|
||||
const root = resolve(options.get("--directory")!);
|
||||
if (command === "prepare") prepare(root, options);
|
||||
validate(root, report);
|
||||
report.ok = report.issues.length === 0;
|
||||
status = report.ok ? 0 : 1;
|
||||
} catch (error) {
|
||||
report.issues.push(error instanceof DocumentError ? error.issue : { document: ".", field: "$", code: "io_error", correction: "Check local permissions and regular files, then retry; no services were started." });
|
||||
if (report.issues[0].code === "usage") status = 2;
|
||||
}
|
||||
const output = json ? JSON.stringify(report) : [
|
||||
report.ok ? "Workspace documents pass local validation." : "Workspace documents require corrections.",
|
||||
...report.issues.map((issue) => `${issue.document}${issue.line ? `:${issue.line}` : ""} [${issue.field}] ${issue.code}: ${issue.correction}`),
|
||||
...report.workspaces.map((entry) => `${entry.id}: Evidence ${entry.evidence}`),
|
||||
`Deferred until runtime: ${report.deferred_checks.join(", ")}.`,
|
||||
].join("\n");
|
||||
return { status, output };
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync, symlinkSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import { afterEach, expect, test } from "vitest";
|
||||
import { parseWorkspaceCatalogYaml } from "../src/workspaces/catalog.js";
|
||||
import { parseWorkspaceYaml } from "../src/workspaces/schema.js";
|
||||
|
||||
const roots: string[] = [];
|
||||
function directory() {
|
||||
const root = mkdtempSync(join(tmpdir(), "tht-documents-"));
|
||||
roots.push(root);
|
||||
return join(root, "workspaces");
|
||||
}
|
||||
afterEach(() => roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })));
|
||||
|
||||
function cli(...args: string[]) {
|
||||
const packaged = process.env.THT_WORKSPACE_TEST_CLI;
|
||||
const result = spawnSync(packaged ?? process.execPath, [...(packaged ? ["workspace"] : ["--import", "tsx", resolve("src/workspace-documents-cli.ts")]), ...args, "--json"], {
|
||||
encoding: "utf8", env: { ...process.env, PATH: "" },
|
||||
});
|
||||
return { ...result, report: result.stdout.trim() ? JSON.parse(result.stdout) : null };
|
||||
}
|
||||
|
||||
const descriptor = "workspace:\n schema_version: 4\n id: practice\n name: Practice\n language: en\n";
|
||||
const catalog = "schema_version: 1\nworkspaces:\n - id: practice\n name: Practice\n";
|
||||
const corpus = [
|
||||
{ name: "minimal", descriptor, catalog, valid: true },
|
||||
{ name: "optional Evidence", descriptor: descriptor + "evidence:\n source:\n type: http\n uris: [https://example.com/manual.md]\n", catalog, valid: true },
|
||||
{ name: "duplicate YAML key", descriptor: descriptor + " id: practice\n", catalog, valid: false },
|
||||
{ name: "ambiguous document", descriptor: descriptor + "---\n" + descriptor, catalog, valid: false },
|
||||
{ name: "unknown workspace field", descriptor: descriptor + " secret: VERY_SECRET_VALUE\n", catalog, valid: false },
|
||||
{ name: "database binding in authored descriptor", descriptor: descriptor + "dwh: {password: VERY_SECRET_VALUE}\n", catalog, valid: false },
|
||||
{ name: "duplicate catalog id", descriptor, catalog: catalog + " - id: practice\n name: Practice\n", valid: false },
|
||||
{ name: "unknown catalog field", descriptor, catalog: catalog + "secret: VERY_SECRET_VALUE\n", valid: false },
|
||||
{ name: "invalid catalog YAML", descriptor, catalog: catalog + "schema_version: 1\n", valid: false },
|
||||
{ name: "unsafe Evidence URI", descriptor: descriptor + "evidence:\n source:\n type: http\n uris: [https://user:VERY_SECRET_VALUE@example.com/file]\n", catalog, valid: false },
|
||||
];
|
||||
|
||||
test.each(corpus)("CLI and runtime agree: $name", (fixture) => {
|
||||
const root = directory();
|
||||
mkdirSync(join(root, "practice"), { recursive: true });
|
||||
writeFileSync(join(root, "thoth-workspaces.yaml"), fixture.catalog);
|
||||
writeFileSync(join(root, "practice/workspace.yaml"), fixture.descriptor);
|
||||
let accepted = true;
|
||||
try { parseWorkspaceCatalogYaml(fixture.catalog); parseWorkspaceYaml(fixture.descriptor); }
|
||||
catch { accepted = false; }
|
||||
expect(accepted).toBe(fixture.valid);
|
||||
const checked = cli("validate", "--directory", root);
|
||||
expect(checked.status).toBe(fixture.valid ? 0 : 1);
|
||||
expect(checked.report.ok).toBe(accepted);
|
||||
expect(checked.stdout + checked.stderr).not.toContain("VERY_SECRET_VALUE");
|
||||
if (!fixture.valid) {
|
||||
expect(checked.report.issues[0].document).not.toBe(".");
|
||||
expect(checked.report.issues[0].correction.length).toBeGreaterThan(10);
|
||||
}
|
||||
});
|
||||
|
||||
test("prepare refuses existing directories and invalid options without changing documents", () => {
|
||||
const root = directory();
|
||||
expect(cli("prepare", "--directory", root, "--id", "practice", "--name", "Practice").status).toBe(0);
|
||||
const before = readFileSync(join(root, "thoth-workspaces.yaml"), "utf8");
|
||||
expect(cli("prepare", "--directory", root, "--id", "other", "--name", "Other").report.issues[0].code).toBe("destination_exists");
|
||||
expect(readFileSync(join(root, "thoth-workspaces.yaml"), "utf8")).toBe(before);
|
||||
expect(cli("validate", "--directory", root, "--typo", "VERY_SECRET_VALUE").status).toBe(2);
|
||||
});
|
||||
|
||||
test("validation rejects directory mismatches, missing references and symlinks without following them", () => {
|
||||
const root = directory();
|
||||
cli("prepare", "--directory", root, "--id", "practice", "--name", "Practice");
|
||||
mkdirSync(join(root, "unlisted"));
|
||||
expect(cli("validate", "--directory", root).report.issues.some((i: {code: string}) => i.code === "unlisted_directory")).toBe(true);
|
||||
rmSync(join(root, "unlisted"), { recursive: true });
|
||||
writeFileSync(join(root, "practice/workspace.yaml"), descriptor.replace("name: Practice", "name: Different"));
|
||||
expect(cli("validate", "--directory", root).report.issues[0].code).toBe("catalog_mismatch");
|
||||
writeFileSync(join(root, "practice/workspace.yaml"), descriptor + "evidence:\n source:\n type: filesystem\n uri: practice/evidence\n");
|
||||
expect(cli("validate", "--directory", root).report.issues[0].code).toBe("missing_reference");
|
||||
symlinkSync(roots[roots.length - 1], join(root, "practice/evidence"), "dir");
|
||||
expect(cli("validate", "--directory", root).report.issues[0].code).toBe("unsafe_reference");
|
||||
});
|
||||
|
||||
test("local Evidence checks references and YAML frontmatter, and explicitly defers canonical content validation", () => {
|
||||
const root = directory();
|
||||
cli("prepare", "--directory", root, "--id", "practice", "--name", "Practice");
|
||||
writeFileSync(join(root, "practice/workspace.yaml"), descriptor + "evidence:\n schema_version: 2\n source:\n type: filesystem\n uri: practice/evidence\n patterns: ['curated/**/*.md']\n");
|
||||
mkdirSync(join(root, "practice/evidence/curated/domain"), { recursive: true });
|
||||
const evidence = join(root, "practice/evidence/curated/domain/rule.md");
|
||||
writeFileSync(evidence, "---\nschema_version: 4\nid: evidence:rule\nkind: domain\nlanguage: en\npurposes: [sql_generation]\n---\n# Rule\n\n## Rule\nUse the order number.\n");
|
||||
const checked = cli("validate", "--directory", root);
|
||||
expect(checked.status).toBe(0);
|
||||
expect(checked.report.workspaces).toEqual([{ id: "practice", evidence: "local-files" }]);
|
||||
expect(checked.report.deferred_checks).toContain("practice:evidence-content-provenance-and-indexing");
|
||||
writeFileSync(evidence, "---\nid: first\nid: VERY_SECRET_VALUE\n---\n# Rule\n");
|
||||
const invalid = cli("validate", "--directory", root);
|
||||
expect(invalid.status).toBe(1);
|
||||
expect(invalid.report.issues[0].document).toBe("practice/evidence/curated/domain/rule.md");
|
||||
expect(invalid.stdout).not.toContain("VERY_SECRET_VALUE");
|
||||
writeFileSync(join(root, "practice/workspace.yaml"), descriptor + "evidence:\n source:\n type: filesystem\n uri: practice/evidence\n patterns: [missing.md]\n");
|
||||
expect(cli("validate", "--directory", root).report.issues[0].code).toBe("missing_reference");
|
||||
});
|
||||
|
||||
test("prepare creates documents accepted by the runtime and validate is repeatable without installation or services", () => {
|
||||
const root = directory();
|
||||
const prepared = cli("prepare", "--directory", root, "--id", "practice", "--name", "Practice");
|
||||
expect(prepared.stderr).toBe("");
|
||||
expect(prepared.status).toBe(0);
|
||||
expect(prepared.report.ok).toBe(true);
|
||||
const catalog = readFileSync(join(root, "thoth-workspaces.yaml"), "utf8");
|
||||
const descriptor = readFileSync(join(root, "practice/workspace.yaml"), "utf8");
|
||||
expect(parseWorkspaceCatalogYaml(catalog).workspaces[0].id).toBe("practice");
|
||||
expect(parseWorkspaceYaml(descriptor).evidence).toBeUndefined();
|
||||
for (let index = 0; index < 2; index++) {
|
||||
const checked = cli("validate", "--directory", root);
|
||||
expect(checked.status).toBe(0);
|
||||
expect(checked.report.workspaces).toEqual([{ id: "practice", evidence: "absent" }]);
|
||||
}
|
||||
expect(readFileSync(join(root, "thoth-workspaces.yaml"), "utf8")).toBe(catalog);
|
||||
expect(readFileSync(join(root, "practice/workspace.yaml"), "utf8")).toBe(descriptor);
|
||||
});
|
||||
@@ -7,6 +7,63 @@ question, queries an enterprise database read-only, and guides the user through
|
||||
core, PostgreSQL catalog, Qdrant, embedding service, and Pi run in Docker; Node.js, Python, and Pi
|
||||
are not required on the host.
|
||||
|
||||
## Prepare and validate workspace documents before starting the stack
|
||||
|
||||
The first two steps of the new flow work without Docker, Node, Python, Pi or an
|
||||
installation descriptor. Use the platform bundle with **both** `tht` and
|
||||
`tht-workspace-documents` in the same directory (`.exe` on Windows). Put that directory
|
||||
on `PATH`, or invoke the absolute executable path. Older packages containing only
|
||||
`tht` do not provide this capability. Maintainers can currently build the bundle;
|
||||
publishing assets and Docker Hub images belongs to a later delivery step. The rest
|
||||
of this guide still describes the existing installation path.
|
||||
|
||||
1. Choose a new directory outside the application checkout, with an existing parent:
|
||||
|
||||
```sh
|
||||
tht workspace prepare --directory ./my-workspaces --id practice --name "Practice" --language en
|
||||
```
|
||||
|
||||
This creates `thoth-workspaces.yaml`, `practice/workspace.yaml` and
|
||||
`workspace-docs/practice/README.md`. Existing destinations, even empty ones, are
|
||||
refused. No services start, Git is not initialized and no remote is contacted.
|
||||
Example databases remain a deferred subproject. For a curator-supplied repository,
|
||||
use a separate local copy and go straight to step 3; read access to the origin is
|
||||
sufficient.
|
||||
2. Edit the catalog (schema v1) and workspace descriptor (schema v4) at your own pace.
|
||||
Keep `id`, `name` and optional `description` identical in both; the id must match
|
||||
the directory name. Root directories must match catalog entries, except
|
||||
`workspace-docs` and the local `.git` directory. Database connections, schema and
|
||||
credentials belong to the installation Metadata Catalog. Evidence is optional
|
||||
and initially absent.
|
||||
3. Validate, correct the reported document/field, and repeat:
|
||||
|
||||
```sh
|
||||
tht workspace validate --directory ./my-workspaces
|
||||
tht workspace validate --directory ./my-workspaces --json
|
||||
```
|
||||
|
||||
PowerShell uses the same arguments, for example
|
||||
`C:\ThothII\bin\tht.exe workspace validate --directory C:\ThothII\my-workspaces`.
|
||||
Validation changes no files. It rejects multiple/malformed YAML documents,
|
||||
duplicate keys/ids, unknown fields, catalog/directory/descriptor mismatches,
|
||||
missing local references and symbolic links. Fix the first error in each document
|
||||
and repeat to reveal any subsequent errors.
|
||||
|
||||
Evidence `absent` is valid. Filesystem checks cover directories, accessibility and
|
||||
literal references; standard Markdown selections also check declared size limits.
|
||||
Evidence v2 requires `curated/` and syntactically valid YAML frontmatter. Local limits
|
||||
are 1 MiB per document read and 100,000 entries per Evidence tree. Arbitrary patterns,
|
||||
the complete curated-unit contract, provenance, HTTP/S3 access and indexing remain
|
||||
explicit runtime checks. See the [Evidence guide](../evidence.md).
|
||||
|
||||
JSON includes `schema_version`, `scope: local-documents`, `ok`, `workspaces`, `issues`
|
||||
and `deferred_checks`. Issues identify document, field, code, correction and YAML
|
||||
line where available, without printing document values. Exit statuses: `0` local
|
||||
success, `1` documents/access/bundle need correction, `2` invalid arguments. Local
|
||||
success does not certify semantic truth, connectivity or readiness. The Git revision
|
||||
activated later must contain the checked documents; this command does not publish
|
||||
uncommitted files or empty directories.
|
||||
|
||||
## Before you start: the two repositories
|
||||
|
||||
There are two separate repositories:
|
||||
|
||||
@@ -7,6 +7,64 @@ naturale, interroga in sola lettura un database aziendale e accompagna l’utent
|
||||
della SQL risultante. Il core, il catalogo PostgreSQL, Qdrant, il servizio di embedding e Pi vengono
|
||||
eseguiti in Docker; sul computer non servono Node.js, Python o Pi.
|
||||
|
||||
## Preparazione e verifica dei workspace prima dello stack
|
||||
|
||||
I primi due passi del nuovo percorso funzionano senza Docker, Node, Python, Pi o
|
||||
un file di installazione. Usare il bundle della propria piattaforma con **entrambi**
|
||||
gli eseguibili `tht` e `tht-workspace-documents` nella stessa cartella (`.exe` su
|
||||
Windows). Aggiungere la cartella al `PATH`, oppure usare il percorso completo.
|
||||
Il vecchio pacchetto con il solo `tht` non contiene questa capacità. Il bundle è
|
||||
attualmente producibile dal manutentore; pubblicazione degli asset e immagini
|
||||
Docker Hub appartengono a una fase successiva. Il resto della guida descrive ancora
|
||||
il percorso di installazione esistente.
|
||||
|
||||
1. Scegliere una cartella nuova, esterna all'applicazione, con padre già esistente:
|
||||
|
||||
```sh
|
||||
tht workspace prepare --directory ./miei-workspace --id pratica --name "Pratica" --language it
|
||||
```
|
||||
|
||||
Sono creati `thoth-workspaces.yaml`, `pratica/workspace.yaml` e
|
||||
`workspace-docs/pratica/README.md`. Una destinazione esistente, anche vuota, viene
|
||||
rifiutata. Nessun servizio viene avviato; Git non viene inizializzato, nessun remoto
|
||||
viene contattato. I database di esempio restano un sottoprogetto differito. Per
|
||||
un repository fornito dal curatore, usare una copia locale separata e passare al
|
||||
punto 3: è sufficiente accesso in lettura all'origine.
|
||||
2. Modificare con calma catalogo (schema v1) e descrittore workspace (schema v4).
|
||||
Mantenere uguali `id`, `name` e l'eventuale `description` nei due file; l'id deve
|
||||
coincidere con la cartella. Ogni cartella alla radice deve corrispondere a un
|
||||
workspace elencato, salvo `workspace-docs` e la directory locale `.git`.
|
||||
Connessioni, schema e credenziali dei database appartengono al Metadata Catalog
|
||||
dell'installazione. Le Evidence sono facoltative e inizialmente assenti.
|
||||
3. Verificare, correggere il documento/campo indicato e ripetere:
|
||||
|
||||
```sh
|
||||
tht workspace validate --directory ./miei-workspace
|
||||
tht workspace validate --directory ./miei-workspace --json
|
||||
```
|
||||
|
||||
Su PowerShell usare gli stessi argomenti, ad esempio
|
||||
`C:\ThothII\bin\tht.exe workspace validate --directory C:\ThothII\miei-workspace`.
|
||||
Il controllo non modifica file. Rifiuta YAML multipli o malformati, chiavi/id
|
||||
duplicati, campi sconosciuti, incoerenze tra catalogo, cartelle e descrittori,
|
||||
riferimenti locali mancanti e link simbolici. Correggere il primo errore del
|
||||
documento e ripetere per vedere eventuali errori successivi.
|
||||
|
||||
Evidence `absent` è valido. Per filesystem si verificano directory, accessibilità e
|
||||
riferimenti letterali; per le selezioni Markdown standard anche i limiti dichiarati.
|
||||
Evidence v2 richiede `curated/` e frontmatter con sintassi YAML valida. I limiti locali
|
||||
sono 1 MiB per documento letto e 100.000 elementi per albero Evidence. Pattern
|
||||
arbitrari, contratto completo delle unità curate, provenienza, accesso HTTP/S3 e
|
||||
indicizzazione restano controlli runtime espliciti. Vedere la [guida Evidence](../evidence.md).
|
||||
|
||||
Il JSON espone `schema_version`, `scope: local-documents`, `ok`, `workspaces`, `issues`
|
||||
e `deferred_checks`. I problemi riportano documento, campo, codice, correzione e,
|
||||
quando disponibile, riga YAML, senza stampare i valori del documento. Exit status:
|
||||
`0` successo locale, `1` documenti/accesso/bundle da correggere, `2` argomenti errati.
|
||||
Il successo locale non certifica verità semantica, connettività o readiness. La
|
||||
revisione Git attivata in seguito deve contenere i documenti verificati; il comando
|
||||
non pubblica file non committati o directory vuote.
|
||||
|
||||
## Prima di iniziare: i due repository
|
||||
|
||||
Servono due repository distinti:
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
**Stato:** design concordato con grill-with-docs il 2026-09-14. Questo worktree definisce e rende
|
||||
verificabile il percorso manuale; non introduce pacchetti nativi.
|
||||
|
||||
**Aggiornamento:** il [PRD del 27 settembre](2026-09-27-guided-installation-prd.md)
|
||||
rende le immagini precompilate su Docker Hub il percorso ordinario e include la
|
||||
loro pubblicazione nel progetto. Il percorso con build da sorgente documentato qui
|
||||
resta un'alternativa; il precedente rinvio di Docker Hub è superato.
|
||||
La revisione del 28 settembre dello stesso PRD sostituisce inoltre il setup
|
||||
interattivo con preparazione dei documenti, verifiche ripetibili ed esecuzione
|
||||
senza richiesta di parametri.
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Permettere di predisporre una copia di THothII su macOS, Windows e Linux partendo dal clone del
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
# PRD — Installazione di ThothII da documenti verificati
|
||||
|
||||
Creato: 2026-09-27. Revisione: 2026-09-28. Stato: requisiti e chiarimenti R1/R2
|
||||
approvati; `grill-with-docs` e `/to-spec` conclusi. Specifica pubblicata su Gitea
|
||||
con etichetta `ready-for-agent`; implementazione non iniziata.
|
||||
Branch: `codex/guided-standalone-install`.
|
||||
|
||||
La [specifica derivata](2026-09-28-document-first-installation-spec.md) raccoglie
|
||||
user story, decisioni implementative e collaudi. Il piano di test è stato confermato
|
||||
dall'utente e la specifica è pubblicata nell'issue
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
La [scomposizione approvata](2026-09-28-installation-ticket-breakdown.md) è pubblicata
|
||||
nelle issue #43–#54 con dipendenze native. Il prossimo passaggio è `/implement`
|
||||
sui ticket senza blocchi, inizialmente validazione workspace e rilascio Docker Hub.
|
||||
|
||||
Questo documento consolida le decisioni della
|
||||
[ripresa del progetto](2026-09-27-guided-installation-resumption.md) e aggiorna il
|
||||
[piano standalone del 14 settembre](2026-09-14-manual-standalone-installation.md)
|
||||
per l'esperienza guidata. Conserva architettura, protezione dei segreti e contratti
|
||||
del prodotto; modifica il percorso operativo e l'ordine dei collaudi. La successiva
|
||||
precisazione dell'utente rende la distribuzione di immagini precompilate su Docker Hub
|
||||
parte della prima versione del percorso ordinario, superando il precedente rinvio.
|
||||
La revisione del 28 settembre sostituisce la raccolta interattiva dei parametri:
|
||||
si preparano prima i documenti, li si verifica anche più volte, poi si esegue il setup.
|
||||
Prevale sulle precedenti decisioni I1/I2 dove consentivano configurazioni obbligatorie
|
||||
rinviate o richieste durante l'installazione.
|
||||
|
||||
## Obiettivo e destinatario
|
||||
|
||||
Una persona capace di installare Docker, clonare un repository e fornire le proprie
|
||||
credenziali deve poter predisporre con calma i documenti necessari e rendere
|
||||
utilizzabile almeno un workspace, senza conoscere l'architettura interna.
|
||||
Template commentati, esempi compilati e documentazione passo per passo spiegano
|
||||
cosa inserire nei file YAML e nei file protetti `.env` o equivalenti.
|
||||
DWH e provider LLM possono essere esterni; non si promette un funzionamento offline.
|
||||
|
||||
La CLI offre preparazione dei template, verifiche ripetibili e applicazione dei
|
||||
documenti già verificati. Il setup non raccoglie parametri, non apre questionari
|
||||
e non completa silenziosamente documenti incompleti. L'utente corregge i documenti
|
||||
prima di eseguirlo. Le pagine amministrative rimangono disponibili per l'uso e la
|
||||
manutenzione successivi, senza diventare una scorciatoia per rinviare parametri
|
||||
obbligatori dell'installazione.
|
||||
|
||||
Il percorso predefinito scarica da Docker Hub le immagini applicative già compilate:
|
||||
il computer dell'utente svolge configurazione, inizializzazione dei servizi e dei
|
||||
database, avvio e verifiche. L'installazione da sorgente resta disponibile come
|
||||
scelta esplicita alternativa. Nessuna compilazione dell'applicazione, neppure
|
||||
all'interno di un container locale, è richiesta dal percorso ordinario.
|
||||
|
||||
## Decisioni approvate
|
||||
|
||||
| Area | Comportamento richiesto |
|
||||
| --- | --- |
|
||||
| Distribuzione predefinita | Creare, collaudare e pubblicare su Docker Hub le immagini applicative precompilate; il setup le scarica e le avvia senza build locale. |
|
||||
| Alternativa da sorgente | Conservare un percorso esplicito di build dai sorgenti, documentato e verificato, con configurazione e funzionalità equivalenti. |
|
||||
| Due traguardi | Mostrare separatamente piattaforma installata e workspace pronto. |
|
||||
| Preparazione anticipata | Repository workspace e documenti applicativi predisposti prima dell'esecuzione; template, esempi e guida alla compilazione. |
|
||||
| Setup senza domande | Consuma documenti già verificati, mostra avanzamento ed errori e non chiede valori mancanti. |
|
||||
| Modelli | Provider, modelli, usi, endpoint e riferimenti alle credenziali descritti nei documenti prima del setup; configurazioni di esempio supportate e commentate. |
|
||||
| Embedding | Configurazione locale precompilata come percorso ordinario. |
|
||||
| Ripresa | Correggere i documenti, ripetere le verifiche e riprendere l'esecuzione senza questionari né perdita del lavoro completato. |
|
||||
| Workspace | Preparare prima repository e descriptor conformi; dichiarare separatamente i parametri di collegamento ai database secondo i contratti ThothII. |
|
||||
| Contenuti | Riutilizzare descrizioni/Evidence curate; nessuna generazione AI implicita per completare un documento. Eventuali attività di curation restano esplicite. |
|
||||
| Evidence | Opzionali nel contratto; se configurate devono essere valide e utilizzabili. |
|
||||
| Collaudi | Prima Windows, poi Omarchy su PC Intel, infine macOS, in tre tappe distinte. |
|
||||
|
||||
## Rilascio e distribuzione delle immagini
|
||||
|
||||
La creazione e pubblicazione delle immagini appartengono al processo di rilascio
|
||||
del progetto. Il sottoprogetto installazione comprende quindi anche una procedura
|
||||
riproducibile per costruire, verificare e pubblicare queste immagini su Docker Hub;
|
||||
non basta aggiungere un'opzione di pull senza fornire immagini utilizzabili.
|
||||
|
||||
**Stato iniziale dichiarato dall'utente il 28 settembre:** le immagini applicative
|
||||
ThothII su Docker Hub non sono disponibili. Prima di collaudare l'installazione
|
||||
precompilata su un PC Windows o Linux occorre produrle, pubblicarle e verificarne
|
||||
il download. Questa dipendenza è bloccante per quel collaudo, non viene aggirata
|
||||
usando immagini costruite soltanto nella cache della macchina di test.
|
||||
|
||||
Il progetto deve fornire un comando di produzione e pubblicazione, mantenuto nel
|
||||
repository e documentato per il manutentore. Il comando riceve revisione/versione,
|
||||
namespace Docker Hub e architetture, costruisce e verifica le immagini proprietarie,
|
||||
le pubblica e produce il manifest di rilascio con digest e artefatti compatibili.
|
||||
Il nome e la sintassi saranno fissati nella specifica; il comando non è ancora
|
||||
implementato. Le credenziali di pubblicazione appartengono al manutentore e non
|
||||
entrano nei documenti dell'utente che installerà ThothII.
|
||||
|
||||
La sequenza di rilascio è: produzione e controlli, pubblicazione su Docker Hub,
|
||||
verifica del pull del rilascio pubblicato, quindi collaudo della procedura sui
|
||||
sistemi destinatari. Questa fase del manutentore precede i sei passi dell'utente.
|
||||
|
||||
Il pacchetto distribuito deve comprendere tutto ciò che serve all'installazione:
|
||||
immagini applicative, manifest Compose/configurazione di avvio, migrazioni e risorse
|
||||
di inizializzazione, oltre al comando operatore o al suo bootstrap. Il numero delle
|
||||
immagini segue i servizi dell'architettura corrente: non è richiesto accorpare tutto
|
||||
in un singolo container. I servizi di terze parti mantengono immagini compatibili
|
||||
con lo stack, senza ricostruirli sul computer dell'utente.
|
||||
|
||||
Nell'architettura corrente le immagini proprietarie da pubblicare sono `core` e
|
||||
`frontend`; PostgreSQL, Qdrant e Ollama usano immagini upstream. Le attività
|
||||
`catalog-migrate` e `workspace-maintenance` riusano la stessa immagine release di
|
||||
`core`. Il pacchetto di installazione include anche le risorse oggi montate dal
|
||||
checkout, fra cui `docker/catalog-db-init.sql` e `docker/embedding-model-init.sh`.
|
||||
Il download del modello embedding, la creazione dei volumi/database e le migrazioni
|
||||
restano attività di inizializzazione locale, distinte dalla compilazione.
|
||||
|
||||
Ogni rilascio identifica una versione coerente di immagini, CLI e configurazione;
|
||||
il manifest registra riferimenti verificabili, inclusi i digest delle immagini.
|
||||
Il setup riporta la versione installata e non combina automaticamente componenti
|
||||
incompatibili tramite tag mobili. Nomi e namespace Docker Hub saranno definiti
|
||||
nella specifica di pubblicazione; non sono presunti già esistenti.
|
||||
|
||||
Il percorso ordinario deve poter partire dal pacchetto di rilascio senza richiedere
|
||||
il checkout dei sorgenti applicativi o strumenti di compilazione. Anche l'eventuale
|
||||
CLI nativa deve essere distribuita già compilata per gli host supportati; nascondere
|
||||
una compilazione di `tht` nel bootstrap non soddisfa il requisito.
|
||||
|
||||
L'installazione pubblica non richiede credenziali di pubblicazione Docker Hub.
|
||||
Le immagini non includono credenziali dell'installazione, dati personali, workspace
|
||||
dell'operatore o i database di esempio preinstallati. Configurazione e dati
|
||||
persistenti vengono creati localmente nei percorsi e volumi dell'installazione.
|
||||
|
||||
Il supporto iniziale Windows/WSL2 e Omarchy richiede immagini Linux amd64; per la
|
||||
tappa macOS Apple Silicon servono immagini Linux arm64 e un bootstrap host adeguato.
|
||||
La pubblicazione dichiara solo le architetture effettivamente verificate, rispettando
|
||||
l'ordine dei collaudi concordato.
|
||||
|
||||
La modalità sorgente costruisce gli stessi componenti a partire da una revisione
|
||||
esplicita, documenta i prerequisiti aggiuntivi e usa gli stessi contratti di
|
||||
configurazione, persistenza e migrazione. Un errore di download da Docker Hub non
|
||||
deve attivarla automaticamente: l'utente può correggere il problema e riprovare,
|
||||
oppure scegliere consapevolmente l'alternativa da sorgente.
|
||||
|
||||
## Percorso dell'utente
|
||||
|
||||
Prima dei sei passi sono disponibili guida, template e strumenti di verifica già
|
||||
compilati. Git e gli strumenti minimi necessari per acquisire i documenti sono
|
||||
esplicitati nella guida; la verifica completa dell'host rimane al passo 3. I primi
|
||||
controlli documentali non devono richiedere l'avvio di ThothII o dei suoi container.
|
||||
|
||||
### 1. Preparazione del repository dei workspace
|
||||
|
||||
L'utente prepara una copia del repository predefinito con Financial, European
|
||||
Football e F1, oppure un repository ad hoc a partire da un template documentato.
|
||||
Il repository predefinito contiene definizioni, documentazione, Evidence e riferimenti
|
||||
ai pacchetti dati; il clone non equivale ad aver già creato i database PostgreSQL.
|
||||
La disponibilità effettiva del percorso predefinito dipende dal sottoprogetto esempi.
|
||||
|
||||
Si preservano le scelte già approvate sulla copia autonoma o sull'accesso in sola
|
||||
lettura all'originale; workspace ed Evidence locali restano modificabili. La
|
||||
preparazione non richiede diritti di push al repository pubblico e non sostituisce
|
||||
un repository già configurato senza una scelta esplicita.
|
||||
|
||||
### 2. Verifica dei documenti dei workspace
|
||||
|
||||
Un comando dedicato verifica sintassi YAML, versione/schema ThothII, campi richiesti,
|
||||
tipi, identificatori, unicità, corrispondenza fra catalogo e directory, descriptor
|
||||
referenziati, percorsi e file Evidence dove configurati. La verifica è ripetibile
|
||||
sui file locali prima che Docker o ThothII siano in esecuzione.
|
||||
|
||||
La verifica sostanziale copre ciò che è dimostrabile dai documenti: coerenza dei
|
||||
riferimenti, esistenza e leggibilità dei contenuti, conformità delle Evidence e
|
||||
assenza di contraddizioni rilevabili. Non pretende di certificare automaticamente
|
||||
la verità delle regole di dominio o interrogare database non ancora creati.
|
||||
|
||||
Ogni errore identifica documento, campo e, quando disponibile, riga, con indicazione
|
||||
della correzione. L'utente modifica i documenti e ripete il controllo. Le Evidence
|
||||
restano opzionali: assenza dichiarata ed Evidence configurate ma invalide sono
|
||||
condizioni diverse. I controlli incrociati che richiedono i parametri applicativi
|
||||
vengono completati al passo 5.
|
||||
|
||||
### 3. Verifica delle precondizioni
|
||||
|
||||
Verificare sistema/architettura, Docker e Compose, accesso al daemon, risorse e spazio
|
||||
richiesti, percorsi e permessi, porte previste, accesso ai servizi esterni e al registry
|
||||
per quanto valutabile. Su Windows verificare Ubuntu WSL2 e integrazione Docker
|
||||
Desktop. I requisiti dipendenti da valori scelti al passo 4 sono ricontrollati al 5.
|
||||
|
||||
Distinguere componenti necessari sull'host da componenti inclusi nelle immagini:
|
||||
Pi appartiene a `core`, non è un prerequisito da installare separatamente sul PC.
|
||||
Presenza e versione di Pi sono verificate nel rilascio; il funzionamento effettivo
|
||||
nel container è verificato al passo 6. Lo stesso principio vale per le dipendenze
|
||||
applicative già incluse. Go, Python, Node e compilatori non sono prerequisiti host
|
||||
del percorso precompilato.
|
||||
|
||||
### 4. Preparazione dei parametri applicativi
|
||||
|
||||
L'utente compila i documenti locali usando template commentati ed esempi: descriptor
|
||||
di installazione, configurazione dei modelli e riferimenti ai file protetti `.env`
|
||||
o equivalenti. Sono espliciti campi obbligatori, opzionali, default e condizioni in
|
||||
cui un parametro serve. La preparazione può svolgersi in più sessioni senza avviare
|
||||
il setup o i servizi applicativi.
|
||||
|
||||
I documenti definiscono versione del rilascio, percorsi/volumi, profilo e accesso,
|
||||
repository/workspace selezionati, provider/modelli per i rispettivi usi, endpoint,
|
||||
embedding, parametri di collegamento ai database e riferimenti ai segreti. La
|
||||
configurazione dei modelli deriva dall'Installation Model Catalog, senza un secondo
|
||||
catalogo del setup. L'embedding locale ha un esempio precompilato.
|
||||
|
||||
Il descriptor workspace v4 continua a contenere identità ed Evidence: non vi si
|
||||
inseriscono campi database o modelli estranei al contratto. I binding database sono
|
||||
predisposti in un input locale separato, da specificare, e applicati al Metadata
|
||||
Catalog durante il setup mediante i suoi servizi; non diventano una seconda autorità
|
||||
runtime. La configurazione server/Omics rimane fuori dal perimetro.
|
||||
|
||||
I segreti non entrano nel repository pubblico, nei log o nei rapporti di verifica.
|
||||
Per le credenziali tecniche interne un comando preparatorio può generare file
|
||||
protetti prima delle verifiche, senza questionario né richiesta durante il setup.
|
||||
Le selezioni degli esempi e le eventuali operazioni facoltative sono dichiarate
|
||||
prima dell'esecuzione. Le pagine amministrative restano disponibili dopo l'avvio
|
||||
per modifiche e curation, non per raccogliere valori obbligatori dimenticati.
|
||||
|
||||
### 5. Verifica dei parametri applicativi
|
||||
|
||||
Un comando ripetibile controlla completezza e correttezza dei documenti, sintassi
|
||||
e compatibilità dei valori, riferimenti ai segreti, modelli/usi/default, collegamenti
|
||||
workspace/database, configurazione Compose, disponibilità del rilascio nel registry
|
||||
e compatibilità delle architetture. Completa i controlli incrociati dei passi 2 e 3.
|
||||
|
||||
Quando fattibile senza creare lo stack, verifica raggiungibilità, autenticazione
|
||||
e compatibilità delle dipendenze esterne con operazioni circoscritte; la documentazione
|
||||
spiega le prove effettuate, inclusi eventuali accessi a provider a consumo.
|
||||
Non cambia dati applicativi né esegue migrazioni o importazioni.
|
||||
|
||||
Il rapporto distingue `superato`, `errore`, `avviso` e `non ancora verificabile`,
|
||||
senza trasformare assenza di verifica in successo. I controlli che richiedono lo
|
||||
stack sono elencati prima e obbligatori al passo 6, secondo R2 approvata.
|
||||
Un errore formale o una configurazione obbligatoria mancante blocca l'esecuzione.
|
||||
|
||||
Il risultato identifica i documenti e la revisione del repository esaminati. Una
|
||||
modifica successiva invalida i controlli dipendenti: il setup non deve applicare
|
||||
file diversi da quelli verificati senza ricontrollarli. Segreti e loro valori
|
||||
non vengono copiati nel rapporto.
|
||||
|
||||
### 6. Setup esecutivo
|
||||
|
||||
Il setup ricontrolla l'ammissibilità del piano verificato, scarica le immagini del
|
||||
rilascio da Docker Hub, crea reti/volumi/container e inizializza i database applicativi.
|
||||
Esegue migrazioni, applicazione della configurazione e dei binding, sincronizzazione
|
||||
e preparazione necessaria dei workspace secondo i contratti esistenti. Quando
|
||||
disponibili e selezionati, crea e carica i database di esempio dal relativo pacchetto.
|
||||
|
||||
Non pone domande su provider, modelli, percorsi, credenziali o altri parametri.
|
||||
Se trova un valore mancante o incoerente, si ferma con una diagnosi e rimanda alla
|
||||
correzione dei documenti e alla loro verifica; non apre un wizard di riparazione.
|
||||
Le conferme dei contratti di dominio non vengono aggirate: la specifica deve
|
||||
distinguere operazioni predisponibili nel piano da attività umane residue senza
|
||||
reinserire la raccolta dei parametri durante l'installazione.
|
||||
|
||||
Esegue i controlli disponibili solo a runtime: salute dei servizi, Pi, modello
|
||||
embedding effettivamente caricato, collegamenti dalla rete dei container, Catalog
|
||||
e preparazione dei workspace. Mostra separatamente piattaforma avviata e workspace
|
||||
pronto, più eventuali verifiche funzionali ancora da svolgere. Il collaudo completo
|
||||
include una domanda reale con revisione umana, senza SQL target di benchmark.
|
||||
|
||||
## Documentazione di accompagnamento
|
||||
|
||||
Le guide italiana e inglese seguono esattamente i sei passi. Per ciascuno indicano
|
||||
input, file da predisporre, template ed esempio compilato, comando di verifica,
|
||||
esito atteso, errori comuni e passaggio successivo. Un elenco dei documenti e dei
|
||||
segreti necessari consente di raccogliere le informazioni in anticipo.
|
||||
|
||||
Le istruzioni distinguono manutentore del rilascio e utente installatore, host e
|
||||
container, controlli locali e runtime. Il percorso sorgente è esplicitamente
|
||||
alternativo; un download fallito non ne provoca l'attivazione automatica.
|
||||
|
||||
## Avanzamento, errori e ripresa
|
||||
|
||||
La procedura conserva l'installazione di riferimento, gli input verificati, i
|
||||
passaggi completati, l'ultimo errore e il prossimo passo, senza conservare segreti
|
||||
nello stato di avanzamento. Alla ripresa verifica lo stato reale: una vecchia spunta
|
||||
non prova che servizio, credenziale o indice siano ancora validi.
|
||||
|
||||
Correggere un endpoint o una credenziale non impone di rifare tutto il setup. La
|
||||
specifica deve definire quali verifiche dipendenti vanno ripetute, preservando
|
||||
configurazioni, workspace, sessioni e contenuti non coinvolti nella modifica.
|
||||
Le modifiche manuali vengono riconosciute e spiegate, non cancellate implicitamente.
|
||||
|
||||
La ripresa riguarda le tappe della procedura: non promette una ripresa interna
|
||||
di operazioni che non la supportano, come il preprocessing corrente. In questi
|
||||
casi il passaggio viene rieseguito in modo coerente con il suo contratto.
|
||||
|
||||
Un fallimento riporta fase, causa comprensibile, correzione consigliata e modalità
|
||||
di ripresa. Distinguere problemi dell'host, dei servizi locali e delle dipendenze
|
||||
esterne. Un provider o DWH indisponibile non annulla una verifica valida della
|
||||
piattaforma, ma impedisce di dichiarare il percorso complessivo pronto.
|
||||
|
||||
## Criteri di accettazione
|
||||
|
||||
| Scenario | Esito verificabile |
|
||||
| --- | --- |
|
||||
| Rilascio Docker Hub | Immagini costruite e pubblicate con versione, digest e architetture dichiarate; avvio verificato usando quanto effettivamente scaricato dal registry. |
|
||||
| Installazione precompilata | Su host senza toolchain e senza sorgenti applicativi, il setup scarica le immagini e completa configurazione/avvio senza compilare né invocare build locali. |
|
||||
| Risorse di avvio | Compose, migrazioni e inizializzazione non dipendono da file presenti soltanto in un checkout dei sorgenti. |
|
||||
| Download fallito | Errore comprensibile e ripetibile; nessuna build da sorgente avviata implicitamente. |
|
||||
| Modalità sorgente | Scelta esplicita ancora funzionante, con gli stessi contratti di configurazione e persistenza del rilascio precompilato. |
|
||||
| Preparazione documentale | Template e guida consentono di predisporre tutti i YAML e file protetti necessari prima dell'esecuzione. |
|
||||
| Ordine dei passi | Repository, verifica workspace, precondizioni, parametri applicativi, verifica parametri, setup esecutivo. |
|
||||
| Verifica workspace senza stack | Il passo 2 funziona senza Docker attivo o applicazione installata e senza toolchain host aggiuntive. |
|
||||
| Controlli ripetibili | Ripetere i controlli non crea container, non migra DB e non modifica i documenti dell'utente. |
|
||||
| Completezza prima del setup | Un campo obbligatorio mancante blocca l'esecuzione, indicando file/campo e correzione; nessuna domanda interattiva. |
|
||||
| Input modificati | I controlli dipendenti sono invalidati o ripetuti; nessuna applicazione di input diversi da quelli verificati. |
|
||||
| Setup non interattivo | Con documenti completi il passo 6 termina senza richiedere input da terminale; un errore non apre un questionario. |
|
||||
| Verifiche sostanziali | Il rapporto distingue prove eseguite da controlli non ancora possibili; non certifica verità di dominio o servizi non verificati. |
|
||||
| Modello configurato | Credenziali/endpoint verificati e selezione valida per gli usi richiesti. |
|
||||
| Credenziale errata | Diagnosi senza esporre il segreto, correzione nel file protetto e nuova verifica prima della ripresa. |
|
||||
| Interruzione e riavvio | La procedura ricontrolla gli input e riprende dall'avanzamento verificato senza nuove domande sui parametri. |
|
||||
| Contenuti esistenti | Descrizioni curate ed Evidence locali preservate; nessuna generazione o sovrascrittura silenziosa. |
|
||||
| Evidence assenti | Nessun blocco dovuto alla sola assenza quando non sono configurate. |
|
||||
| Workspace pronto | Connessione, schema e preparazione necessaria verificati; domanda reale completata con revisione umana. |
|
||||
| Riesecuzione | Nessuna duplicazione, azzeramento di dati o perdita delle personalizzazioni. |
|
||||
| Stop/start | Accesso e workspace utilizzabile persistono; i problemi esterni sono segnalati separatamente. |
|
||||
| Segreti | Assenti da log, riepiloghi, file pubblici e stato di avanzamento. |
|
||||
|
||||
Il dettaglio dei controlli e i test automatici devono rispettare le API e i contratti
|
||||
attuali; i test di portabilità e il collaudo con servizi reali restano distinti.
|
||||
La prima tappa usa Windows x64/WSL2, la seconda Linux Omarchy x64, la terza macOS
|
||||
Apple Silicon, coerentemente con le architetture già previste dal progetto.
|
||||
Gli esiti di una tappa non valgono come collaudo delle successive.
|
||||
|
||||
## Sottoprogetto degli esempi
|
||||
|
||||
L'implementazione rimane rinviata, come confermato con R1. I requisiti sono conservati sul branch
|
||||
`codex/benchmark-examples`, commit `08a5db55`. Il setup non offre come disponibili
|
||||
CLI, database o modalità di copia del repository non ancora implementati.
|
||||
|
||||
Il percorso richiesto ora parte dal repository predefinito oppure da quello ad hoc.
|
||||
Il primo collaudo utilizza un repository ad hoc; il percorso predefinito completo
|
||||
arriverà con il sottoprogetto esempi. Quando disponibili e selezionati nei documenti,
|
||||
creazione e caricamento dei database avvengono nell'installazione
|
||||
dell'utente a partire dai pacchetti dati verificati, senza compilare l'applicazione
|
||||
o incorporare quei database nelle immagini. Il percorso ad hoc può essere collaudato
|
||||
con workspace/database disponibili. La disponibilità di immagini Docker Hub è
|
||||
invece un prerequisito esplicito di ogni collaudo del percorso precompilato.
|
||||
|
||||
## Confini della specifica successiva
|
||||
|
||||
La verifica del codice ha individuato questi punti di integrazione concreti:
|
||||
|
||||
- `compose.yaml` costruisce oggi `core` e `frontend`; i servizi di manutenzione
|
||||
usano l'immagine core locale. `setup --complete` esegue una build
|
||||
(`tools/tht/internal/setup/run.go:77`) e `scripts/install-tht.sh:84` compila la CLI
|
||||
tramite Docker se non riceve un artefatto già costruito. Il percorso ordinario
|
||||
deve sostituire entrambi i comportamenti con artefatti del rilascio. La CI
|
||||
`.github/workflows/container-multiarch.yml` verifica già entrambe le architetture
|
||||
Linux; occorre aggiungere la pubblicazione Docker Hub e la verifica dei pacchetti
|
||||
effettivamente distribuiti.
|
||||
- I parser workspace (`backend/src/workspaces/catalog.ts:52`, `schema.ts:382`)
|
||||
verificano i documenti senza dipendenze dal runtime, ma non sono oggi un comando
|
||||
preinstallazione nativo. Devono essere resi disponibili negli strumenti
|
||||
precompilati preservando gli stessi contratti, senza richiedere Node sul PC.
|
||||
- La configurazione database è applicata al descriptor runtime dal Catalog
|
||||
(`backend/src/catalog/runtime-binding.ts:33`). Serve un input locale preparatorio
|
||||
e un percorso di applicazione al Catalog, senza cambiare il significato del
|
||||
workspace v4 o creare due autorità persistenti per i binding.
|
||||
- `config.Load` contiene verifiche riutilizzabili su YAML e file ambiente
|
||||
(`tools/tht/internal/config/installation.go:100`); il `doctor` corrente combina
|
||||
controlli documentali e runtime (`tools/tht/internal/doctor/report.go:97`).
|
||||
La specifica deve separarli per rendere disponibili i gate dei passi 2, 3 e 5.
|
||||
- L'ammissione della sessione controlla modello, preprocessing e servizi necessari
|
||||
(`backend/src/routes/sessions.ts:438`); il preprocessing richiede un database
|
||||
associato e una sincronizzazione corrente. Le descrizioni generate dall'AI
|
||||
non costituiscono un requisito generale: possono essere già disponibili
|
||||
descrizioni curate o commenti della sorgente. Riferimento:
|
||||
[contratto di preprocessing](../contracts/workspace-preprocessing-cli.md).
|
||||
|
||||
La specifica tecnica dovrà definire build/pubblicazione Docker Hub, pacchetto di
|
||||
rilascio e bootstrap precompilato, selezione esplicita del percorso sorgente,
|
||||
template e documenti locali, validatori senza runtime, applicazione dei parametri
|
||||
al Catalog, esecuzione senza questionari, stato/ripresa e verifiche dei due traguardi.
|
||||
Nomi dei comandi di preparazione/verifica/pubblicazione e formato dello stato sono
|
||||
dettagli da progettare, non funzionalità esistenti attestate da questo PRD.
|
||||
|
||||
## Chiarimenti approvati del 28 settembre
|
||||
|
||||
| ID | Scelta | Decisione approvata |
|
||||
| --- | --- | --- |
|
||||
| R1 | Disponibilità dei tre esempi al primo rilascio | Conservare il rinvio del sottoprogetto e collaudare prima il percorso con repository ad hoc; introdurre il percorso predefinito completo quando gli esempi sono disponibili. |
|
||||
| R2 | Controlli impossibili prima della creazione dello stack | Bloccare gli errori rilevabili prima; elencare i controlli runtime non ancora eseguibili e renderli obbligatori al passo 6, senza contarli come superati preventivamente. |
|
||||
|
||||
Approvazione: «ok per le tue proposte. dopodichè procedi con to-spec».
|
||||
Il principio dei sei passi resta invariato.
|
||||
|
||||
Non rientrano in questo lavoro un nuovo installer grafico, la riscrittura delle
|
||||
superfici amministrative, il supporto multi-repository, la distribuzione dei
|
||||
database di esempio o modifiche al deployment server/Omics.
|
||||
@@ -0,0 +1,155 @@
|
||||
# Ripresa dell'installazione guidata
|
||||
|
||||
Stato al 28 settembre: revisione documentale in sei passi richiesta dall'utente;
|
||||
raccolta interattiva dei parametri durante il setup superata. R1/R2 confermate,
|
||||
`grill-with-docs` e `/to-spec` conclusi, piano di test confermato dall'utente.
|
||||
Il riferimento consolidato è il
|
||||
[PRD dell'installazione guidata](2026-09-27-guided-installation-prd.md).
|
||||
La [specifica derivata](2026-09-28-document-first-installation-spec.md) è pubblicata
|
||||
su Gitea come
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42),
|
||||
con etichetta `ready-for-agent`. `/to-tickets` è completato: la
|
||||
[scomposizione approvata](2026-09-28-installation-ticket-breakdown.md) collega le
|
||||
issue #43–#54, con dipendenze native verificate e parent invariata.
|
||||
Prossimo passo: `/implement` su #43 o #46, inizialmente senza blocchi.
|
||||
Nessun codice applicativo è stato implementato in questi passaggi.
|
||||
|
||||
## Base di lavoro
|
||||
|
||||
Branch `codex/guided-standalone-install`, commit iniziale `67ee5262`.
|
||||
Il branch conserva il setup guidato e i controlli workspace incompleti, separati dal
|
||||
rilascio server. Il piano del 14 settembre descrive il precedente percorso manuale;
|
||||
le decisioni qui registrate aggiornano l'obiettivo del lavoro ripreso.
|
||||
|
||||
## Decisioni confermate il 27 settembre 2026
|
||||
|
||||
- Destinatario: una persona capace di installare Docker, clonare un repository e
|
||||
compilare i valori richiesti, senza conoscere l'architettura di ThothII.
|
||||
- Risultato: almeno un workspace utilizzabile per una domanda reale, attraverso due
|
||||
traguardi espliciti: piattaforma installata e workspace pronto. La procedura guida
|
||||
le decisioni umane necessarie e può essere ripresa senza ricominciare.
|
||||
- Collaudo in tre tappe distinte e ordinate: prima Windows, poi Linux Omarchy su PC
|
||||
Intel, infine macOS. Non attribuire a una piattaforma gli esiti ottenuti su un'altra.
|
||||
- Distribuzione ordinaria tramite immagini applicative precompilate pubblicate su
|
||||
Docker Hub; build e pubblicazione fanno parte del progetto. L'installazione locale
|
||||
configura e inizializza lo stack senza compilare; l'alternativa da sorgente resta
|
||||
esplicitamente disponibile. Anche il comando host deve essere fornito precompilato
|
||||
nel percorso ordinario. La creazione/caricamento degli esempi resta un'integrazione
|
||||
prevista, con l'implementazione del relativo sottoprogetto ancora rinviata.
|
||||
|
||||
## Vincoli già documentati
|
||||
|
||||
Il precedente piano prevedeva clone Gitea e build locale; la decisione successiva
|
||||
li mantiene come alternativa al percorso precompilato Docker Hub. Restano Docker
|
||||
Compose e, su Windows, Ubuntu WSL2 con integrazione Docker Desktop.
|
||||
Il workspace descriptor contiene identità ed
|
||||
Evidence; configurazione database e metadati appartengono al Metadata Catalog.
|
||||
L'Installation Model Catalog appartiene all'installazione.
|
||||
|
||||
## Revisione del 28 settembre — prevale sul percorso interattivo
|
||||
|
||||
La preparazione e le verifiche precedono l'esecuzione, nell'ordine richiesto:
|
||||
|
||||
1. Preparare il repository workspace predefinito con i tre esempi oppure uno ad hoc.
|
||||
2. Verificare formalmente e, per quanto possibile, sostanzialmente i documenti workspace.
|
||||
3. Verificare le precondizioni dell'host e dei componenti previsti.
|
||||
4. Predisporre i documenti locali YAML/.env con i parametri dell'applicazione.
|
||||
5. Verificarne completezza, correttezza e coerenza con i workspace.
|
||||
6. Eseguire il setup dai documenti verificati, scaricando le immagini Docker Hub
|
||||
e creando lo stack, senza domande sui parametri.
|
||||
|
||||
Template ed esempi commentati e guide IT/EN accompagnano ogni fase. Le verifiche
|
||||
devono essere ripetibili prima di creare i container. Pi è incluso in `core`, non
|
||||
deve essere installato sull'host; i suoi controlli runtime avvengono dopo l'avvio.
|
||||
I binding database restano di competenza del Catalog, con un input locale
|
||||
preparatorio distinto dai descriptor workspace v4.
|
||||
|
||||
L'utente conferma che le immagini Docker Hub oggi non esistono: occorre un comando
|
||||
di produzione/pubblicazione per il manutentore, poi verificare il pull degli
|
||||
artefatti pubblicati prima di collaudare l'installazione precompilata sui PC.
|
||||
La preparazione del rilascio non è un compito dell'utente installatore.
|
||||
|
||||
R1/R2 confermate: esempi ancora rinviati e primo collaudo con repository ad hoc;
|
||||
controlli runtime elencati prima ed eseguiti obbligatoriamente dopo la creazione
|
||||
dello stack. Nessun controllo non eseguito conta come superato.
|
||||
|
||||
## Aspetti da tradurre nella specifica tecnica
|
||||
|
||||
- Quali template e documenti locali preparare, verificare e applicare, senza
|
||||
raccogliere parametri durante l'esecuzione.
|
||||
- Come distinguere validazione documentale, controlli preventivi esterni e controlli
|
||||
runtime, mantenendo i contratti delle superfici amministrative esistenti.
|
||||
- Criteri dettagliati di verifica, ripresa dopo errori e accettazione per ogni tappa.
|
||||
|
||||
## Sottoprogetto esempi: requisiti definiti, implementazione rinviata
|
||||
|
||||
Su richiesta dell'utente l'implementazione dei database di esempio viene rinviata;
|
||||
la definizione dei requisiti dell'installazione prosegue indipendentemente.
|
||||
Branch dedicato: `codex/benchmark-examples`, creato da `67ee5262`, con documentazione
|
||||
consolidata nel commit `08a5db55`. Il PRD approvato è
|
||||
`docs/plans/2026-09-27-example-databases-prd.md` su quel branch.
|
||||
|
||||
Il PRD conserva D1–D8: Financial, European Football e F1, tre workspace separati,
|
||||
dati PostgreSQL e schema commentato, Evidence curate e domande di accompagnamento
|
||||
senza SQL target, contenuti italiano/inglese. CLI scaricabile dal repository pubblico
|
||||
degli esempi Gitea gestito da TYL Consulting, collegato dal repository pubblico
|
||||
ThothII. Selezione di uno, due o tre esempi dopo il setup, oppure come ultimo passo
|
||||
facoltativo dello stesso setup; pacchetti PostgreSQL già verificati ove redistribuibili.
|
||||
|
||||
La copia del repository potrà essere indipendente, senza storia e collegamenti Git
|
||||
all'originale, oppure scaricata con accesso al repository pubblico in sola lettura.
|
||||
Workspace ed Evidence locali restano modificabili. Preparazione e verifiche sono
|
||||
responsabilità del progetto; all'utente vengono sottoposte solo ambiguità non
|
||||
risolvibili dalle fonti. Chi installa dovrà trovare gli esempi pronti all'uso.
|
||||
|
||||
Il caricatore, il supporto alla cartella `examples/` e alla copia autonoma sono da
|
||||
implementare. Finché il sottoprogetto è rinviato, il setup non deve offrirli come
|
||||
funzionalità disponibili. Il requisito di un workspace utilizzabile resta valido:
|
||||
per il collaudo si dovrà usare un workspace/database realmente disponibile.
|
||||
|
||||
## Verifiche da completare
|
||||
|
||||
Riesecuzione e fallimenti intermedi del setup; requisiti HTTPS per il repository
|
||||
workspace; test dedicati dei nuovi comandi; distinzione fra stato della piattaforma
|
||||
e Workspace Readiness; collaudo reale completo secondo l'ordine concordato.
|
||||
|
||||
## Riscontro sul setup corrente
|
||||
|
||||
- CLI guidata e pagine amministrative esistenti sono già il percorso previsto dal
|
||||
piano del 14 settembre; non è richiesto un nuovo installer grafico.
|
||||
- `setup --complete` prepara autenticazione e modelli, build, migrazioni Catalog,
|
||||
avvio, workspace pull, test Pi e doctor. Non configura binding DB, sincronizzazione
|
||||
dei metadati e preprocessing (`tools/tht/internal/setup/run.go:60`). Il messaggio
|
||||
finale corrente «ThothII is ready» deve essere allineato al traguardo verificato.
|
||||
- I modelli sono oggi preimpostati, senza selettore del provider nel Request
|
||||
(`tools/tht/internal/setup/files.go:449`).
|
||||
- La riesecuzione rifiuta file di configurazione esistenti con contenuto diverso;
|
||||
non equivale ancora a una ripresa guidata delle tappe tecniche e umane
|
||||
(`tools/tht/internal/setup/files.go:107`). La specifica deve prevedere stato delle
|
||||
tappe e gestione delle correzioni, senza sovrascrivere personalizzazioni.
|
||||
|
||||
## Round installazione I1–I3 del 27 settembre — storico superato dove indicato
|
||||
|
||||
La revisione del 28 settembre sopra prevale su I1/I2: nessun rinvio di parametri
|
||||
obbligatori al setup e nessuna raccolta tramite questionario. Il testo seguente
|
||||
conserva il contesto della decisione precedente e non è il comportamento richiesto
|
||||
per la nuova procedura. I3 resta valido per riuso dei contenuti e curation esplicita.
|
||||
|
||||
L'utente conferma «tutto come da te suggerito», dopo il chiarimento sulla CLI locale
|
||||
interattiva: domande condizionate alle risposte, configurazioni precompilate,
|
||||
credenziali protette, verifica delle connessioni, possibilità di rinviare una
|
||||
configurazione e ripresa senza ricominciare. La CLI guida alle pagine amministrative
|
||||
esistenti per il workspace e ne verifica il completamento.
|
||||
|
||||
| ID | Decisione | Scelta approvata |
|
||||
| --- | --- | --- |
|
||||
| I1 | Primo avvio senza repository/workspace disponibile | Consentire di completare il solo traguardo «piattaforma installata» e riprendere in seguito la configurazione del workspace. Il percorso complessivo resta incompleto fino al primo workspace utilizzabile e alla domanda reale. Nessuna dipendenza dalla futura disponibilità degli esempi. |
|
||||
| I2 | Scelta dei modelli durante il setup | Selezione guidata di provider e modello tra configurazioni supportate/precompilate, chiedendo le credenziali necessarie; percorso avanzato per configurazioni personalizzate. Embedding locale preconfigurato come scelta iniziale. |
|
||||
| I3 | Preparazione di descrizioni ed Evidence | Riutilizzare i contenuti già curati. Proporre la generazione AI delle descrizioni mancanti come scelta esplicita, con revisione umana, invece di avviarla automaticamente. Guidare alle pagine amministrative necessarie e registrare il punto di ripresa. |
|
||||
|
||||
Le Evidence sono opzionali nel contratto del workspace: non introdurre un obbligo
|
||||
generale di crearle per completare l'installazione. La specifica deve rispettare
|
||||
i controlli di Workspace Readiness su connessione, schema e indicizzazione,
|
||||
distinguendo assenza lecita di Evidence da configurazione incompleta o incoerente.
|
||||
Per le decisioni correnti e i criteri di accettazione fa fede il PRD revisionato
|
||||
al 28 settembre, senza attestare che siano già implementati.
|
||||
@@ -0,0 +1,387 @@
|
||||
# Spec: installation from validated documents and Docker Hub releases
|
||||
|
||||
## Problem Statement
|
||||
|
||||
An operator who understands Docker and can edit a documented configuration should
|
||||
not have to discover ThothII's architecture while answering an installation wizard.
|
||||
The operator needs time to prepare workspace and application documents, validate
|
||||
them repeatedly, and correct errors before applying changes to the machine.
|
||||
|
||||
The current setup combines document generation, local builds, startup and runtime
|
||||
diagnostics. Its success message can precede an actually usable workspace. It does
|
||||
not provide the complete preinstallation validation and resumable, non-interactive
|
||||
execution required by this workflow.
|
||||
|
||||
The ordinary installation must consume published, prebuilt application images.
|
||||
As reported by the project owner on 28 September 2026, ThothII images are not yet
|
||||
available on Docker Hub. Publishing and verifying a real release is therefore a
|
||||
prerequisite for testing the consumer installation, rather than a later enhancement.
|
||||
|
||||
## Solution
|
||||
|
||||
Deliver a documented six-step workflow, in this exact order:
|
||||
|
||||
1. Prepare a workspace repository: a project-specific repository initially, or the
|
||||
default examples repository when that separately deferred project is available.
|
||||
2. Validate workspace documents formally and substantively to the extent possible
|
||||
from their contents and available references.
|
||||
3. Verify host and distribution prerequisites.
|
||||
4. Prepare application parameters in installation-local YAML and protected
|
||||
environment/secret documents, using commented templates and complete examples.
|
||||
5. Validate application parameters and their consistency with the selected workspaces.
|
||||
6. Execute the validated installation without asking configuration questions: pull
|
||||
the release images, create and initialize the stack, apply declared configuration,
|
||||
and run the required runtime checks.
|
||||
|
||||
Before these consumer steps can be tested against Docker Hub, a maintainer command
|
||||
must build, check and publish the release and verify that its artifacts can be pulled.
|
||||
Local source builds remain an explicit alternative, with the same configuration and
|
||||
persistence contracts. A failed pull never silently switches to source compilation.
|
||||
|
||||
Checks that cannot run before container or database creation are enumerated as
|
||||
deferred obligations and must run after startup. Errors detectable beforehand block
|
||||
execution. Platform acceptance, Workspace Readiness and functional acceptance are
|
||||
reported separately. A real question with human review completes functional acceptance.
|
||||
|
||||
## User Stories
|
||||
|
||||
1. As an installer, I want a six-step guide, so that I can understand the whole process before changing my machine.
|
||||
2. As an installer, I want commented templates and completed examples, so that I can prepare documents without knowing internal component names.
|
||||
3. As an installer, I want to pause document preparation, so that I can obtain missing information without restarting an installer.
|
||||
4. As an installer, I want to prepare a project-specific workspace repository, so that I can use my own database before the example databases are delivered.
|
||||
5. As an installer, I want the future default repository to be clearly distinguished from available features, so that I am not directed to unavailable examples.
|
||||
6. As an installer, I want read-only access to the source workspace repository, so that consuming a workspace does not require publication rights.
|
||||
7. As a workspace author, I want local document validation before Docker starts, so that syntax and contract errors are inexpensive to correct.
|
||||
8. As a workspace author, I want duplicate identifiers, unsupported fields and inconsistent references reported, so that formally valid YAML does not hide an invalid workspace.
|
||||
9. As a workspace author, I want errors to identify the document and field, so that I know precisely what to edit.
|
||||
10. As a workspace author, I want optional Evidence distinguished from invalid configured Evidence, so that an intentionally absent corpus does not block installation.
|
||||
11. As a workspace author, I want semantic validation limits stated honestly, so that successful validation is not mistaken for certification of domain knowledge.
|
||||
12. As an installer, I want host prerequisites checked explicitly, so that Docker, architecture, permissions and resource problems are detected before setup.
|
||||
13. As a Windows installer, I want a verified WSL2 and Docker Desktop path, so that I can follow one supported installation procedure.
|
||||
14. As an installer, I want Pi supplied with the application image, so that I do not have to install an unnecessary host dependency.
|
||||
15. As an installer, I want application models, endpoints and credentials prepared before execution, so that I can consult colleagues or provider documentation at my own pace.
|
||||
16. As an installer, I want one authored model catalog, so that provider and embedding configuration do not disagree across components.
|
||||
17. As an installer, I want database bindings prepared locally and separately from workspace definitions, so that environment-specific details do not leak into shared workspace repositories.
|
||||
18. As an installer, I want generated internal credentials prepared in protected files, so that I need not invent technical passwords during execution.
|
||||
19. As an installer, I want my secrets excluded from logs and validation reports, so that diagnostic output is safe to inspect and share.
|
||||
20. As an installer, I want repeatable application validation, so that I can correct configuration without creating containers or changing databases.
|
||||
21. As an installer, I want available external connections checked before startup, so that preventable endpoint or authentication errors are found early.
|
||||
22. As an installer, I want non-executable checks listed explicitly, so that I know what still needs to be proved after startup.
|
||||
23. As an installer, I want validation tied to the documents and release I selected, so that execution cannot silently apply different inputs.
|
||||
24. As an installer, I want setup to run with closed standard input, so that it cannot unexpectedly ask me for a parameter.
|
||||
25. As an installer, I want missing values to stop setup with a useful diagnosis, so that I can correct the document and validate again.
|
||||
26. As an installer, I want prebuilt images downloaded from Docker Hub, so that I need no application source checkout or compiler.
|
||||
27. As an installer, I want the operator tool supplied precompiled, so that its bootstrap does not hide a local build.
|
||||
28. As an installer, I want release components to be compatible and identifiable, so that my installation is reproducible.
|
||||
29. As an installer, I want registry failures reported without automatic compilation, so that the selected installation mode remains predictable.
|
||||
30. As an installer, I want configuration, credentials and data kept outside application images, so that my installation remains local and persistent.
|
||||
31. As an installer, I want migrations and database binding initialization handled explicitly, so that a running container is not mistaken for an initialized application.
|
||||
32. As an installer, I want existing curated descriptions and Evidence preserved, so that rerunning setup cannot overwrite human work.
|
||||
33. As an installer, I want runtime checks performed from the actual container environment, so that host connectivity is not confused with application connectivity.
|
||||
34. As an installer, I want completed and failed execution stages recorded, so that I can resume after interruption without duplicating data.
|
||||
35. As an installer, I want configuration corrections to invalidate dependent checks, so that resuming does not trust stale results.
|
||||
36. As an administrator, I want Catalog changes to retain their existing confirmation and concurrency rules, so that installation automation does not bypass domain safeguards.
|
||||
37. As an installer, I want separate platform and workspace status, so that I know whether I can already ask a real question.
|
||||
38. As an installer, I want stop/start behavior checked, so that a successful first run is not the only working state.
|
||||
39. As a maintainer, I want an explicit release build-and-publish command, so that consumer installation can use actual Docker Hub artifacts.
|
||||
40. As a maintainer, I want versioned images and release metadata, so that published artifacts can be traced to a source revision.
|
||||
41. As a maintainer, I want publication credentials isolated from consumer configuration, so that installers need no write access to Docker Hub.
|
||||
42. As a maintainer, I want the published artifacts tested by pulling them, so that an unpublished local image cannot satisfy release acceptance.
|
||||
43. As a source-build user, I want an explicit supported build path, so that source customization remains possible.
|
||||
44. As a maintainer, I want Windows, Omarchy and macOS acceptance recorded separately and in order, so that support claims reflect tests actually performed.
|
||||
45. As an Italian or English reader, I want matching step-by-step guides, so that language choice does not change the installation contract.
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
### Boundaries and authority
|
||||
|
||||
- Keep the existing standalone architecture and operator CLI. The application runs
|
||||
through Compose; the operator CLI owns preparation, validation and execution of
|
||||
the installation, rather than introducing another installer or backend workflow.
|
||||
- Preserve Workspace schema v4 and the workspace catalog as the authority for
|
||||
workspace identity and optional Evidence. Formal validation uses the same rules
|
||||
as runtime loading, including strict YAML interpretation, duplicate detection,
|
||||
directory/index consistency and prohibited fields.
|
||||
- Preserve the Installation Model Catalog as the sole authored source for provider,
|
||||
model eligibility, defaults and embedding facts. Session and embedding configuration
|
||||
must be complete before ordinary execution. Metadata generation remains optional
|
||||
when its catalog configuration is omitted consistently.
|
||||
- Preserve the PostgreSQL Metadata Catalog as the authority for Workspace Database
|
||||
identity, schema, metadata and active Database Binding. Respect the existing
|
||||
one-database-per-workspace boundary. Prepared binding documents are bootstrap
|
||||
inputs, not a second runtime database catalog.
|
||||
- Preserve installation-local secret storage, reference-based binding credentials,
|
||||
editable Evidence authority, read-only DWH access and the separation of reference
|
||||
preprocessing from Memory. Do not rewrite model projections or runtime snapshots
|
||||
as independent authored configuration.
|
||||
|
||||
### Preparation documents and command surfaces
|
||||
|
||||
- Expose distinct operator operations for template preparation, workspace validation,
|
||||
host checks, application validation, execution, status and resumption. Their exact
|
||||
CLI spelling can be finalized with the implementation tickets; they must remain
|
||||
separately invocable and scriptable. Setup execution is never a parameter wizard.
|
||||
- Template preparation creates explicitly requested sample documents or protected
|
||||
credential files without starting application services. It never silently replaces
|
||||
existing user documents. Placeholders are visibly incomplete and cannot pass the
|
||||
required-field checks.
|
||||
- Supply a versioned, installation-local database bootstrap document describing the
|
||||
workspace identity, engine, physical database/schema, transport and endpoint
|
||||
configuration, and references to secrets. Validate against existing Catalog
|
||||
capabilities and selected workspace identities. No credentials belong in the
|
||||
shared workspace descriptors or public repository.
|
||||
- Binding imports use authenticated, authorized Catalog services and their version
|
||||
checks. On first execution they create the declared bindings and install secrets
|
||||
through the existing store. On rerun, equivalent values are a no-op; conflicting
|
||||
existing administrative changes stop with a reconciliation report. The bootstrap
|
||||
input does not continuously overwrite a mutable Catalog.
|
||||
- Initial local administrative authentication and its protected bootstrap material
|
||||
are prepared before execution. Execution cannot depend on a person answering a
|
||||
login wizard. Reuse supported operator authentication boundaries and required
|
||||
permissions, without introducing a privileged unauthenticated installation API.
|
||||
- Supply a precompiled validation capability with the operator distribution. The
|
||||
workspace validation step must work without Docker, ThothII, Node or an application
|
||||
source checkout. Reuse canonical validation rules; if a new packaging boundary is
|
||||
necessary, prove equivalence with a shared set of valid and invalid documents.
|
||||
|
||||
### Validation contract
|
||||
|
||||
- Workspace validation covers syntax, strict schema, identity, catalog/descriptor
|
||||
relationships and locally available Evidence references. It does not claim to
|
||||
establish the truth of domain rules, database contents or services that do not exist.
|
||||
- Host checks distinguish host prerequisites from bundled application dependencies.
|
||||
Pi is checked as a release component and subsequently in the running core image,
|
||||
never required as a separate host installation.
|
||||
- Application validation checks required configuration, compatible release and host,
|
||||
model usages/defaults, protected secret references, database transport capabilities,
|
||||
workspace links, effective Compose configuration and accessible remote dependencies.
|
||||
A transport that cannot serve NL-to-SQL sessions cannot pass workspace-readiness
|
||||
validation merely because it can perform administrative diagnostics.
|
||||
- Reports expose a stable outcome, check identifier, affected logical input/field,
|
||||
explanation and next action. The public outcomes are passed, error, warning and
|
||||
deferred-to-runtime. Human-readable output is accompanied by pristine structured
|
||||
output for automation; exit status distinguishes success from blocking failure.
|
||||
- Validation is read-only with respect to user documents, application state and
|
||||
target databases. Explicit report output is allowed. Remote checks are bounded,
|
||||
documented and non-mutating; any provider usage incurred by a configured smoke
|
||||
test is disclosed before invocation, not requested interactively during setup.
|
||||
- Missing or invalid required configuration, missing release artifacts, unsupported
|
||||
architecture and failures of available required dependencies block execution.
|
||||
Unreachable existing external services are errors, not automatically reclassified
|
||||
as deferred. Only checks intrinsically dependent on the not-yet-created local
|
||||
stack qualify for the accepted deferred category.
|
||||
- Maintain an explicit obligation list for deferred checks: container-network
|
||||
connectivity, Catalog initialization, Pi operation, local embedding availability,
|
||||
preprocessing and relevant workspace runtime readiness. Each obligation has a
|
||||
defined runtime check; there is no successful final state while a required
|
||||
obligation remains unverified or failed.
|
||||
- Bind the execution plan to normalized non-secret configuration, repository revision
|
||||
and verified content, selected release digests and validator version. Re-read
|
||||
protected credentials when checking or executing; do not expose their values or
|
||||
unkeyed secret-derived fingerprints in reports. Re-run credential checks where
|
||||
freshness cannot be established safely.
|
||||
- Revalidate changed dependencies and live prerequisites at execution or resume.
|
||||
A previously successful report is not blanket authorization to apply changed files
|
||||
or evidence of current network availability.
|
||||
|
||||
### Release production and distribution
|
||||
|
||||
- Provide a maintainer command accepting source revision, release version, Docker Hub
|
||||
namespace and target architectures. It performs preflight checks, reproducible
|
||||
builds, artifact checks, publication and output of a coherent release manifest.
|
||||
This command is a deliverable of this feature, not an undocumented manual prerequisite.
|
||||
- Publish the existing core and frontend application images. Catalog migration and
|
||||
workspace maintenance use the same released core image. Keep PostgreSQL, Qdrant
|
||||
and Ollama as compatible upstream images; preserve the existing service boundaries.
|
||||
- Package the operator executable, validation capability, Compose definitions,
|
||||
initialization resources and migration support required by the release. No runtime
|
||||
mount may require a resource that exists only in an application source checkout.
|
||||
- Pin the release identity and resolved image digests. A published release manifest
|
||||
binds compatible images and operator/configuration versions. Do not overwrite an
|
||||
already published immutable release version or declare a partially published
|
||||
image set installable. An interrupted publication can retry without advertising
|
||||
an incomplete consumer release.
|
||||
- Keep publishing credentials outside consumer bundles and logs. Public consumers
|
||||
pull without publishing rights. Application images contain application software,
|
||||
not installation secrets, user workspace data or prepopulated example databases.
|
||||
- The ordinary bootstrap downloads a precompiled operator and release artifacts.
|
||||
It must not compile the CLI through Docker as a hidden fallback. Windows WSL2
|
||||
uses the Linux executable; macOS uses an appropriate host executable.
|
||||
- Deliver and accept Linux amd64 images for Windows/WSL2 and Omarchy first. Add and
|
||||
accept Linux arm64 for the macOS Apple Silicon stage. Multiarchitecture build
|
||||
results do not by themselves prove host installation acceptance.
|
||||
- A maintainer smoke test pulls the published artifacts by their release references.
|
||||
Consumer acceptance runs must not succeed because of an unpushed locally built
|
||||
image. Confirm core, frontend and maintenance references all resolve to the release.
|
||||
- Retain explicit source mode with the same configuration, validation and persistence
|
||||
rules. It is not the default and is never an automatic recovery action for a pull
|
||||
failure. Registry recovery is a retry of the selected released artifacts.
|
||||
|
||||
### Non-interactive execution and recovery
|
||||
|
||||
- Execute only a complete, currently validated plan with no blocking errors. The
|
||||
ordinary sequence pulls the release, prepares runtime projections and isolated
|
||||
installation storage, starts required services, applies migrations, registers the
|
||||
workspace source and imports the prepared Catalog bindings before dependent work.
|
||||
- Apply configuration and migrations through existing service boundaries. Hold an
|
||||
installation execution lock to prevent concurrent runs from racing over the same
|
||||
state, containers or bootstrap imports.
|
||||
- Reuse durable Catalog Sync Runs and their freshness/locking rules. Fresh additive
|
||||
synchronization can proceed under the existing contract. A destructive diff or
|
||||
another domain-required human decision stops at an explicit awaiting-review state;
|
||||
the operator reviews through the existing administration surface and subsequently
|
||||
resumes. This is a domain decision, not permission to collect missing setup parameters
|
||||
or add an automatic confirmation bypass.
|
||||
- Reuse existing curated metadata and Evidence. Do not generate AI descriptions or
|
||||
new domain rules as an installation side effect. Optional generation remains a
|
||||
separate explicit administrative action. Required preprocessing can use supported
|
||||
source comments or curated descriptions without mandatory AI generation.
|
||||
- Persist a bounded execution journal with installation identity, plan identity,
|
||||
stage outcomes, released component versions, deferred-check outcomes and recovery
|
||||
guidance. Do not persist secret values or raw exception output. Write progress
|
||||
atomically and check actual state on resume.
|
||||
- A repeated execution of the same completed plan must not recreate bindings,
|
||||
duplicate data, clear Memory, overwrite Evidence or erase sessions. Reconcile
|
||||
already completed stages with their actual persistent state before proceeding.
|
||||
- After a document correction, revalidate and repeat only affected checks/stages.
|
||||
Do not infer that an interrupted migration or import failed before inspecting its
|
||||
durable result. Preprocessing, which has no internal resume contract, may need to
|
||||
rerun as a whole; report that honestly.
|
||||
- Never implement recovery by deleting all volumes or reverting user data. Report
|
||||
the failing stage and safe next action. Failed or interrupted execution is not
|
||||
advertised as a complete installation.
|
||||
- Report platform state, Workspace Readiness and functional acceptance separately.
|
||||
Runtime checks exercise the released Pi, embedding and actual container transport.
|
||||
Final acceptance includes a real human-reviewed question and stop/start persistence.
|
||||
The workflow's human review is not replaced by unattended benchmark evaluation.
|
||||
|
||||
### Documentation and delivery boundaries
|
||||
|
||||
- Keep Italian and English guides aligned with the six steps. Each step states its
|
||||
inputs, documents, examples, verification operation, expected output and common
|
||||
corrections. Provide an advance checklist of information and credentials to collect.
|
||||
- Separate maintainer publication instructions, consumer prebuilt installation and
|
||||
source-build instructions. State precisely which components are host prerequisites
|
||||
and which are shipped inside the release.
|
||||
- First acceptance uses an available project-specific repository and database.
|
||||
The Financial, European Football and F1 project stays deferred. Do not expose its
|
||||
unavailable loader, repository-copy support or data bundles as usable features.
|
||||
- Preserve the future integration boundary: examples will be selected in documents
|
||||
and loaded locally after application initialization, without rebuilding the
|
||||
application or embedding the datasets into its Docker images.
|
||||
|
||||
## Testing Decisions
|
||||
|
||||
### Confirmed test boundaries
|
||||
|
||||
Use the public operator workflow as the principal test boundary: prepared documents
|
||||
in, stable reports/exit statuses and observable installation outcomes out. Exercise
|
||||
validation and execution through this boundary while replacing external command
|
||||
execution and remote services with controllable test counterparts. Keep focused
|
||||
contract tests at existing workspace parsing and Catalog boundaries where they
|
||||
prevent divergent schemas or authority rules. Add real release and host acceptance
|
||||
tests for behavior that simulated external services cannot establish.
|
||||
|
||||
The project owner confirmed this testing boundary on 28 September 2026, completing
|
||||
the `/to-spec` checkpoint. The product decisions, six-step workflow and testing
|
||||
scope are approved for specification publication and subsequent ticket decomposition.
|
||||
|
||||
### Existing testing practice to extend
|
||||
|
||||
- Operator setup tests already use temporary installation fixtures and a replaceable
|
||||
command runner to cover sequencing, startup failures, error preservation and recovery
|
||||
messages. Extend that boundary to document validation, prebuilt execution and resumption.
|
||||
- Installation configuration tests cover strict schemas, model catalog rules and
|
||||
incompatible existing files. Extend them with complete/incomplete preparation
|
||||
documents, protected references and cross-document consistency.
|
||||
- Workspace tests cover strict catalog/descriptor parsing, immutable Git revisions,
|
||||
runtime handoff and secret handling. Reuse their document fixtures and validity
|
||||
rules to demonstrate equivalence of the preinstallation validator.
|
||||
- Catalog and preprocessing tests already cover durable runs, locks, binding freshness,
|
||||
failure recording and preservation of authoritative state. Reuse these boundaries
|
||||
to verify bootstrap import and resumption without bypassing the domain contracts.
|
||||
- Existing multiarchitecture image checks provide a starting point for released
|
||||
artifact verification. They do not replace pulling the published artifacts or
|
||||
testing supported host environments.
|
||||
|
||||
### Required behavioral coverage
|
||||
|
||||
1. Validate workspace documents with Docker absent and no application runtime;
|
||||
reject malformed YAML, duplicate keys/identifiers, unsupported fields, broken
|
||||
references and invalid configured Evidence with actionable locations.
|
||||
2. Repeated document/host/application checks do not create containers, change source
|
||||
documents, import data or migrate databases. Only explicitly requested reports
|
||||
may be written by validation.
|
||||
3. Complete application documents pass; placeholders, missing required models,
|
||||
invalid binding transport and unreadable secret references block execution.
|
||||
4. Existing external-service failures remain errors. Checks genuinely dependent on
|
||||
newly created local services are listed as deferred and cannot disappear from
|
||||
final acceptance.
|
||||
5. Execute with standard input closed. Valid inputs need no responses; missing
|
||||
values yield an error without waiting for input or prompting for a replacement.
|
||||
6. Changing documents, workspace revision or release after validation invalidates
|
||||
dependent results. Credential changes are caught without leaking secret material.
|
||||
7. A clean prebuilt consumer installation performs pulls and initialization, never
|
||||
application or operator compilation; absent images fail without a source fallback.
|
||||
8. Published manifests resolve all required images, platform variants and maintenance
|
||||
components coherently. Simulated publication interruption does not advertise a
|
||||
partial release; a real smoke test exercises artifacts pulled from Docker Hub.
|
||||
9. Prepared database bindings become Catalog state once, use the existing protected
|
||||
secret store and remain unchanged on equivalent reruns. Administrative divergence
|
||||
is reported rather than silently overwritten.
|
||||
10. Interruption after a durable operation but before journal completion resumes by
|
||||
inspecting state, without duplicating that operation. Concurrent setup runs cannot
|
||||
mutate the same installation simultaneously.
|
||||
11. Destructive Catalog synchronization requires its existing review and fresh source
|
||||
checks. The setup's non-interactive nature does not auto-approve a destructive diff.
|
||||
12. Existing descriptions, Evidence, sessions and Memory survive validation, rerun,
|
||||
configuration correction and stop/start. Optional AI generation is not triggered.
|
||||
13. Runtime Pi, embedding and connectivity checks are executed from the installed
|
||||
release, and platform success cannot mask failed Workspace Readiness.
|
||||
14. Source mode remains functional and explicit with equivalent configuration
|
||||
contracts. A source-mode pass cannot close prebuilt distribution acceptance.
|
||||
15. Execute real consumer acceptance first on Windows x64/WSL2, then Omarchy x64,
|
||||
then macOS Apple Silicon. Record each environment, release identity, stage
|
||||
outcomes, a real reviewed question and a stop/start check separately.
|
||||
|
||||
Good tests assert observable contracts, preserved data and required side effects,
|
||||
not private helper calls or incidental internal ordering. Use real isolated Catalog
|
||||
instances where transaction and lock behavior matters. Mock external provider
|
||||
failures for repeatable tests, while keeping actual DWH/model acceptance separate.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Implementing or publishing the three example databases, their curated contents,
|
||||
example CLI, auxiliary repository layout or autonomous repository-copy mode.
|
||||
- A new graphical installer, a conversational parameter wizard, or collecting
|
||||
required parameters in administration pages after an incomplete setup.
|
||||
- Installing Pi, Python, Node or an application build toolchain on ordinary consumer hosts.
|
||||
- Changes to server/Omics deployment, upstream authentication or the application's
|
||||
existing human-in-the-loop workflow.
|
||||
- Multiple workspace repositories per installation or multiple databases per workspace.
|
||||
- Automatic release upgrades, destructive reset/uninstall, whole-volume rollback
|
||||
or backup-policy redesign. Interrupted initial setup recovery remains in scope.
|
||||
- Automatic semantic certification, generated Evidence without sources, benchmark
|
||||
SQL targets or automated accuracy scoring.
|
||||
- Publishing Docker images or executing installations as part of this specification
|
||||
authoring task. These are implementation and release deliverables described above.
|
||||
|
||||
## Further Notes
|
||||
|
||||
The project owner approved the six-step revision and both final clarifications on
|
||||
28 September 2026: examples stay deferred, and runtime-only checks are explicit
|
||||
post-start obligations. Earlier interactive-wizard and incomplete-configuration
|
||||
installation proposals are superseded where they conflict with this specification.
|
||||
|
||||
This specification follows the existing decisions on PostgreSQL metadata authority,
|
||||
installation-local bindings, secret references, durable schema synchronization and
|
||||
the Installation Model Catalog. It does not change those architectural authorities.
|
||||
|
||||
Publication of a usable Docker Hub release is a blocking dependency of consumer
|
||||
prebuilt-installation acceptance. Availability of the deferred examples is not.
|
||||
Docker Hub namespace, publishing credentials and concrete release versions are
|
||||
maintainer release inputs, not values to invent or embed into user templates.
|
||||
|
||||
After publication to Gitea, `/to-tickets` will split this specification into small
|
||||
end-to-end increments with explicit blockers. Implementation has not started in
|
||||
this task, and publishing the specification does not attest that a release exists.
|
||||
@@ -0,0 +1,394 @@
|
||||
# Scomposizione della specifica di installazione
|
||||
|
||||
Data: 2026-09-28. Stato: scomposizione approvata dall'utente («approvo»);
|
||||
pubblicazione `/to-tickets` completata. Verificati testi, etichetta `ready-for-agent`
|
||||
e dipendenze native delle issue #43–#54; specifica parent invariata.
|
||||
Parent: [Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
Gli identificatori T01–T12 restano riferimenti della scomposizione; le issue reali
|
||||
sono elencate sotto. Ogni issue usa `ready-for-agent` e dipendenze native Gitea.
|
||||
La parent non viene modificata né chiusa.
|
||||
|
||||
## Issue pubblicate
|
||||
|
||||
Avanzamento locale, 2026-09-28: T01/#43 implementato sul branch
|
||||
`codex/guided-standalone-install`. Disponibili `tht workspace prepare` e
|
||||
`tht workspace validate`, con helper autonomo che riusa i parser runtime. Guide
|
||||
IT/EN aggiornate; esempi e pubblicazione degli artefatti restano differiti ai ticket
|
||||
previsti. Nessuna chiusura o modifica della parent effettuata.
|
||||
|
||||
Verifica: 14 test della CLI passano sia da sorgenti sia con il bundle nativo macOS
|
||||
arm64 e `PATH` vuoto; artefatti Windows amd64/Linux amd64 cross-compilati, senza
|
||||
attribuire loro un collaudo host. Backend su Node 24.16: 109 file passati, un file
|
||||
saltato, 1.417 test passati e 40 saltati; typecheck e build rigorosa documentazione
|
||||
passati. Suite Go: tutti i pacchetti passati, salvo un primo errore intermittente
|
||||
nel test di concorrenza authstorage; quel test passa in tre ripetizioni e il pacchetto
|
||||
completo passa nella verifica isolata. Le revisioni Standards e Spec non lasciano
|
||||
finding aperti. Il prossimo incremento sequenziale è T02/#44.
|
||||
|
||||
| Ticket | Issue Gitea | Dipendenze dirette |
|
||||
| --- | --- | --- |
|
||||
| T01 | [Preparare e validare un repository workspace senza stack](https://git.tylconsulting.it/mptyl/ThothII/issues/43) | Nessuna |
|
||||
| T02 | [Preparare e validare i documenti applicativi](https://git.tylconsulting.it/mptyl/ThothII/issues/44) | #43 |
|
||||
| T03 | [Verificare precondizioni e produrre il piano eseguibile](https://git.tylconsulting.it/mptyl/ThothII/issues/45) | #44 |
|
||||
| T04 | [Produrre e pubblicare un rilascio Docker Hub installabile](https://git.tylconsulting.it/mptyl/ThothII/issues/46) | Nessuna |
|
||||
| T05 | [Installare la piattaforma dal rilascio senza domande](https://git.tylconsulting.it/mptyl/ThothII/issues/47) | #45, #46 |
|
||||
| T06 | [Applicare i binding preparati al Catalog](https://git.tylconsulting.it/mptyl/ThothII/issues/48) | #47 |
|
||||
| T07 | [Portare il workspace alla readiness con controlli runtime](https://git.tylconsulting.it/mptyl/ThothII/issues/49) | #48 |
|
||||
| T08 | [Conservare il percorso esplicito da sorgente](https://git.tylconsulting.it/mptyl/ThothII/issues/50) | #47 |
|
||||
| T09 | [Riprendere dopo correzioni e interruzioni senza perdere stato](https://git.tylconsulting.it/mptyl/ThothII/issues/51) | #49, #50 |
|
||||
| T10 | [Collaudare l'installazione pubblicata su Windows/WSL2](https://git.tylconsulting.it/mptyl/ThothII/issues/52) | #51 |
|
||||
| T11 | [Collaudare l'installazione su Omarchy](https://git.tylconsulting.it/mptyl/ThothII/issues/53) | #52 |
|
||||
| T12 | [Pubblicare e collaudare il percorso macOS Apple Silicon](https://git.tylconsulting.it/mptyl/ThothII/issues/54) | #53 |
|
||||
|
||||
Ogni ticket comprende verifiche del comportamento e aggiornamenti pertinenti delle
|
||||
guide IT/EN. Le dipendenze elencate sono dirette; non si ripetono quelle transitive.
|
||||
Si riusano il runner dell'operatore e i servizi di dominio esistenti; gli adattamenti
|
||||
necessari sono inclusi nella prima funzionalità che li usa. Non emerge una necessità
|
||||
di refactoring trasversale da pubblicare come lavoro orizzontale separato.
|
||||
|
||||
| Ticket | Titolo | Bloccato da | Risultato dimostrabile |
|
||||
| --- | --- | --- | --- |
|
||||
| T01 | Preparare e validare un repository workspace senza stack | Nessuno | Template e controllo locale conformi ai contratti, senza Docker attivo. |
|
||||
| T02 | Preparare e validare i documenti applicativi | T01 | Parametri, modelli e binding completi verificati senza avviare servizi. |
|
||||
| T03 | Verificare precondizioni e produrre il piano eseguibile | T02 | Rapporto con errori bloccanti e obblighi runtime, legato agli input. |
|
||||
| T04 | Produrre e pubblicare un rilascio Docker Hub installabile | Nessuno | Comando manutentore e pacchetto pubblico verificato tramite pull. |
|
||||
| T05 | Installare la piattaforma dal rilascio senza domande | T03, T04 | Pull, inizializzazione e avvio da documenti, con stato e ripresa delle fasi. |
|
||||
| T06 | Applicare i binding preparati al Catalog | T05 | Database dei workspace configurati senza questionari o duplicazioni. |
|
||||
| T07 | Portare il workspace alla readiness con controlli runtime | T06 | Schema, preprocessing e servizi verificati senza aggirare la revisione umana. |
|
||||
| T08 | Conservare il percorso esplicito da sorgente | T05 | Stessi input e contratti, con build scelta esplicitamente. |
|
||||
| T09 | Riprendere dopo correzioni e interruzioni senza perdere stato | T07, T08 | Recupero dell'intero percorso, compresi binding, sync e preprocessing. |
|
||||
| T10 | Collaudare l'installazione pubblicata su Windows/WSL2 | T09 | Prima accettazione reale senza sorgenti o compilatori. |
|
||||
| T11 | Collaudare l'installazione su Omarchy | T10 | Seconda accettazione reale su Linux x64, distinta da Windows. |
|
||||
| T12 | Pubblicare e collaudare il percorso macOS Apple Silicon | T11 | Terza accettazione con immagini arm64 e comando host compatibile. |
|
||||
|
||||
## T01 — Preparare e validare un repository workspace senza stack
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Un autore prepara un repository ad hoc usando un template documentato e verifica
|
||||
i documenti localmente prima di installare ThothII. Il validatore è fornito come
|
||||
capacità eseguibile senza Node, Docker attivo o checkout dei sorgenti applicativi.
|
||||
Riusa i contratti del runtime, senza creare uno schema workspace alternativo.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Il template distingue catalogo workspace, descriptor ed Evidence opzionali e non contiene funzionalità degli esempi ancora indisponibili.
|
||||
- [ ] Preparare un template non avvia servizi, non sovrascrive documenti esistenti e non richiede accesso in scrittura al repository originale.
|
||||
- [ ] Il controllo respinge YAML ambiguo o invalido, chiavi duplicate, identificatori duplicati, campi estranei, incoerenze catalogo/directory e riferimenti locali mancanti.
|
||||
- [ ] Le Evidence configurate sono verificate per ciò che è controllabile localmente; assenza lecita e invalidità sono distinte, senza certificare il significato delle regole di dominio.
|
||||
- [ ] Gli esiti identificano documento/campo e correzione; output strutturato e codici di uscita sono verificabili senza esporre segreti.
|
||||
- [ ] Una raccolta condivisa di casi validi/invalidi prova equivalenza con i parser runtime, e il controllo passa senza Docker e senza runtime host aggiuntivi.
|
||||
- [ ] Guide IT/EN mostrano preparazione, correzione e ripetizione del passo 2.
|
||||
|
||||
### Blocked by
|
||||
|
||||
None (can start immediately).
|
||||
|
||||
## T02 — Preparare e validare i documenti applicativi
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
L'operatore compila template locali per installazione, modelli, binding database e
|
||||
segreti, e ne verifica completezza e coerenza con i workspace già verificati.
|
||||
Non viene avviata l'applicazione e nessun valore viene richiesto dal futuro setup.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Template commentati ed esempi completi spiegano obblighi, default e riferimenti ai documenti protetti; i placeholder non superano la validazione.
|
||||
- [ ] Modelli e embedding rispettano l'Installation Model Catalog; generazione metadati opzionale e default sono coerenti con i contratti esistenti.
|
||||
- [ ] Un input bootstrap locale versionato descrive Workspace Database e Database Binding con riferimenti ai segreti; i descriptor workspace restano conformi allo schema v4.
|
||||
- [ ] Validazione incrociata di workspace, binding, engine/trasporto, modelli, percorsi e file ambiente, senza migrare o interrogare in scrittura alcun database.
|
||||
- [ ] La generazione esplicita delle credenziali tecniche produce file protetti prima del setup, senza sovrascritture o segreti nei log/rapporti.
|
||||
- [ ] I test coprono input completi, mancanti, incompatibili e segreti illeggibili; i documenti dell'utente rimangono invariati durante le verifiche.
|
||||
- [ ] Guide IT/EN consentono di raccogliere e preparare tutte le informazioni con calma prima dell'esecuzione.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T01 — Preparare e validare un repository workspace senza stack.
|
||||
|
||||
## T03 — Verificare precondizioni e produrre il piano eseguibile
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
L'operatore verifica host e dipendenze esterne disponibili, quindi ottiene un piano
|
||||
eseguibile riferito ai documenti e al rilascio scelti. Il rapporto distingue errori,
|
||||
avvisi e controlli necessariamente rinviati al runtime, senza creare lo stack.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] I controlli host sono invocabili al passo 3; quelli dipendenti dai parametri finali sono completati o ripetuti al passo 5.
|
||||
- [ ] Sono verificati Docker/Compose, architettura, WSL2 quando pertinente, percorsi/permessi, risorse e disponibilità del rilascio e dei suoi componenti nel registry.
|
||||
- [ ] Le prove sulle dipendenze esterne disponibili sono circoscritte e documentate; un servizio esistente irraggiungibile non viene promosso a semplice controllo differito.
|
||||
- [ ] Pi non è richiesto sull'host; le dipendenze incluse nelle immagini sono riconosciute nel manifest e associate a controlli runtime precisi.
|
||||
- [ ] Il piano registra input non segreti, revisione/contenuti workspace, release e versione del validatore; nessun segreto o fingerprint pubblico non protetto di segreti.
|
||||
- [ ] Ogni controllo differito ha un'identità e un'obbligazione runtime; valori obbligatori mancanti o immagini assenti bloccano il piano.
|
||||
- [ ] Prove con manifest e servizi controllati coprono cambiamento degli input, credenziali, errori di rete e architetture; nessuna creazione di container o mutazione di dati.
|
||||
- [ ] Guide IT/EN spiegano rapporto, errori e verifiche ancora da eseguire. La prova con il rilascio reale verrà completata dal ticket di esecuzione, dopo T04.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T02 — Preparare e validare i documenti applicativi.
|
||||
|
||||
## T04 — Produrre e pubblicare un rilascio Docker Hub installabile
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Il manutentore esegue un comando riproducibile che costruisce, verifica e pubblica
|
||||
core/frontend su Docker Hub, insieme al pacchetto operatore compatibile, e dimostra
|
||||
che il rilascio pubblicato è scaricabile. La pubblicazione delle immagini oggi
|
||||
mancanti è un risultato concreto del ticket, non un prerequisito lasciato a mano.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Il comando riceve revisione, versione, namespace e architetture e mantiene fuori da bundle/log le credenziali di pubblicazione.
|
||||
- [ ] Pubblica core/frontend Linux amd64 per la prima tappa; Catalog migration e workspace maintenance risolvono alla stessa immagine core del rilascio.
|
||||
- [ ] Il bundle contiene comando host precompilato, Compose, inizializzazione e risorse di migrazione, senza dipendenze da checkout sorgente durante l'avvio.
|
||||
- [ ] Il processo può includere la capacità di validazione preinstallazione prodotta da T01 nelle revisioni che la contengono; non serve duplicarne l'implementazione per questo ticket.
|
||||
- [ ] Il manifest lega versione/revisione e digest compatibili; una pubblicazione parziale non viene esposta come rilascio completo e una versione immutabile non viene sovrascritta.
|
||||
- [ ] Viene pubblicato un rilascio reale e viene verificato il pull degli artefatti pubblicati, senza affidarsi a immagini presenti soltanto nella cache di build.
|
||||
- [ ] Test automatici verificano orchestrazione, fallimenti e retry senza richiedere una pubblicazione reale a ogni test; la prova reale del ticket resta distinta e registrata.
|
||||
- [ ] Documentazione manutentore IT/EN e istruzioni del bundle distinguono pubblicazione, consumo e futura estensione arm64. Namespace e accessi effettivi sono input del manutentore, non valori inventati.
|
||||
|
||||
### Blocked by
|
||||
|
||||
None (can start immediately).
|
||||
|
||||
## T05 — Installare la piattaforma dal rilascio senza domande
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
L'operatore applica un piano verificato, scarica gli artefatti pubblicati e ottiene
|
||||
una piattaforma inizializzata e accessibile senza compilazione o domande. Lo stato
|
||||
registrato permette di ritentare le fasi di piattaforma interrotte; non viene ancora
|
||||
dichiarato pronto un workspace privo delle successive verifiche Catalog.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Avvio da bundle rilasciato e operatore precompilato, senza checkout applicativo o toolchain; la revisione del bundle include i validatori e i comandi effettivamente utilizzati.
|
||||
- [ ] Il piano viene ricontrollato rispetto a input, release e prerequisiti vivi prima delle mutazioni; un piano mancante o incoerente viene rifiutato.
|
||||
- [ ] Con standard input chiuso il setup esegue pull, configurazione runtime, reti/volumi/container, inizializzazione Catalog/Memory e migrazioni senza richiedere parametri.
|
||||
- [ ] L'accesso amministrativo iniziale deriva da materiale protetto preparato prima; non si introduce un endpoint privilegiato senza autenticazione.
|
||||
- [ ] Un lock impedisce esecuzioni concorrenti; il journal atomico registra le fasi senza segreti e consente di verificare lo stato reale prima di ripetere una fase interrotta.
|
||||
- [ ] Errori di pull non causano build locali; errori di configurazione rimandano ai documenti e alla nuova verifica, senza prompt di riparazione.
|
||||
- [ ] La piattaforma accessibile è distinta dalla Workspace Readiness ancora da verificare; nessun messaggio finale prematuro di piena utilizzabilità.
|
||||
- [ ] Test del runner e prova con artefatti pubblicati coprono successo, stdin chiuso, interruzioni e ripetizione senza cancellare volumi o dati. Guide IT/EN documentano il risultato parziale corretto.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T03 — Verificare precondizioni e produrre il piano eseguibile.
|
||||
- T04 — Produrre e pubblicare un rilascio Docker Hub installabile.
|
||||
|
||||
## T06 — Applicare i binding preparati al Catalog
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Il setup rende operativa la configurazione database predisposta nei documenti:
|
||||
registra il repository, crea i Workspace Database e le Database Binding nel Catalog,
|
||||
installa i riferimenti segreti e verifica le connessioni. Il risultato è un binding
|
||||
utilizzabile senza una compilazione manuale dei parametri nell'interfaccia web.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Identità e revisioni dei workspace corrispondono al piano; il consumo del repository non richiede push e non sostituisce implicitamente una sorgente esistente.
|
||||
- [ ] Creazione e modifica dei binding utilizzano servizi autorizzati, controlli di versione e secret store esistenti; nessuna seconda autorità runtime nei documenti bootstrap.
|
||||
- [ ] La stessa configurazione applicata due volte non duplica record, credenziali o binding.
|
||||
- [ ] Una modifica amministrativa incompatibile produce un rapporto di riconciliazione invece di essere sovrascritta dai file preparatori.
|
||||
- [ ] La connessione viene controllata dall'ambiente applicativo; un esito positivo ottenuto dall'host non basta a dichiararla utilizzabile dai container.
|
||||
- [ ] Un'interruzione dopo il salvataggio ma prima dell'aggiornamento del journal viene riconosciuta alla ripresa, senza duplicazioni o perdita di segreti.
|
||||
- [ ] Test di contratto e integrazione Catalog coprono autorizzazioni, concorrenza, versioni e rerun; guide IT/EN illustrano diagnosi e riconciliazione.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T05 — Installare la piattaforma dal rilascio senza domande.
|
||||
|
||||
## T07 — Portare il workspace alla readiness con controlli runtime
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Da un binding applicato, il percorso completa sincronizzazione dello schema e
|
||||
preparazione necessaria e rende visibili i risultati dei controlli runtime.
|
||||
Un workspace è pronto solo quando tutti i requisiti applicabili sono verificati;
|
||||
le decisioni umane già previste dai contratti rimangono esplicite.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] La sincronizzazione usa i Catalog Sync Runs durabili con lock, freschezza e transazioni esistenti; non introduce una seconda implementazione.
|
||||
- [ ] Diff distruttive fermano il percorso in attesa della revisione di dominio esistente; ripresa successiva senza auto-conferme né domande sui parametri di setup.
|
||||
- [ ] Preprocessing e consolidamento riusano descrizioni/commenti ed Evidence curate; nessuna generazione AI implicita, nessuna cancellazione di Memory o sovrascrittura di curation.
|
||||
- [ ] Assenza lecita di Evidence non blocca; Evidence configurate ma invalide e indici necessari non pronti restano blocchi reali.
|
||||
- [ ] Pi, modello embedding, trasporto DWH e altri obblighi differiti sono eseguiti a runtime e rendicontati; nessun obbligo scompare o viene considerato superato senza prova.
|
||||
- [ ] Stato piattaforma, Workspace Readiness e collaudo funzionale sono distinti; una domanda reale con revisione rimane la prova funzionale, senza SQL target.
|
||||
- [ ] Test di servizio e integrazione dimostrano esiti, conservazione dati e ripresa dei run; guide IT/EN spiegano le eventuali revisioni umane residue.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T06 — Applicare i binding preparati al Catalog.
|
||||
|
||||
## T08 — Conservare il percorso esplicito da sorgente
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Un operatore sceglie esplicitamente la build da una revisione sorgente e usa gli
|
||||
stessi documenti, validatori, identità d'installazione e servizi del percorso
|
||||
precompilato. L'alternativa resta praticabile mentre il default diventa Docker Hub.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Modalità sorgente e prerequisiti aggiuntivi sono espliciti; nessun errore del registry la attiva automaticamente.
|
||||
- [ ] I componenti costruiti sono equivalenti nei contratti di configurazione, migrazione e persistenza; non esistono implementazioni parallele dei binding o della readiness.
|
||||
- [ ] Il piano identifica modalità e revisione e invalida i controlli dipendenti quando cambiano.
|
||||
- [ ] L'esecuzione rimane non interattiva e usa journal/lock comuni; i segreti non entrano nelle immagini di sviluppo.
|
||||
- [ ] Una prova automatizzata dimostra build e avvio espliciti e il mancato fallback da pull; una prova sorgente non chiude l'accettazione del rilascio precompilato.
|
||||
- [ ] Guide IT/EN separano il percorso avanzato da quello ordinario e rendono visibili i prerequisiti aggiuntivi.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T05 — Installare la piattaforma dal rilascio senza domande.
|
||||
|
||||
## T09 — Riprendere dopo correzioni e interruzioni senza perdere stato
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
L'operatore corregge un endpoint, una credenziale o un altro documento dopo un errore
|
||||
e riprende l'intero percorso con verifiche aggiornate. Questo ticket completa il
|
||||
recupero fra stadi e modalità, oltre ai retry locali già consegnati dai singoli ticket.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Cambiamenti ai documenti, ai contenuti/revisioni workspace o al rilascio invalidano le sole verifiche/fasi dipendenti; le altre vengono riconciliate con lo stato reale.
|
||||
- [ ] La rotazione di una credenziale viene rilevata senza esporla o pubblicarne fingerprint non protetti; si ripetono le prove necessarie.
|
||||
- [ ] Ripresa dopo interruzione nei confini fra pull, inizializzazione, importazione Catalog, sync e preprocessing non duplica operazioni già persistite.
|
||||
- [ ] Il preprocessing interrotto è rieseguito secondo il contratto esistente, senza promettere resume interno; un run in attesa di decisione umana conserva tale stato.
|
||||
- [ ] Interruzioni, errori e concorrenza non corrompono il journal né attivano reset di volumi; diagnosi e stato rimangono privi di segreti.
|
||||
- [ ] Test del percorso pubblico, con guasti controllati e integrazione dove conta la persistenza, dimostrano conservazione di sessioni, Evidence, descrizioni e Memory in entrambe le modalità.
|
||||
- [ ] Le guide IT/EN presentano scenari di correzione/ripresa senza suggerire la cancellazione dei dati come normale rimedio.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T07 — Portare il workspace alla readiness con controlli runtime.
|
||||
- T08 — Conservare il percorso esplicito da sorgente.
|
||||
|
||||
## T10 — Collaudare l'installazione pubblicata su Windows/WSL2
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Dimostrare il percorso completo su un PC Windows x64 con Ubuntu WSL2 e Docker
|
||||
Desktop usando il rilascio realmente pubblicato, repository ad hoc e documenti
|
||||
predisposti. Il collaudo include le correzioni necessarie a rendere utilizzabile
|
||||
la prima piattaforma e un rapporto riproducibile.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Un rilascio della revisione integrata viene pubblicato tramite T04 e consumato tramite pull; le immagini costruite soltanto localmente non soddisfano la prova.
|
||||
- [ ] Il consumer non dispone di sorgenti applicativi o toolchain necessarie a compilare; operatore e validatori sono quelli precompilati nel bundle.
|
||||
- [ ] Tutti i sei passi sono percorsi nell'ordine documentato, con almeno una correzione documentale e una ripresa dopo errore, senza domande durante il setup.
|
||||
- [ ] Primo workspace ad hoc realmente utilizzabile, una domanda con revisione umana e stop/start con stato preservato; nessun uso presunto degli esempi rinviati.
|
||||
- [ ] Rapporto con host/runtime, revisione, digest e risultati distinti di piattaforma/workspace/funzione, senza segreti; problemi esterni non sono nascosti.
|
||||
- [ ] Guide IT/EN sono verificate rispetto ai comandi e agli esiti reali; eventuale assenza di host o credenziali necessarie lascia il collaudo incompleto, non simulato come riuscito.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T09 — Riprendere dopo correzioni e interruzioni senza perdere stato.
|
||||
|
||||
## T11 — Collaudare l'installazione su Omarchy
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Dopo la tappa Windows, ripetere e rendere funzionante il percorso su Linux Omarchy
|
||||
x64, producendo un'evidenza di accettazione propria e mantenendo il comportamento
|
||||
documentale e non interattivo già consegnato.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Rilascio pubblico compatibile scaricato da Docker Hub e comando host precompilato; nessuna compilazione nel percorso ordinario.
|
||||
- [ ] Prerequisiti, permessi, percorsi e rete di Omarchy sono verificati su un host reale, senza trasferire automaticamente l'esito Windows.
|
||||
- [ ] Sei passi, input invalido/corretto, ripresa, workspace ad hoc, domanda reale e stop/start superano il collaudo.
|
||||
- [ ] Ogni correzione di portabilità include la relativa verifica e non introduce una divergenza dei contratti rispetto al percorso Windows.
|
||||
- [ ] Rapporto separato con versioni/digest e guide IT/EN coerenti; senza un host disponibile il gate rimane aperto.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T10 — Collaudare l'installazione pubblicata su Windows/WSL2.
|
||||
|
||||
## T12 — Pubblicare e collaudare il percorso macOS Apple Silicon
|
||||
|
||||
### Parent
|
||||
|
||||
[Spec: installazione da documenti verificati e distribuzione Docker Hub](https://git.tylconsulting.it/mptyl/ThothII/issues/42).
|
||||
|
||||
### What to build
|
||||
|
||||
Dopo Omarchy, pubblicare e verificare il set di artefatti compatibile con macOS
|
||||
Apple Silicon, incluse immagini Linux arm64 e comando nativo, e chiudere la terza
|
||||
tappa di accettazione su un Mac reale.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] Il comando di rilascio pubblica immagini arm64 e bundle host compatibile, con manifest/digest coerenti e senza dichiarare supporto prima del collaudo.
|
||||
- [ ] Il consumer usa il rilascio pubblico e non compila; gli script e le risorse di inizializzazione sono presenti nel bundle.
|
||||
- [ ] Tutti i sei passi, correzione/ripresa, workspace ad hoc, domanda reale e stop/start sono verificati sul Mac.
|
||||
- [ ] Le eventuali correzioni conservano compatibilità e contratti delle tappe precedenti; le prove multiarch di build non sostituiscono il collaudo host.
|
||||
- [ ] Rapporto macOS separato e guide IT/EN finalizzate per le tre piattaforme; nessun risultato sintetico viene presentato come prova reale.
|
||||
|
||||
### Blocked by
|
||||
|
||||
- T11 — Collaudare l'installazione su Omarchy.
|
||||
|
||||
## Verifiche della scomposizione
|
||||
|
||||
- I primi ticket lavorabili sono T01 e T04.
|
||||
- T03 usa manifest e servizi controllati per i propri contratti; non aspetta la
|
||||
pubblicazione reale. T05 è il primo punto che richiede insieme validazione e
|
||||
artefatti realmente pubblicati.
|
||||
- T06 e T08 possono procedere in parallelo dopo T05. T09 riunisce i percorsi per
|
||||
verificare correzioni e ripresa dell'intera installazione.
|
||||
- I tre gate host sono sequenziali per scelta esplicita dell'utente, non per una
|
||||
dipendenza architetturale inventata.
|
||||
- Gli esempi restano esclusi. Il comando di pubblicazione Docker Hub e almeno una
|
||||
pubblicazione reale sono inclusi, non demandati a un futuro progetto.
|
||||
- Nessun aggiornamento o chiusura della parent è previsto dalla pubblicazione.
|
||||
@@ -1,5 +1,46 @@
|
||||
# Native installation CLI
|
||||
|
||||
## Offline workspace documents (issue #43)
|
||||
|
||||
`tht workspace prepare --directory NEW_PATH --id ID --name NAME [--language en|it]`
|
||||
creates an ad hoc workspace repository template. `tht workspace validate --directory
|
||||
PATH [--json]` checks the working documents without an installation descriptor or
|
||||
services. Both commands invoke the packaged sibling `tht-workspace-documents`, which
|
||||
compiles the canonical backend YAML/Zod parsers with its runtime. Neither Node nor
|
||||
Bun is required on the user's computer. Validation never writes documents or Git
|
||||
configuration. See the [IT](../../docs/install/standalone-manual-it.md) and
|
||||
[EN](../../docs/install/standalone-manual-en.md) guides for the correction loop and
|
||||
explicit runtime checks that local validation cannot satisfy.
|
||||
|
||||
Maintainer build (Go from `go.mod`, Node/npm for build only):
|
||||
|
||||
```sh
|
||||
cd backend
|
||||
npm ci
|
||||
npm run build:workspace-tools
|
||||
# Cross-compile the complete platform pairs:
|
||||
npm run build:workspace-tools -- --all
|
||||
```
|
||||
|
||||
The output is `dist/workspace-tools/<os>-<arch>/` containing `tht[.exe]`,
|
||||
`tht-workspace-documents[.exe]`, `SHA256SUMS` and `build.json`. Individual targets:
|
||||
`windows-amd64`, `linux-amd64`, `linux-arm64`, `darwin-amd64`, `darwin-arm64`.
|
||||
Bun is pinned in `backend/package-lock.json`; compilation embeds the runtime, and
|
||||
cross-compilation may download the selected Bun target. Deliver the complete pair
|
||||
from one build, verify checksums and keep the executables together. The previous
|
||||
`build-tht.sh` / `install-tht.sh` single-binary path remains for existing operator
|
||||
commands; it does not package this helper. Release publication is tracked separately
|
||||
in issue #46; building a Windows/Linux artifact does not establish acceptance there.
|
||||
|
||||
Run the same public CLI fixture corpus against the native pair, with subprocess
|
||||
`PATH` deliberately empty:
|
||||
|
||||
```sh
|
||||
cd backend
|
||||
THT_WORKSPACE_TEST_CLI=/absolute/path/dist/workspace-tools/darwin-arm64/tht \
|
||||
npx vitest run test/workspace-documents-cli.test.ts
|
||||
```
|
||||
|
||||
## Shell configuration
|
||||
|
||||
The schema-v2 `thothii-installation.yaml` accepts this optional section:
|
||||
|
||||
@@ -85,6 +85,10 @@ Commands:
|
||||
pi maintenance recover --yes
|
||||
Verify a terminal installation, remove stale lifecycle files, and clear maintenance.
|
||||
pi logs Show the latest 200 sanitized core log lines (bounded; no follow mode).
|
||||
workspace prepare --directory NEW_PATH --id ID --name NAME [--language en|it] [--json]
|
||||
Prepare workspace documents locally, before installation.
|
||||
workspace validate --directory PATH [--json]
|
||||
Validate local workspace documents without starting services.
|
||||
workspace inspect --workspace ID [--json]
|
||||
workspace pull [--json]
|
||||
Pull and activate the configured workspace repository.
|
||||
@@ -141,6 +145,9 @@ func run(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
||||
}
|
||||
return commandUsageError(stderr, fmt.Sprintf("unknown command %q", command))
|
||||
}
|
||||
if command == "workspace" && len(commandArgs) > 0 && (commandArgs[0] == "prepare" || commandArgs[0] == "validate") {
|
||||
return workspaceDocumentsCommand(ctx, commandArgs, stdout, stderr)
|
||||
}
|
||||
workingDirectory, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "tht: current directory is unavailable: %s\n", output.Sanitize(err.Error(), nil))
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// Resolve only the packaged sibling, never an executable from the workspace or PATH.
|
||||
func workspaceDocumentsCommand(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
||||
executable, err := os.Executable()
|
||||
if err == nil {
|
||||
executable, err = filepath.EvalSymlinks(executable)
|
||||
}
|
||||
if err == nil {
|
||||
name := "tht-workspace-documents"
|
||||
if runtime.GOOS == "windows" {
|
||||
name += ".exe"
|
||||
}
|
||||
command := exec.CommandContext(ctx, filepath.Join(filepath.Dir(executable), name), args...)
|
||||
command.Stdout, command.Stderr = stdout, stderr
|
||||
err = command.Run()
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
var exitError *exec.ExitError
|
||||
if errors.As(err, &exitError) && exitError.ExitCode() >= 0 {
|
||||
return exitError.ExitCode()
|
||||
}
|
||||
}
|
||||
const correction = "Install tht and tht-workspace-documents from the same platform bundle in the same directory, then retry."
|
||||
if slices.Contains(args, "--json") {
|
||||
_ = json.NewEncoder(stdout).Encode(map[string]any{
|
||||
"schema_version": 1, "scope": "local-documents", "ok": false,
|
||||
"workspaces": []any{}, "deferred_checks": []string{},
|
||||
"issues": []map[string]string{{"document": "CLI", "field": "$", "code": "workspace_helper_unavailable", "correction": correction}},
|
||||
})
|
||||
} else {
|
||||
fmt.Fprintln(stderr, correction)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWorkspaceDocumentsNeedsPackagedHelperNotInstallation(t *testing.T) {
|
||||
t.Setenv("PATH", "")
|
||||
t.Setenv("THOTHII_INSTALLATION", "/nonexistent/installation.yaml")
|
||||
for _, action := range []string{"prepare", "validate"} {
|
||||
var stdout, stderr bytes.Buffer
|
||||
status := run(context.Background(), []string{"workspace", action, "--directory", t.TempDir(), "--json"}, &stdout, &stderr)
|
||||
var report struct {
|
||||
OK bool `json:"ok"`
|
||||
Issues []struct {
|
||||
Code string `json:"code"`
|
||||
} `json:"issues"`
|
||||
}
|
||||
if err := json.Unmarshal(stdout.Bytes(), &report); err != nil {
|
||||
t.Fatalf("missing structured helper error: status=%d stdout=%s stderr=%s", status, &stdout, &stderr)
|
||||
}
|
||||
if status != 1 || report.OK || len(report.Issues) != 1 || report.Issues[0].Code != "workspace_helper_unavailable" || stderr.Len() != 0 {
|
||||
t.Fatalf("unexpected missing-helper result: status=%d stdout=%s stderr=%s", status, &stdout, &stderr)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user