release v0.3.0 (origen c00f020)
This commit is contained in:
commit
85318855ba
13 files changed
+874
No files matched your search
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Toni Ramiro
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# pi-new-project (distribución)
|
||||||
|
|
||||||
|
Versión instalable de **pi-new-project** v0.3.0: solo los ficheros que pi
|
||||||
|
necesita para usar el paquete (skill `new-project` y orden `/modelo-proyecto`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pi install git:git.sargatxet.cloud/sargatxet/pi-new-project-dist
|
||||||
|
# versión fija:
|
||||||
|
pi install git:git.sargatxet.cloud/sargatxet/pi-new-project-dist@v0.3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentación, cambios e incidencias: <https://git.sargatxet.cloud/sargatxet/pi-new-project>
|
||||||
|
|
||||||
|
> Repositorio generado automáticamente desde https://git.sargatxet.cloud/sargatxet/pi-new-project
|
||||||
|
> (commit `c00f020`). No hagas cambios aquí: se perderán en la próxima publicación.
|
||||||
|
|
||||||
|
Licencia MIT, ver [`LICENSE`](LICENSE).
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
/**
|
||||||
|
* modelo-proyecto — modelo por defecto de un proyecto.
|
||||||
|
*
|
||||||
|
* Guarda el modelo elegido en `<proyecto>/.pi/settings.json` (`defaultProvider`
|
||||||
|
* y `defaultModel`), que pi aplica al iniciar cualquier sesión nueva en ese
|
||||||
|
* proyecto (una vez concedida la confianza del proyecto).
|
||||||
|
*
|
||||||
|
* - Orden `/modelo-proyecto [proveedor/modelo]`: muestra los modelos
|
||||||
|
* disponibles para elegir (o usa el indicado), lo guarda en el proyecto del
|
||||||
|
* directorio actual y lo activa en la sesión en curso.
|
||||||
|
* - Herramienta `elegir_modelo_proyecto`: la usa la skill `new-project` para
|
||||||
|
* que el usuario elija el modelo al crear un proyecto en otra ruta.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
||||||
|
import { join, resolve } from "node:path";
|
||||||
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
||||||
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
||||||
|
import { DynamicBorder } from "@earendil-works/pi-coding-agent";
|
||||||
|
import { Container, type SelectItem, SelectList, Text } from "@earendil-works/pi-tui";
|
||||||
|
import { Type } from "typebox";
|
||||||
|
|
||||||
|
const SETTINGS_REL = join(".pi", "settings.json");
|
||||||
|
/** Máximo de modelos visibles a la vez en el selector (la lista se desplaza). */
|
||||||
|
const MAX_VISIBLES = 15;
|
||||||
|
|
||||||
|
function clave(m: Model<Api>): string {
|
||||||
|
return `${m.provider}/${m.id}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function kilos(n: number | undefined): string {
|
||||||
|
if (!n) return "?";
|
||||||
|
return n >= 1_000_000 ? `${(n / 1_000_000).toFixed(1)}M` : `${Math.round(n / 1000)}K`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function etiqueta(m: Model<Api>, actual?: string): string {
|
||||||
|
const marca = actual === clave(m) ? " ← actual del proyecto" : "";
|
||||||
|
return `${clave(m)} (${m.name ?? m.id}, ctx ${kilos(m.contextWindow)})${marca}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function disponibles(ctx: ExtensionContext): Model<Api>[] {
|
||||||
|
return [...ctx.modelRegistry.getAvailable()].sort((a, b) => clave(a).localeCompare(clave(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function leerSettings(proyecto: string): Record<string, unknown> {
|
||||||
|
const ruta = join(proyecto, SETTINGS_REL);
|
||||||
|
if (!existsSync(ruta)) return {};
|
||||||
|
const texto = readFileSync(ruta, "utf-8").trim();
|
||||||
|
if (!texto) return {};
|
||||||
|
const datos = JSON.parse(texto);
|
||||||
|
if (typeof datos !== "object" || datos === null || Array.isArray(datos)) {
|
||||||
|
throw new Error(`${ruta} no contiene un objeto JSON`);
|
||||||
|
}
|
||||||
|
return datos as Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function modeloDelProyecto(proyecto: string): string | undefined {
|
||||||
|
try {
|
||||||
|
const s = leerSettings(proyecto);
|
||||||
|
if (typeof s.defaultProvider === "string" && typeof s.defaultModel === "string") {
|
||||||
|
return `${s.defaultProvider}/${s.defaultModel}`;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// settings ilegible: se trata como sin modelo
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fusiona defaultProvider/defaultModel en .pi/settings.json sin tocar el resto. */
|
||||||
|
function guardarModelo(proyecto: string, m: Model<Api>): string {
|
||||||
|
const ruta = join(proyecto, SETTINGS_REL);
|
||||||
|
const datos = leerSettings(proyecto);
|
||||||
|
datos.defaultProvider = m.provider;
|
||||||
|
datos.defaultModel = m.id;
|
||||||
|
mkdirSync(join(proyecto, ".pi"), { recursive: true });
|
||||||
|
const tmp = `${ruta}.tmp`;
|
||||||
|
writeFileSync(tmp, `${JSON.stringify(datos, null, 2)}\n`, "utf-8");
|
||||||
|
renameSync(tmp, ruta);
|
||||||
|
return ruta;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buscar(ctx: ExtensionContext, texto: string): Model<Api> | undefined {
|
||||||
|
const t = texto.trim();
|
||||||
|
const lista = disponibles(ctx);
|
||||||
|
return (
|
||||||
|
lista.find((m) => clave(m) === t) ??
|
||||||
|
(t.includes("/") ? undefined : lista.filter((m) => m.id === t).at(0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function elegir(ctx: ExtensionContext, proyecto: string): Promise<Model<Api> | undefined> {
|
||||||
|
const lista = disponibles(ctx);
|
||||||
|
if (lista.length === 0) throw new Error("no hay modelos disponibles (¿falta /login o credenciales?)");
|
||||||
|
const actual = modeloDelProyecto(proyecto);
|
||||||
|
const titulo = `Modelo por defecto del proyecto (${proyecto})`;
|
||||||
|
|
||||||
|
// Fuera de la TUI (p. ej. RPC) no hay componentes propios: diálogo estándar.
|
||||||
|
if (ctx.mode !== "tui") {
|
||||||
|
const opciones = lista.map((m) => etiqueta(m, actual));
|
||||||
|
const elegido = await ctx.ui.select(titulo, opciones);
|
||||||
|
if (!elegido) return undefined;
|
||||||
|
return lista[opciones.indexOf(elegido)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const items: SelectItem[] = lista.map((m) => ({ value: clave(m), label: etiqueta(m, actual) }));
|
||||||
|
const valor = await ctx.ui.custom<string | null>((tui, theme, _kb, done) => {
|
||||||
|
const contenedor = new Container();
|
||||||
|
contenedor.addChild(new DynamicBorder((s) => theme.fg("accent", s)));
|
||||||
|
contenedor.addChild(new Text(theme.fg("accent", theme.bold(titulo))));
|
||||||
|
|
||||||
|
// Ventana de MAX_VISIBLES elementos que se desplaza con el cursor;
|
||||||
|
// ↑ en el primero salta al último y ↓ en el último vuelve al primero.
|
||||||
|
const selector = new SelectList(items, Math.min(items.length, MAX_VISIBLES), {
|
||||||
|
selectedPrefix: (t) => theme.fg("accent", t),
|
||||||
|
selectedText: (t) => theme.fg("accent", t),
|
||||||
|
description: (t) => theme.fg("muted", t),
|
||||||
|
scrollInfo: (t) => theme.fg("dim", t),
|
||||||
|
noMatch: (t) => theme.fg("warning", t),
|
||||||
|
});
|
||||||
|
const inicial = actual ? items.findIndex((i) => i.value === actual) : -1;
|
||||||
|
if (inicial >= 0) selector.setSelectedIndex(inicial);
|
||||||
|
selector.onSelect = (item) => done(item.value);
|
||||||
|
selector.onCancel = () => done(null);
|
||||||
|
contenedor.addChild(selector);
|
||||||
|
|
||||||
|
contenedor.addChild(new Text(theme.fg("dim", "↑↓ moverse • enter elegir • esc cancelar")));
|
||||||
|
contenedor.addChild(new DynamicBorder((s) => theme.fg("accent", s)));
|
||||||
|
|
||||||
|
return {
|
||||||
|
render: (width: number) => contenedor.render(width),
|
||||||
|
invalidate: () => contenedor.invalidate(),
|
||||||
|
handleInput: (data: string) => {
|
||||||
|
selector.handleInput(data);
|
||||||
|
tui.requestRender();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (!valor) return undefined;
|
||||||
|
return lista.find((m) => clave(m) === valor);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function (pi: ExtensionAPI) {
|
||||||
|
// Lista para autocompletar (getArgumentCompletions no recibe ctx).
|
||||||
|
let cache: string[] = [];
|
||||||
|
pi.on("session_start", (_event, ctx) => {
|
||||||
|
try {
|
||||||
|
cache = disponibles(ctx).map(clave);
|
||||||
|
} catch {
|
||||||
|
cache = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pi.registerCommand("modelo-proyecto", {
|
||||||
|
description: "Elige el modelo por defecto de este proyecto (se guarda en .pi/settings.json)",
|
||||||
|
getArgumentCompletions: (prefijo) => {
|
||||||
|
const p = prefijo.trim().toLowerCase();
|
||||||
|
const items = cache.filter((k) => k.toLowerCase().includes(p)).map((k) => ({ value: k, label: k }));
|
||||||
|
return items.length ? items : null;
|
||||||
|
},
|
||||||
|
handler: async (args, ctx) => {
|
||||||
|
const proyecto = ctx.cwd;
|
||||||
|
let modelo: Model<Api> | undefined;
|
||||||
|
try {
|
||||||
|
if (args.trim()) {
|
||||||
|
modelo = buscar(ctx, args);
|
||||||
|
if (!modelo) {
|
||||||
|
ctx.ui.notify(`Modelo "${args.trim()}" no disponible. Usa /modelo-proyecto sin argumentos para elegir.`, "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!ctx.hasUI) {
|
||||||
|
ctx.ui.notify("Sin interfaz: indica el modelo, /modelo-proyecto proveedor/modelo", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modelo = await elegir(ctx, proyecto);
|
||||||
|
if (!modelo) {
|
||||||
|
ctx.ui.notify("Sin cambios: no se eligió modelo.", "info");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const ruta = guardarModelo(proyecto, modelo);
|
||||||
|
const activo = await pi.setModel(modelo);
|
||||||
|
ctx.ui.notify(
|
||||||
|
`Modelo del proyecto: ${clave(modelo)} (guardado en ${ruta})` +
|
||||||
|
(activo ? "; activado en esta sesión." : "; no se pudo activar ahora (¿credenciales?)."),
|
||||||
|
activo ? "info" : "warning",
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
ctx.ui.notify(`modelo-proyecto: ${(err as Error).message}`, "error");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
pi.registerTool({
|
||||||
|
name: "elegir_modelo_proyecto",
|
||||||
|
label: "Elegir modelo del proyecto",
|
||||||
|
description:
|
||||||
|
"Muestra al usuario la lista de modelos disponibles para que elija el modelo por defecto de un proyecto " +
|
||||||
|
"y lo guarda en <ruta>/.pi/settings.json (defaultProvider/defaultModel), que pi usará en las nuevas sesiones " +
|
||||||
|
"de ese proyecto. Úsala al crear un proyecto. No elijas tú el modelo: deja que el usuario lo seleccione. " +
|
||||||
|
"Pasa 'modelo' (proveedor/id) solo si el usuario ya lo ha dicho explícitamente.",
|
||||||
|
parameters: Type.Object({
|
||||||
|
ruta: Type.String({ description: "Directorio raíz del proyecto" }),
|
||||||
|
modelo: Type.Optional(
|
||||||
|
Type.String({ description: "proveedor/id ya indicado por el usuario; si falta se muestra el selector" }),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
||||||
|
const proyecto = resolve(ctx.cwd, params.ruta.replace(/^~(?=$|\/)/, process.env.HOME ?? "~"));
|
||||||
|
let modelo: Model<Api> | undefined;
|
||||||
|
if (params.modelo) {
|
||||||
|
modelo = buscar(ctx, params.modelo);
|
||||||
|
if (!modelo) {
|
||||||
|
const lista = disponibles(ctx).map(clave).join(", ");
|
||||||
|
throw new Error(`modelo "${params.modelo}" no disponible. Disponibles: ${lista}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!ctx.hasUI) {
|
||||||
|
const lista = disponibles(ctx).map(clave).join("\n");
|
||||||
|
throw new Error(
|
||||||
|
`sin interfaz para mostrar el selector. Pregunta al usuario y vuelve a llamar con 'modelo'. Disponibles:\n${lista}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
modelo = await elegir(ctx, proyecto);
|
||||||
|
if (!modelo) {
|
||||||
|
return {
|
||||||
|
content: [{ type: "text", text: "El usuario canceló la elección; no se guardó modelo. Pregúntale si quiere elegir uno." }],
|
||||||
|
details: { proyecto, modelo: null },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const ruta = guardarModelo(proyecto, modelo);
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: `Modelo por defecto del proyecto: ${clave(modelo)}. Guardado en ${ruta}. Se cambia con /modelo-proyecto.`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
details: { proyecto, modelo: clave(modelo), ruta },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "pi-new-project",
|
||||||
|
"version": "0.3.0",
|
||||||
|
"private": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "Paquete de pi con la skill new-project (base documental de un proyecto) y la orden /modelo-proyecto (modelo por defecto del proyecto).",
|
||||||
|
"homepage": "https://git.sargatxet.cloud/sargatxet/pi-new-project",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://git.sargatxet.cloud/sargatxet/pi-new-project.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"pi-package"
|
||||||
|
],
|
||||||
|
"pi": {
|
||||||
|
"extensions": [
|
||||||
|
"./extensions"
|
||||||
|
],
|
||||||
|
"skills": [
|
||||||
|
"./skills"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
name: new-project
|
||||||
|
description: Genera la base documental de un proyecto nuevo (AGENTS.md, README.md, CHANGELOG.md, TODO.md, INSTALL.md y .gitignore) a partir de plantillas, y deja que el usuario elija el modelo por defecto del proyecto. Úsala cuando el usuario pida crear un proyecto, repositorio o directorio nuevo, inicializar su documentación o "montar el esqueleto" de un repo.
|
||||||
|
license: MIT
|
||||||
|
---
|
||||||
|
|
||||||
|
# new-project
|
||||||
|
|
||||||
|
Genera el esqueleto documental de un proyecto. Todas las plantillas están en
|
||||||
|
`templates/` y el andamiaje lo hace `scripts/new-project.sh`.
|
||||||
|
|
||||||
|
## Procedimiento
|
||||||
|
|
||||||
|
1. **Recoge los datos** que falten antes de ejecutar nada:
|
||||||
|
- ruta de destino (obligatoria);
|
||||||
|
- nombre del proyecto (por defecto, el nombre del directorio destino);
|
||||||
|
- descripción en una frase (obligatoria: se usa en README y AGENTS);
|
||||||
|
- autor (opcional; por defecto `git config user.name`);
|
||||||
|
- si hay que inicializar un repositorio git (`--git`).
|
||||||
|
No inventes la descripción: si el usuario no la da, pregúntala o propón una
|
||||||
|
y confírmala.
|
||||||
|
2. **Ejecuta el script** desde este directorio de skill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/new-project.sh --nombre "Mi Proyecto" --descripcion "Qué hace" \
|
||||||
|
--git /ruta/al/proyecto
|
||||||
|
```
|
||||||
|
|
||||||
|
El script no sobreescribe ficheros existentes salvo con `--force` y muestra
|
||||||
|
un resumen de lo creado. Usa `--dry-run` para revisar antes.
|
||||||
|
3. **Modelo por defecto del proyecto** (obligatorio): el usuario elige el modelo
|
||||||
|
de entre los existentes; tú no lo eliges.
|
||||||
|
- Llama a la herramienta `elegir_modelo_proyecto` con `ruta` = destino del
|
||||||
|
proyecto. Muestra al usuario el selector con los modelos disponibles y
|
||||||
|
guarda su elección en `<ruta>/.pi/settings.json` (`defaultProvider` y
|
||||||
|
`defaultModel`). pi lo usará en todas las sesiones nuevas del proyecto.
|
||||||
|
- Si la herramienta no existe o no hay interfaz: ejecuta `pi --list-models`,
|
||||||
|
enséñale la lista al usuario, pregúntale cuál quiere y guárdalo con
|
||||||
|
`scripts/new-project.sh --modelo proveedor/id <destino>` (solo crea
|
||||||
|
`.pi/settings.json` si no existe).
|
||||||
|
- Si el usuario cancela, déjalo sin fijar e indícale que puede hacerlo más
|
||||||
|
tarde con `/modelo-proyecto`.
|
||||||
|
4. **Revisa el resultado**: abre `README.md` y `AGENTS.md` del proyecto generado
|
||||||
|
y completa lo que quede como `PENDIENTE` (objetivos, stack, comandos de
|
||||||
|
verificación reales). No dejes marcadores de plantilla ni secciones vacías.
|
||||||
|
5. **Ajusta** `INSTALL.md` con los requisitos y pasos reales del stack elegido.
|
||||||
|
6. **Commit inicial** si se creó repo git (incluye `.pi/settings.json`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A && git commit -m "docs: base documental inicial"
|
||||||
|
```
|
||||||
|
7. Informa al usuario de la ruta creada, los ficheros, el modelo elegido, el
|
||||||
|
commit y de que puede cambiar el modelo en cualquier momento con
|
||||||
|
`/modelo-proyecto` dentro del proyecto.
|
||||||
|
|
||||||
|
## Reglas
|
||||||
|
|
||||||
|
- No ejecutes el script sobre un directorio que ya tiene `AGENTS.md` o `README.md`
|
||||||
|
sin avisar y confirmar (usaría `--force`).
|
||||||
|
- Las secciones `## Reglas de modelo` (salvo el modelo por defecto, que gestiona
|
||||||
|
`/modelo-proyecto`) y `## Reglas de funcionamiento` de
|
||||||
|
`AGENTS.md` se dejan como `PENDIENTE` a propósito: se acuerdan después, por
|
||||||
|
proyecto. No las rellenes con suposiciones.
|
||||||
|
- Idioma de los documentos generados: español.
|
||||||
|
- Rutas relativas siempre desde este directorio de skill.
|
||||||
|
|
||||||
|
## Referencia
|
||||||
|
|
||||||
|
- `scripts/new-project.sh --help` — todas las opciones.
|
||||||
|
- `/modelo-proyecto [proveedor/id]` — cambia el modelo por defecto del proyecto
|
||||||
|
del directorio actual (sin argumento, muestra el selector).
|
||||||
|
- `templates/` — plantillas con marcadores `{{PROYECTO}}`, `{{DESCRIPCION}}`,
|
||||||
|
`{{AUTOR}}`, `{{FECHA}}`, `{{FECHA_ISO}}`.
|
||||||
|
- `references/plantillas.md` — qué contiene cada documento y cuándo tocarlo.
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Plantillas de la base documental
|
||||||
|
|
||||||
|
Qué genera `new-project.sh` y cuándo hay que tocar cada documento.
|
||||||
|
|
||||||
|
| Documento | Para qué sirve | Cuándo actualizarlo |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `AGENTS.md` | Reglas de trabajo para agentes y colaboradores: flujo, commits, verificación y las futuras reglas de modelo y de funcionamiento. | Al cambiar el flujo, las reglas, los comandos de verificación o al fijar las reglas de modelo. |
|
||||||
|
| `README.md` | Puerta de entrada: qué es el proyecto, estado, instalación rápida, uso y estructura. | Al cambiar el propósito, el uso o la estructura. |
|
||||||
|
| `INSTALL.md` | Instalación reproducible: requisitos, dependencias, configuración, verificación, arranque, actualización y desinstalación. | Al añadir dependencias, variables de entorno o cambiar pasos de instalación. |
|
||||||
|
| `CHANGELOG.md` | Historial *Keep a Changelog*: `Añadido` / `Cambiado` / `Corregido` / `Eliminado`. | En cada cambio, sin excepción. |
|
||||||
|
| `TODO.md` | Tareas en curso, pendientes y hechas, incluida la deuda técnica. | Al abrir o cerrar tareas. |
|
||||||
|
| `.gitignore` | Exclusiones básicas: secretos, dependencias descargadas, artefactos de build, logs. | Al detectar ficheros que no deben versionarse. |
|
||||||
|
| `.pi/settings.json` | Modelo por defecto de pi para el proyecto (`defaultProvider`, `defaultModel`). Lo crea `elegir_modelo_proyecto` o `--modelo`. | Solo con `/modelo-proyecto`, a petición del usuario. |
|
||||||
|
|
||||||
|
## Marcadores
|
||||||
|
|
||||||
|
El script sustituye estos marcadores en todas las plantillas:
|
||||||
|
|
||||||
|
| Marcador | Valor |
|
||||||
|
| --- | --- |
|
||||||
|
| `{{PROYECTO}}` | `--nombre` o, si falta, el nombre del directorio destino. |
|
||||||
|
| `{{DESCRIPCION}}` | `--descripcion` o un `PENDIENTE` explícito. |
|
||||||
|
| `{{AUTOR}}` | `--autor` o `git config user.name`. |
|
||||||
|
| `{{FECHA}}` y `{{FECHA_ISO}}` | Fecha de ejecución en formato `AAAA-MM-DD`. |
|
||||||
|
|
||||||
|
## Secciones reservadas
|
||||||
|
|
||||||
|
`AGENTS.md` incluye a propósito dos secciones con `PENDIENTE`:
|
||||||
|
|
||||||
|
- `## Reglas de modelo` — explica dónde está el modelo por defecto y cómo
|
||||||
|
cambiarlo; el criterio de selección por tarea queda `PENDIENTE`.
|
||||||
|
- `## Reglas de funcionamiento` — estándares, ramas, revisión y automatización.
|
||||||
|
|
||||||
|
No se rellenan al generar el proyecto: se acuerdan después, proyecto a proyecto.
|
||||||
|
|
||||||
|
## Modelo por defecto
|
||||||
|
|
||||||
|
- Al crear el proyecto, el usuario elige el modelo en el selector de la
|
||||||
|
herramienta `elegir_modelo_proyecto` (alternativa: `--modelo proveedor/id`).
|
||||||
|
- Se guarda en `<proyecto>/.pi/settings.json`; pi lo aplica en cada sesión nueva
|
||||||
|
del proyecto si éste es de confianza.
|
||||||
|
- Se cambia en cualquier momento con `/modelo-proyecto`, que fusiona el valor con
|
||||||
|
el resto de ajustes del fichero y activa el modelo en la sesión actual.
|
||||||
Executable
+154
@@ -0,0 +1,154 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Genera la base documental de un proyecto a partir de las plantillas de la skill.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# bash >= 5.2 sustituye '&' del reemplazo por el patrón encontrado; lo desactivamos
|
||||||
|
# para que los valores con '&' o '\' se inserten literales.
|
||||||
|
shopt -u patsub_replacement 2>/dev/null || true
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
TEMPLATES_DIR="$SCRIPT_DIR/../templates"
|
||||||
|
|
||||||
|
PROYECTO=""
|
||||||
|
DESCRIPCION=""
|
||||||
|
AUTOR=""
|
||||||
|
DESTINO=""
|
||||||
|
MODELO=""
|
||||||
|
INIT_GIT=0
|
||||||
|
FORCE=0
|
||||||
|
DRY_RUN=0
|
||||||
|
FECHA_ISO="$(date +%Y-%m-%d)"
|
||||||
|
|
||||||
|
uso() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Uso: new-project.sh [opciones] <directorio-destino>
|
||||||
|
|
||||||
|
Genera AGENTS.md, README.md, CHANGELOG.md, TODO.md, INSTALL.md y .gitignore.
|
||||||
|
|
||||||
|
Opciones:
|
||||||
|
-n, --nombre NOMBRE Nombre del proyecto (por defecto: nombre del directorio).
|
||||||
|
-d, --descripcion TEXTO Descripción en una frase (por defecto: PENDIENTE).
|
||||||
|
-a, --autor NOMBRE Autor (por defecto: git config user.name).
|
||||||
|
-m, --modelo PROV/ID Modelo por defecto del proyecto; se guarda en
|
||||||
|
.pi/settings.json (lista: pi --list-models).
|
||||||
|
En pi es preferible la herramienta
|
||||||
|
elegir_modelo_proyecto o la orden /modelo-proyecto.
|
||||||
|
-g, --git Inicializa un repositorio git en el destino.
|
||||||
|
-f, --force Sobreescribe ficheros que ya existan.
|
||||||
|
--dry-run Muestra lo que haría sin escribir nada.
|
||||||
|
-h, --help Muestra esta ayuda.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
die() { printf 'error: %s\n' "$*" >&2; exit 1; }
|
||||||
|
aviso() { printf 'aviso: %s\n' "$*" >&2; }
|
||||||
|
requiere() { [[ $# -ge 2 && -n "$2" && "$2" != -* ]] || die "$1 necesita un valor"; }
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-n | --nombre) requiere "$@"; PROYECTO="$2"; shift 2 ;;
|
||||||
|
-d | --descripcion) requiere "$@"; DESCRIPCION="$2"; shift 2 ;;
|
||||||
|
-a | --autor) requiere "$@"; AUTOR="$2"; shift 2 ;;
|
||||||
|
-m | --modelo) requiere "$@"; MODELO="$2"; shift 2 ;;
|
||||||
|
-g | --git) INIT_GIT=1; shift ;;
|
||||||
|
-f | --force) FORCE=1; shift ;;
|
||||||
|
--dry-run) DRY_RUN=1; shift ;;
|
||||||
|
-h | --help) uso; exit 0 ;;
|
||||||
|
--) shift; break ;;
|
||||||
|
-*) die "opción desconocida: $1 (usa --help)" ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ $# -ge 1 ]] || { uso >&2; exit 2; }
|
||||||
|
DESTINO="$1"
|
||||||
|
[[ $# -eq 1 ]] || die "solo se admite un directorio destino"
|
||||||
|
|
||||||
|
[[ -d "$TEMPLATES_DIR" ]] || die "no encuentro las plantillas en $TEMPLATES_DIR"
|
||||||
|
|
||||||
|
if [[ -z "$PROYECTO" ]]; then
|
||||||
|
PROYECTO="$(basename -- "${DESTINO%/}")"
|
||||||
|
fi
|
||||||
|
[[ -n "$PROYECTO" ]] || die "no puedo deducir el nombre del proyecto; usa --nombre"
|
||||||
|
|
||||||
|
if [[ -z "$DESCRIPCION" ]]; then
|
||||||
|
DESCRIPCION="PENDIENTE: describir $PROYECTO en una frase."
|
||||||
|
aviso "sin --descripcion; se deja un PENDIENTE en README.md y AGENTS.md"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$AUTOR" ]]; then
|
||||||
|
AUTOR="$(git config user.name 2>/dev/null || true)"
|
||||||
|
[[ -n "$AUTOR" ]] || AUTOR="PENDIENTE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$MODELO" ]]; then
|
||||||
|
[[ "$MODELO" =~ ^[^/[:space:]\"]+/[^[:space:]\"]+$ ]] \
|
||||||
|
|| die "--modelo debe tener la forma proveedor/id (p. ej. anthropic/claude-sonnet-4-5)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
FICHEROS=(AGENTS.md README.md CHANGELOG.md TODO.md INSTALL.md .gitignore)
|
||||||
|
|
||||||
|
render() {
|
||||||
|
local plantilla="$1" salida="$2" contenido
|
||||||
|
contenido="$(<"$plantilla")"
|
||||||
|
contenido="${contenido//'{{PROYECTO}}'/$PROYECTO}"
|
||||||
|
contenido="${contenido//'{{DESCRIPCION}}'/$DESCRIPCION}"
|
||||||
|
contenido="${contenido//'{{AUTOR}}'/$AUTOR}"
|
||||||
|
contenido="${contenido//'{{FECHA}}'/$FECHA_ISO}"
|
||||||
|
contenido="${contenido//'{{FECHA_ISO}}'/$FECHA_ISO}"
|
||||||
|
printf '%s\n' "$contenido" > "$salida"
|
||||||
|
}
|
||||||
|
|
||||||
|
destino_abs="$(cd -- "$DESTINO" 2>/dev/null && pwd || true)"
|
||||||
|
[[ -n "$destino_abs" ]] || destino_abs="$DESTINO"
|
||||||
|
|
||||||
|
creados=()
|
||||||
|
omitidos=()
|
||||||
|
|
||||||
|
for fichero in "${FICHEROS[@]}"; do
|
||||||
|
ruta="$DESTINO/$fichero"
|
||||||
|
if [[ -e "$ruta" && $FORCE -eq 0 ]]; then
|
||||||
|
omitidos+=("$fichero")
|
||||||
|
aviso "$fichero ya existe; se omite (usa --force para sobreescribir)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $DRY_RUN -eq 1 ]]; then
|
||||||
|
printf 'dry-run: escribiría %s\n' "$ruta"
|
||||||
|
else
|
||||||
|
mkdir -p -- "$DESTINO"
|
||||||
|
render "$TEMPLATES_DIR/$fichero.tmpl" "$ruta"
|
||||||
|
fi
|
||||||
|
creados+=("$fichero")
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -n "$MODELO" ]]; then
|
||||||
|
settings="$DESTINO/.pi/settings.json"
|
||||||
|
if [[ -e "$settings" && $FORCE -eq 0 ]]; then
|
||||||
|
omitidos+=(".pi/settings.json")
|
||||||
|
aviso ".pi/settings.json ya existe; se omite (usa /modelo-proyecto en pi para cambiar el modelo sin perder otros ajustes)"
|
||||||
|
elif [[ $DRY_RUN -eq 1 ]]; then
|
||||||
|
printf 'dry-run: escribiría %s (modelo %s)\n' "$settings" "$MODELO"
|
||||||
|
creados+=(".pi/settings.json")
|
||||||
|
else
|
||||||
|
mkdir -p -- "$DESTINO/.pi"
|
||||||
|
printf '{\n "defaultProvider": "%s",\n "defaultModel": "%s"\n}\n' \
|
||||||
|
"${MODELO%%/*}" "${MODELO#*/}" > "$settings"
|
||||||
|
creados+=(".pi/settings.json")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $INIT_GIT -eq 1 && $DRY_RUN -eq 0 ]]; then
|
||||||
|
if [[ -d "$DESTINO/.git" ]]; then
|
||||||
|
aviso "$DESTINO ya es un repositorio git"
|
||||||
|
else
|
||||||
|
git -C "$DESTINO" init -q
|
||||||
|
printf 'git: repositorio inicializado en %s\n' "$destino_abs"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '\nproyecto: %s\n' "$PROYECTO"
|
||||||
|
printf 'destino: %s\n' "$destino_abs"
|
||||||
|
printf 'modelo: %s\n' "${MODELO:-sin fijar (elígelo con /modelo-proyecto)}"
|
||||||
|
printf 'creados: %s\n' "${creados[*]:-ninguno}"
|
||||||
|
[[ ${#omitidos[@]} -eq 0 ]] || printf 'omitidos: %s\n' "${omitidos[*]}"
|
||||||
|
[[ $DRY_RUN -eq 1 ]] || printf 'siguiente: revisa README.md, INSTALL.md y las secciones PENDIENTE de AGENTS.md\n'
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Secretos y configuración local
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# Dependencias descargadas
|
||||||
|
node_modules/
|
||||||
|
vendor/
|
||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
|
||||||
|
# Artefactos de build
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
target/
|
||||||
|
out/
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Sistema operativo y editores
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
Guía para agentes y colaboradores que trabajen en **{{PROYECTO}}**.
|
||||||
|
Léela antes de tocar cualquier fichero y respétala en cada cambio.
|
||||||
|
|
||||||
|
## Propósito del proyecto
|
||||||
|
|
||||||
|
{{DESCRIPCION}}
|
||||||
|
|
||||||
|
## Contenido del repositorio
|
||||||
|
|
||||||
|
| Ruta | Descripción |
|
||||||
|
| --- | --- |
|
||||||
|
| `AGENTS.md` | Este documento: reglas de trabajo. |
|
||||||
|
| `README.md` | Visión general y puesta en marcha. |
|
||||||
|
| `INSTALL.md` | Instalación detallada y dependencias. |
|
||||||
|
| `CHANGELOG.md` | Historial de cambios (*Keep a Changelog*). |
|
||||||
|
| `TODO.md` | Tareas pendientes y deuda técnica. |
|
||||||
|
| `.pi/settings.json` | Ajustes de pi del proyecto: modelo por defecto. |
|
||||||
|
| _(completar)_ | Añade aquí el código y los recursos del proyecto. |
|
||||||
|
|
||||||
|
## Reglas de modelo
|
||||||
|
|
||||||
|
### Modelo por defecto
|
||||||
|
|
||||||
|
El modelo por defecto del proyecto se guarda en `.pi/settings.json`
|
||||||
|
(`defaultProvider` y `defaultModel`) y pi lo aplica al iniciar cada sesión nueva
|
||||||
|
en este directorio (requiere haber confiado en el proyecto: `/trust`).
|
||||||
|
|
||||||
|
- Para cambiarlo: `/modelo-proyecto` (muestra los modelos disponibles) o
|
||||||
|
`/modelo-proyecto proveedor/id`.
|
||||||
|
- No edites a mano ni cambies ese modelo sin que lo pida el usuario.
|
||||||
|
- `.pi/settings.json` se versiona; un cambio de modelo se commitea como
|
||||||
|
cualquier otro cambio.
|
||||||
|
|
||||||
|
### Otras reglas
|
||||||
|
|
||||||
|
PENDIENTE: definir el contexto y el criterio de selección de modelos por tarea
|
||||||
|
(coste, VRAM, ventana, velocidad). Se acuerda tarea por tarea; hasta entonces,
|
||||||
|
no fijar valores aquí.
|
||||||
|
|
||||||
|
## Reglas de funcionamiento
|
||||||
|
|
||||||
|
PENDIENTE: definir flujo de trabajo, estándares de código, comandos obligatorios,
|
||||||
|
política de ramas y de revisión, y cualquier automatización propia del proyecto.
|
||||||
|
|
||||||
|
## Reglas obligatorias
|
||||||
|
|
||||||
|
1. **Todo cambio se documenta y se commitea.** Cada vez que se modifique
|
||||||
|
cualquier fichero del repositorio:
|
||||||
|
- Añadir una entrada en `CHANGELOG.md` (fecha, versión y tipo:
|
||||||
|
`Añadido` / `Cambiado` / `Corregido` / `Eliminado`).
|
||||||
|
- Actualizar `TODO.md` si el cambio abre, cierra o modifica tareas.
|
||||||
|
- Actualizar `README.md`, `INSTALL.md` o los documentos que correspondan si
|
||||||
|
cambia el comportamiento, la instalación o el uso.
|
||||||
|
- Crear **un commit de git** con mensaje claro en imperativo.
|
||||||
|
2. **Nunca dejar documentación desfasada.** Si el código y los documentos no
|
||||||
|
coinciden, el cambio está incompleto.
|
||||||
|
3. **No commitear** secretos, binarios, artefactos de build, logs ni dependencias
|
||||||
|
descargadas (`.gitignore` cubre lo básico; amplíalo según el stack).
|
||||||
|
4. **Idioma: español** para documentación, mensajes de commit y comentarios.
|
||||||
|
|
||||||
|
## Verificación antes de commitear
|
||||||
|
|
||||||
|
PENDIENTE: sustituir por los comandos reales del stack (formato, tipos, tests,
|
||||||
|
lint). Ningún commit sin verificación en verde.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ejemplo
|
||||||
|
# make check
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flujo de trabajo
|
||||||
|
|
||||||
|
1. Editar los ficheros necesarios.
|
||||||
|
2. Ejecutar las verificaciones anteriores.
|
||||||
|
3. Actualizar `CHANGELOG.md`, `TODO.md` y la documentación afectada.
|
||||||
|
4. `git add -A && git commit -m "tipo(alcance): descripción breve"`.
|
||||||
|
5. Informar del cambio y del hash del commit.
|
||||||
|
|
||||||
|
## Convención de mensajes de commit
|
||||||
|
|
||||||
|
`tipo(alcance): resumen` — tipos: `feat`, `fix`, `docs`, `chore`, `refactor`,
|
||||||
|
`test`, `build`, `perf`.
|
||||||
|
|
||||||
|
Ejemplos:
|
||||||
|
- `docs: documentar instalación y puesta en marcha`
|
||||||
|
- `feat(api): añadir búsqueda paginada`
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
Todos los cambios relevantes de este proyecto se documentan en este fichero.
|
||||||
|
|
||||||
|
El formato sigue [*Keep a Changelog*](https://keepachangelog.com/es-ES/1.1.0/)
|
||||||
|
y el proyecto usa [Versionado Semántico](https://semver.org/lang/es/).
|
||||||
|
|
||||||
|
## [No publicado]
|
||||||
|
|
||||||
|
### Añadido
|
||||||
|
|
||||||
|
- Base documental inicial del proyecto ({{FECHA}}): `AGENTS.md`, `README.md`,
|
||||||
|
`INSTALL.md`, `CHANGELOG.md`, `TODO.md` y `.gitignore`.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Plantilla de entrada:
|
||||||
|
|
||||||
|
## [0.1.0] - AAAA-MM-DD
|
||||||
|
|
||||||
|
### Añadido
|
||||||
|
### Cambiado
|
||||||
|
### Corregido
|
||||||
|
### Eliminado
|
||||||
|
-->
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# INSTALL — {{PROYECTO}}
|
||||||
|
|
||||||
|
Instalación, configuración y puesta en marcha de **{{PROYECTO}}**.
|
||||||
|
|
||||||
|
{{DESCRIPCION}}
|
||||||
|
|
||||||
|
## 1. Requisitos
|
||||||
|
|
||||||
|
PENDIENTE: completar con el stack real.
|
||||||
|
|
||||||
|
| Componente | Versión mínima | Notas |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Sistema operativo | PENDIENTE | |
|
||||||
|
| Lenguaje / runtime | PENDIENTE | |
|
||||||
|
| Gestor de paquetes | PENDIENTE | |
|
||||||
|
| Otros | PENDIENTE | |
|
||||||
|
|
||||||
|
Comprueba lo instalado:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PENDIENTE: comandos de comprobación (p. ej. python3 --version)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Obtener el código
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <url-del-repositorio>
|
||||||
|
cd {{PROYECTO}}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Dependencias
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PENDIENTE: instalación de dependencias
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Configuración
|
||||||
|
|
||||||
|
PENDIENTE: variables de entorno, ficheros de configuración y secretos. Indica
|
||||||
|
qué ficheros hay que crear y de dónde copiarlos (`.env.example`, etc.).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PENDIENTE: cp .env.example .env y editar
|
||||||
|
```
|
||||||
|
|
||||||
|
| Variable | Obligatoria | Descripción |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| PENDIENTE | | |
|
||||||
|
|
||||||
|
## 5. Verificación de la instalación
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PENDIENTE: comando de humo que demuestre que funciona
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Arranque
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PENDIENTE: comando de arranque en desarrollo y en producción
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. Actualización
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pull
|
||||||
|
# PENDIENTE: reinstalar dependencias y aplicar migraciones si las hay
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. Desinstalación
|
||||||
|
|
||||||
|
PENDIENTE: qué borrar y qué dejar.
|
||||||
|
|
||||||
|
## 9. Resolución de problemas
|
||||||
|
|
||||||
|
| Síntoma | Causa probable | Solución |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| PENDIENTE | | |
|
||||||
|
|
||||||
|
Documento creado el {{FECHA}} por {{AUTOR}}.
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# {{PROYECTO}}
|
||||||
|
|
||||||
|
{{DESCRIPCION}}
|
||||||
|
|
||||||
|
## Estado
|
||||||
|
|
||||||
|
- Versión: `0.1.0`
|
||||||
|
- Fecha de creación: {{FECHA}}
|
||||||
|
- Autor: {{AUTOR}}
|
||||||
|
- Estado: en desarrollo
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
PENDIENTE: lenguajes, versiones y dependencias del sistema. Ver `INSTALL.md`.
|
||||||
|
|
||||||
|
## Instalación rápida
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PENDIENTE: sustituir por los comandos reales
|
||||||
|
git clone <url-del-repositorio>
|
||||||
|
cd {{PROYECTO}}
|
||||||
|
```
|
||||||
|
|
||||||
|
Instrucciones completas en [`INSTALL.md`](INSTALL.md).
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
PENDIENTE: ejemplo mínimo de uso o de arranque.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PENDIENTE
|
||||||
|
```
|
||||||
|
|
||||||
|
## Estructura
|
||||||
|
|
||||||
|
```text
|
||||||
|
{{PROYECTO}}/
|
||||||
|
├── AGENTS.md # reglas de trabajo para agentes y colaboradores
|
||||||
|
├── README.md # este documento
|
||||||
|
├── INSTALL.md # instalación y dependencias
|
||||||
|
├── CHANGELOG.md # historial de cambios
|
||||||
|
├── TODO.md # tareas pendientes
|
||||||
|
└── .pi/
|
||||||
|
└── settings.json # modelo por defecto de pi (cambiar con /modelo-proyecto)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentación
|
||||||
|
|
||||||
|
| Documento | Contenido |
|
||||||
|
| --- | --- |
|
||||||
|
| [`AGENTS.md`](AGENTS.md) | Reglas, flujo de trabajo y convenciones. |
|
||||||
|
| [`INSTALL.md`](INSTALL.md) | Instalación, configuración y desinstalación. |
|
||||||
|
| [`CHANGELOG.md`](CHANGELOG.md) | Qué cambió y cuándo. |
|
||||||
|
| [`TODO.md`](TODO.md) | Qué falta y qué está en curso. |
|
||||||
|
|
||||||
|
## Licencia
|
||||||
|
|
||||||
|
PENDIENTE: indicar licencia del proyecto.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# TODO — {{PROYECTO}}
|
||||||
|
|
||||||
|
Tareas pendientes y deuda técnica. Al cerrar una tarea, muévela a *Hecho* y
|
||||||
|
anota el cambio en `CHANGELOG.md`.
|
||||||
|
|
||||||
|
## En curso
|
||||||
|
|
||||||
|
- [ ] _(nada en curso)_
|
||||||
|
|
||||||
|
## Pendiente
|
||||||
|
|
||||||
|
- [ ] Definir las **reglas de modelo** del proyecto en `AGENTS.md` (criterio por
|
||||||
|
tarea; el modelo por defecto se cambia con `/modelo-proyecto`).
|
||||||
|
- [ ] Definir las **reglas de funcionamiento** del proyecto en `AGENTS.md`.
|
||||||
|
- [ ] Completar los `PENDIENTE` de `README.md` e `INSTALL.md`.
|
||||||
|
- [ ] Fijar los comandos de verificación reales en `AGENTS.md`.
|
||||||
|
- [ ] Elegir licencia.
|
||||||
|
|
||||||
|
## Hecho
|
||||||
|
|
||||||
|
- [x] {{FECHA}} — base documental inicial (`AGENTS.md`, `README.md`, `INSTALL.md`,
|
||||||
|
`CHANGELOG.md`, `TODO.md`, `.gitignore`).
|
||||||
Reference in new issue
Block a user