@icarusmx/creta 1.5.4 → 1.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/creta.js +44 -3
- package/lib/aws-guide-viewer.js +179 -0
- package/lib/builders/MenuBuilder.js +23 -4
- package/lib/executors/ExercisesExecutor.js +8 -0
- package/lib/exercises/array-object-manipulation.md +1281 -0
- package/lib/exercises/aws-billing-detective.md +588 -0
- package/lib/exercises/git-stash-workflow.md +426 -0
- package/lib/exercises/iterm2-pane-navigation.md +504 -0
- package/lib/exercises/railway-deployment.md +1185 -0
- package/lib/papers/bitcoin/bitcoin.md +92 -0
- package/lib/papers/mapreduce/mapreduce.md +476 -0
- package/lib/papers/spark/spark.md +49 -0
- package/lib/vim-setup-tutorial.js +367 -0
- package/package.json +5 -1
- package/ascii-logo.txt +0 -8
- package/codex-refactor.txt +0 -13
- package/docs/diagrams/README.md +0 -131
- package/docs/diagrams/architecture-overview.mmd +0 -71
- package/docs/diagrams/architecture.svg +0 -1
- package/docs/diagrams/ecosystem-integration.mmd +0 -49
- package/docs/diagrams/evolution-phases.mmd +0 -49
- package/docs/diagrams/output.svg +0 -1
- package/docs/diagrams/phase2-command-help-flow.mmd +0 -51
- package/docs/diagrams/user-journey.mmd +0 -78
- package/ejemplo.sh +0 -3
- package/refactor.txt +0 -581
- package/templates/sveltekit-portfolio/package.json +0 -20
- package/templates/sveltekit-portfolio/src/app.css +0 -51
- package/templates/sveltekit-portfolio/src/app.html +0 -12
- package/templates/sveltekit-portfolio/src/routes/+layout.svelte +0 -108
- package/templates/sveltekit-portfolio/src/routes/+page.svelte +0 -79
- package/templates/sveltekit-portfolio/static/favicon.png +0 -0
- package/templates/sveltekit-portfolio/svelte.config.js +0 -10
- package/templates/sveltekit-portfolio/vite.config.js +0 -10
- package/test/enunciados.test.js +0 -72
- package/test/sintaxis-menu.test.js +0 -45
- package/wea-fome-qlia.sh +0 -92
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
RETO CRETA: PORTFOLIO PERSONAL
|
|
3
|
-
===============================
|
|
4
|
-
|
|
5
|
-
¡Hola {{STUDENT_NAME}}! 👋
|
|
6
|
-
|
|
7
|
-
Este es tu proyecto base para crear un portfolio personal.
|
|
8
|
-
Necesitas completar 3 secciones principales:
|
|
9
|
-
|
|
10
|
-
1. 🧭 NAVBAR (Barra de navegación)
|
|
11
|
-
2. 🌟 HERO (Sección principal)
|
|
12
|
-
3. 🦶 FOOTER (Pie de página)
|
|
13
|
-
|
|
14
|
-
Cada sección tiene comentarios que te guían sobre qué hacer.
|
|
15
|
-
|
|
16
|
-
COMANDOS ÚTILES:
|
|
17
|
-
- npm run dev (inicia el servidor de desarrollo)
|
|
18
|
-
- Ctrl+C (para parar el servidor)
|
|
19
|
-
|
|
20
|
-
¡Manos a la obra! 🚀
|
|
21
|
-
-->
|
|
22
|
-
|
|
23
|
-
<script>
|
|
24
|
-
import '../app.css'
|
|
25
|
-
let { children } = $props();
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<!--
|
|
29
|
-
🧭 RETO 1: NAVBAR
|
|
30
|
-
==================
|
|
31
|
-
|
|
32
|
-
Crea una barra de navegación que incluya:
|
|
33
|
-
- Logo o nombre (lado izquierdo)
|
|
34
|
-
- Menú de navegación (lado derecho)
|
|
35
|
-
* Inicio
|
|
36
|
-
* Sobre mí
|
|
37
|
-
* Proyectos
|
|
38
|
-
* Contacto
|
|
39
|
-
|
|
40
|
-
TIPS DE TAILWIND:
|
|
41
|
-
- Usa 'flex justify-between items-center' para distribuir elementos
|
|
42
|
-
- Usa 'bg-white shadow-sm' para fondo y sombra sutil
|
|
43
|
-
- Usa 'px-4 py-3' para espaciado interno
|
|
44
|
-
- Usa 'hover:text-blue-600' para efectos hover
|
|
45
|
-
|
|
46
|
-
ESTRUCTURA SUGERIDA:
|
|
47
|
-
```html
|
|
48
|
-
<nav class="bg-white shadow-sm">
|
|
49
|
-
<div class="max-w-7xl mx-auto px-4">
|
|
50
|
-
<div class="flex justify-between items-center py-3">
|
|
51
|
-
<div class="flex items-center space-x-3">
|
|
52
|
-
<img src="https://icarus.mx/logo.png" alt="Logo" class="w-8 h-8">
|
|
53
|
-
<span class="text-xl font-bold text-gray-900">{{STUDENT_NAME}}</span>
|
|
54
|
-
</div>
|
|
55
|
-
<div class="hidden md:flex space-x-6">
|
|
56
|
-
<a href="#inicio">Inicio</a>
|
|
57
|
-
<a href="#sobre-mi">Sobre mí</a>
|
|
58
|
-
<a href="#proyectos">Proyectos</a>
|
|
59
|
-
<a href="#contacto">Contacto</a>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
</nav>
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
PERSONALIZACIÓN DEL LOGO:
|
|
67
|
-
- Reemplaza /logo.png con tu propio logo
|
|
68
|
-
- El logo debe ser preferiblemente de 32x32px o similar
|
|
69
|
-
- Formatos recomendados: PNG, SVG, JPG
|
|
70
|
-
-->
|
|
71
|
-
|
|
72
|
-
<nav class="bg-white shadow-sm">
|
|
73
|
-
<!-- ⚠️ COMPLETA AQUÍ LA NAVEGACIÓN -->
|
|
74
|
-
</nav>
|
|
75
|
-
|
|
76
|
-
<main>
|
|
77
|
-
{@render children?.()}
|
|
78
|
-
</main>
|
|
79
|
-
|
|
80
|
-
<!--
|
|
81
|
-
🦶 RETO 3: FOOTER
|
|
82
|
-
==================
|
|
83
|
-
|
|
84
|
-
Crea un pie de página simple que incluya:
|
|
85
|
-
- Tu nombre y año actual
|
|
86
|
-
- Links a redes sociales (opcional)
|
|
87
|
-
- Mensaje "Hecho con ❤️ en Creta"
|
|
88
|
-
|
|
89
|
-
TIPS DE TAILWIND:
|
|
90
|
-
- Usa 'bg-gray-50 border-t' para fondo y borde superior
|
|
91
|
-
- Usa 'py-8 px-4' para espaciado
|
|
92
|
-
- Usa 'text-center text-gray-600 text-sm' para texto centrado y gris
|
|
93
|
-
|
|
94
|
-
ESTRUCTURA SUGERIDA:
|
|
95
|
-
```html
|
|
96
|
-
<footer class="bg-gray-50 border-t">
|
|
97
|
-
<div class="max-w-7xl mx-auto py-8 px-4">
|
|
98
|
-
<div class="text-center text-gray-600 text-sm">
|
|
99
|
-
[Tu contenido aquí]
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
</footer>
|
|
103
|
-
```
|
|
104
|
-
-->
|
|
105
|
-
|
|
106
|
-
<footer class="bg-gray-50 border-t">
|
|
107
|
-
<!-- ⚠️ COMPLETA AQUÍ EL FOOTER -->
|
|
108
|
-
</footer>
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
🌟 RETO CRETA: PORTAFOLIO PERSONAL
|
|
3
|
-
==================================
|
|
4
|
-
|
|
5
|
-
¡Bienvenido de vuelta! Es hora de crear tu portafolio personal.
|
|
6
|
-
Este proyecto incluye varios retos que puedes completar paso a paso:
|
|
7
|
-
|
|
8
|
-
🧭 RETO 1: NAVBAR (archivo +layout.svelte)
|
|
9
|
-
- Crear la navegación principal
|
|
10
|
-
- Incluir tu logo y enlaces a las secciones
|
|
11
|
-
|
|
12
|
-
🎯 RETO 2: HERO SECTION (esta sección)
|
|
13
|
-
- Crear la sección principal de tu portfolio
|
|
14
|
-
- Incluir tu nombre como título principal
|
|
15
|
-
- Una descripción breve de quién eres
|
|
16
|
-
- Un botón de llamada a la acción
|
|
17
|
-
|
|
18
|
-
📝 RETO 3: SOBRE MÍ
|
|
19
|
-
- Sección con información personal
|
|
20
|
-
- Tu foto o avatar
|
|
21
|
-
- Habilidades y experiencia
|
|
22
|
-
|
|
23
|
-
🚀 RETO 4: PROYECTOS
|
|
24
|
-
- Muestra tus mejores proyectos
|
|
25
|
-
- Incluye imágenes, descripciones y enlaces
|
|
26
|
-
|
|
27
|
-
📧 RETO 5: CONTACTO
|
|
28
|
-
- Formulario de contacto
|
|
29
|
-
- Información de contacto
|
|
30
|
-
- Enlaces a redes sociales
|
|
31
|
-
|
|
32
|
-
💡 Si te quedas atascado, puedes usar:
|
|
33
|
-
- creta portafolio-1 (para desbloquear navbar)
|
|
34
|
-
- creta portafolio-2 (para desbloquear navbar + hero)
|
|
35
|
-
- creta portafolio-3 (para la solución completa)
|
|
36
|
-
|
|
37
|
-
TIPS DE TAILWIND para la HERO SECTION:
|
|
38
|
-
- Usa 'min-h-screen flex items-center justify-center' para centrar verticalmente
|
|
39
|
-
- Usa 'text-4xl md:text-6xl font-bold' para títulos grandes y responsivos
|
|
40
|
-
- Usa 'text-lg text-gray-600 mb-8' para descripciones
|
|
41
|
-
- Usa 'bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg' para botones
|
|
42
|
-
|
|
43
|
-
ESTRUCTURA SUGERIDA PARA HERO:
|
|
44
|
-
```html
|
|
45
|
-
<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
|
|
46
|
-
<div class="max-w-4xl mx-auto px-4 text-center">
|
|
47
|
-
<h1 class="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
|
|
48
|
-
Hola, soy [Tu Nombre]
|
|
49
|
-
</h1>
|
|
50
|
-
<p class="text-lg text-gray-600 mb-8">
|
|
51
|
-
[Tu descripción aquí]
|
|
52
|
-
</p>
|
|
53
|
-
<a href="#contacto" class="bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg">
|
|
54
|
-
Contáctame
|
|
55
|
-
</a>
|
|
56
|
-
</div>
|
|
57
|
-
</section>
|
|
58
|
-
```
|
|
59
|
-
-->
|
|
60
|
-
|
|
61
|
-
<svelte:head>
|
|
62
|
-
<title>{{STUDENT_NAME}} - Portafolio</title>
|
|
63
|
-
<meta name="description" content="Portafolio personal de {{STUDENT_NAME}}" />
|
|
64
|
-
</svelte:head>
|
|
65
|
-
|
|
66
|
-
<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
|
|
67
|
-
<!-- ⚠️ COMPLETA AQUÍ LA SECCIÓN HERO -->
|
|
68
|
-
<div class="max-w-4xl mx-auto px-4 text-center">
|
|
69
|
-
<h1 class="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
|
|
70
|
-
Gracias por seguir aquí
|
|
71
|
-
</h1>
|
|
72
|
-
<p class="text-lg text-gray-600 mb-8">
|
|
73
|
-
Abre el proyecto usando <code>code .</code> y sigue las instrucciones. Si tienes dudas, apóyate en el equipo
|
|
74
|
-
</p>
|
|
75
|
-
</div>
|
|
76
|
-
</section>
|
|
77
|
-
|
|
78
|
-
<!-- ⚠️ AQUÍ VAN LAS DEMÁS SECCIONES (SOBRE MÍ, PROYECTOS, CONTACTO) -->
|
|
79
|
-
<!-- Revisa los comentarios arriba para saber qué crear -->
|
|
Binary file
|
package/test/enunciados.test.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict'
|
|
2
|
-
import test from 'node:test'
|
|
3
|
-
import { mock } from 'node:test'
|
|
4
|
-
|
|
5
|
-
import { ENUNCIADOS } from '../lib/data/enunciados.js'
|
|
6
|
-
import { LESSONS_BY_ID } from '../lib/data/lessons/index.js'
|
|
7
|
-
import { executeEnunciados } from '../lib/executors/enunciados-executor.js'
|
|
8
|
-
|
|
9
|
-
const noop = () => {}
|
|
10
|
-
|
|
11
|
-
test('cada enunciado tiene una lección disponible', () => {
|
|
12
|
-
for (const enunciado of ENUNCIADOS) {
|
|
13
|
-
assert.ok(
|
|
14
|
-
LESSONS_BY_ID.get(enunciado.id),
|
|
15
|
-
`Falta la lección para el enunciado ${enunciado.id}`
|
|
16
|
-
)
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test('executeEnunciados ejecuta la lección seleccionada', async () => {
|
|
21
|
-
const selectedEnunciado = ENUNCIADOS[0]
|
|
22
|
-
const menuResponses = [
|
|
23
|
-
{ id: selectedEnunciado.id, data: selectedEnunciado },
|
|
24
|
-
null
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
const capturedLessons = []
|
|
28
|
-
const capturedWaits = []
|
|
29
|
-
|
|
30
|
-
class StubLessonBuilder {
|
|
31
|
-
constructor(lesson) {
|
|
32
|
-
this.lesson = lesson
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async start() {
|
|
36
|
-
capturedLessons.push(this.lesson)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const fakeMenu = {
|
|
41
|
-
async show() {
|
|
42
|
-
return menuResponses.shift() || null
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const fakeDelay = (fn) => {
|
|
47
|
-
if (typeof fn === 'function') {
|
|
48
|
-
fn()
|
|
49
|
-
}
|
|
50
|
-
return 0
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const fakeWait = async (message) => {
|
|
54
|
-
capturedWaits.push(message)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const consoleLogMock = mock.method(console, 'log', noop)
|
|
58
|
-
try {
|
|
59
|
-
await executeEnunciados({
|
|
60
|
-
menu: fakeMenu,
|
|
61
|
-
lessonBuilder: StubLessonBuilder,
|
|
62
|
-
waitForEnter: fakeWait,
|
|
63
|
-
delay: fakeDelay
|
|
64
|
-
})
|
|
65
|
-
} finally {
|
|
66
|
-
consoleLogMock.mock.restore()
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
assert.equal(capturedLessons.length, 1)
|
|
70
|
-
assert.equal(capturedLessons[0].id, selectedEnunciado.id)
|
|
71
|
-
assert.deepEqual(capturedWaits, ['\nPresiona Enter para regresar al menú de enunciados...'])
|
|
72
|
-
})
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict'
|
|
2
|
-
import test from 'node:test'
|
|
3
|
-
|
|
4
|
-
import { getSintaxisMenuConfig, getMainMenuConfig } from '../lib/data/menus.js'
|
|
5
|
-
|
|
6
|
-
const baseState = {
|
|
7
|
-
lessonsCompleted: []
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
test('sintaxis menu shows only terminal básico for new users', () => {
|
|
11
|
-
const menu = getSintaxisMenuConfig(baseState)
|
|
12
|
-
assert.equal(menu.options.length, 1)
|
|
13
|
-
assert.equal(menu.options[0].id, 'terminal-basico')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
test('sintaxis menu unlocks git básico after completing terminal básico', () => {
|
|
17
|
-
const state = {
|
|
18
|
-
lessonsCompleted: [{ id: 'terminal-basico' }]
|
|
19
|
-
}
|
|
20
|
-
const menu = getSintaxisMenuConfig(state)
|
|
21
|
-
assert.equal(menu.options.length, 2)
|
|
22
|
-
assert.deepEqual(menu.options.map(option => option.id), ['terminal-basico', 'git-basico'])
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test('sintaxis menu unlocks bash scripts after completing git básico', () => {
|
|
26
|
-
const state = {
|
|
27
|
-
lessonsCompleted: [
|
|
28
|
-
{ id: 'terminal-basico' },
|
|
29
|
-
{ id: 'git-basico' }
|
|
30
|
-
]
|
|
31
|
-
}
|
|
32
|
-
const menu = getSintaxisMenuConfig(state)
|
|
33
|
-
assert.equal(menu.options.length, 3)
|
|
34
|
-
assert.deepEqual(menu.options.map(option => option.id), ['terminal-basico', 'git-basico', 'bash-scripts'])
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
test('main menu title changes when only one option is available', () => {
|
|
38
|
-
const config = getMainMenuConfig({ lessonsCompleted: [] })
|
|
39
|
-
assert.equal(config.title, 'Empecemos por aquí:')
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test('main menu title defaults once multiple options unlock', () => {
|
|
43
|
-
const config = getMainMenuConfig({ lessonsCompleted: [{ id: 'terminal-basico' }] })
|
|
44
|
-
assert.equal(config.title, 'Te ofrecemos las siguientes opciones:')
|
|
45
|
-
})
|
package/wea-fome-qlia.sh
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Summarize a repository's architecture via codex using lightweight bash reconnaissance.
|
|
3
|
-
set -euo pipefail
|
|
4
|
-
|
|
5
|
-
show_help() {
|
|
6
|
-
cat <<'USAGE'
|
|
7
|
-
Usage: wea-fome-qlia.sh [path-to-repo]
|
|
8
|
-
|
|
9
|
-
Collects structural signals from the repository using basic shell commands
|
|
10
|
-
and streams them into `codex -p` to obtain a five-sentence architecture summary.
|
|
11
|
-
Set the SUMMARIZER_PROMPT environment variable to override the default prompt.
|
|
12
|
-
USAGE
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if [[ ${1:-} == "-h" || ${1:-} == "--help" ]]; then
|
|
16
|
-
show_help
|
|
17
|
-
exit 0
|
|
18
|
-
fi
|
|
19
|
-
|
|
20
|
-
if (( $# > 1 )); then
|
|
21
|
-
echo "Only zero or one path argument is supported." >&2
|
|
22
|
-
exit 1
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
REPO_DIR=${1:-.}
|
|
26
|
-
if [[ ! -d "$REPO_DIR" ]]; then
|
|
27
|
-
echo "The path '$REPO_DIR' is not a directory." >&2
|
|
28
|
-
exit 1
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
if [[ -z ${BASH_VERSION:-} ]]; then
|
|
32
|
-
echo "This script requires bash. Run it as './wea-fome-qlia.sh' or 'bash wea-fome-qlia.sh'." >&2
|
|
33
|
-
exit 1
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
if ! command -v codex >/dev/null 2>&1; then
|
|
37
|
-
echo "The 'codex' CLI is required but was not found in PATH." >&2
|
|
38
|
-
exit 1
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
REPO_DIR=$(cd "$REPO_DIR" && pwd)
|
|
42
|
-
TEMP_INPUT=$(mktemp)
|
|
43
|
-
trap 'rm -f "$TEMP_INPUT"' EXIT
|
|
44
|
-
|
|
45
|
-
MAX_DIRS=8
|
|
46
|
-
MAX_ITEMS=12
|
|
47
|
-
PROMPT=${SUMMARIZER_PROMPT:-"You are a senior software architect. Using the repository signals provided, write exactly five sentences that explain the current architecture, main modules, dominant technologies, notable build or tooling traits, and any potential work-in-progress areas."}
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
echo "Repository: $REPO_DIR"
|
|
51
|
-
echo
|
|
52
|
-
echo "Top-level entries (ls):"
|
|
53
|
-
ls -1A "$REPO_DIR" | sed 's/^/ - /'
|
|
54
|
-
|
|
55
|
-
echo
|
|
56
|
-
echo "Directory snapshots:"
|
|
57
|
-
dir_count=0
|
|
58
|
-
while IFS= read -r entry; do
|
|
59
|
-
[[ -z "$entry" ]] && continue
|
|
60
|
-
path="$REPO_DIR/$entry"
|
|
61
|
-
if [[ -d "$path" ]]; then
|
|
62
|
-
((dir_count++))
|
|
63
|
-
echo "* $entry"
|
|
64
|
-
ls -1A "$path" | head -n "$MAX_ITEMS" | sed 's/^/ /'
|
|
65
|
-
if command -v git >/dev/null 2>&1; then
|
|
66
|
-
echo " (files: $(ls -1A "$path" | wc -l | tr -d ' '))"
|
|
67
|
-
fi
|
|
68
|
-
echo
|
|
69
|
-
fi
|
|
70
|
-
if (( dir_count >= MAX_DIRS )); then
|
|
71
|
-
break
|
|
72
|
-
fi
|
|
73
|
-
done <<EOF
|
|
74
|
-
$(ls -1A "$REPO_DIR")
|
|
75
|
-
EOF
|
|
76
|
-
|
|
77
|
-
if command -v git >/dev/null 2>&1 && git -C "$REPO_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
78
|
-
echo "Git status:"
|
|
79
|
-
git -C "$REPO_DIR" status -sb
|
|
80
|
-
|
|
81
|
-
echo
|
|
82
|
-
echo "Recent commits:"
|
|
83
|
-
git -C "$REPO_DIR" log -5 --oneline
|
|
84
|
-
fi
|
|
85
|
-
} > "$TEMP_INPUT"
|
|
86
|
-
|
|
87
|
-
{
|
|
88
|
-
printf '%s\n\n' "$PROMPT"
|
|
89
|
-
echo '--- Repository signals start ---'
|
|
90
|
-
cat "$TEMP_INPUT"
|
|
91
|
-
echo '--- Repository signals end ---'
|
|
92
|
-
} | codex exec -
|