МОСТ
Платформа Challenge Hub: бизнес описывает проблему, AI задаёт уточняющие вопросы и генерирует редактируемую карточку задачи с рейтингом готовности…
О проекте
Команда: shmaloogles
Кейс HackAlem.ai: Образование — AI Sana
Стадия: Рабочий MVP
Задача кейса: Challenge Hub: превратить задачу бизнеса в задание для студенческих команд
Суть
Платформа Challenge Hub: бизнес описывает проблему, AI задаёт уточняющие вопросы и генерирует редактируемую карточку задачи с рейтингом готовности, задача публикуется в каталоге, студенческие команды откликаются, бизнес принимает решения.
Как устроено
Бэкенд на Go (REST, pgx, PostgreSQL 16) ведёт жизненный цикл задачи draft → confirmed → published. AI-модуль на OpenAI Responses API со strict structured output (по умолчанию gpt-4.1-mini, есть mock и явный fallback) по промптам clarify и generate уточняет описание и заполняет карточку. Рейтинг готовности считает детерминированный Go-код по заполненности полей (контекст, данные, результат, критерии успеха и др., максимум 100) с уровнями Draft, Workable, Ready и Priority. Фронтенд на Nuxt 4 и Vue 3 содержит каталог с фильтрами, формы, отклики и переключатель ролей.
Ключевые решения
- structured outputs
- deterministic readiness scoring
- clarification dialogue
- mock/fallback AI provider
Особенности
Рейтинг готовности считает прозрачная формула по заполненности полей, без LLM. README прямо говорит, что рейтинг измеряет полноту, а не качество. В ответе явно указан режим AI (provider, mock или fallback).
Стек
Go · PostgreSQL 16 · pgx · Nuxt 4 · Vue 3 · TypeScript · Docker Compose · GitHub Actions · Nix
Модели
gpt-4.1-mini · OpenAI Responses API
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-b70aa203-shmaloogles.
README
README.mdМОСТ
Платформа, которая помогает бизнесу превратить описание проблемы в понятную задачу, а студенческим командам — предложить решение.
Сценарий: описание → уточняющие вопросы → редактируемая карточка → рейтинг готовности → подтверждение → публикация → отклик → решение бизнеса.
Хакатонный MVP. Роли переключаются без регистрации; это демонстрационный режим, а не система разграничения доступа.
Быстрый запуск
Нужны Git, Docker Engine с Compose v2 либо Docker Desktop. Для сборки образов нужен доступ к реестрам образов и пакетам. Доступ к приватному репозиторию должен быть настроен отдельно.
git clone https://github.com/BAITC-Hacks/hack-b70aa203-shmaloogles.git
cd hack-b70aa203-shmaloogles
cp .env.example .env
docker compose up -d --build
docker compose ps
| Сервис | Адрес по умолчанию |
|---|---|
| Приложение | http://localhost:3000 |
| REST API | http://localhost:8080/api |
| Проверка API и подключения к БД | http://localhost:8080/health |
| PostgreSQL | localhost:5432 |
При первом запуске пустой БД автоматически выполняются SQL-схема и демоданные из backend/db/. Данные сохраняются в Docker volume postgres_data.
По умолчанию включён mock AI: ключ не нужен, но ответы заглушки не доказывают качество реальной модели.
curl -fsS http://localhost:8080/health
# {"status":"healthy"}
curl -fsS 'http://localhost:8080/api/tasks?sort=readiness_desc'
curl -fsS http://localhost:8080/api/teams
Настройки
Compose читает корневой .env. Не добавляйте его и API-ключи в Git.
| Переменная | По умолчанию | Назначение |
|---|---|---|
FRONTEND_PORT | 3000 | Порт интерфейса на хосте |
API_PORT | 8080 | Порт API на хосте |
POSTGRES_PORT | 5432 | Порт БД на хосте |
POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD | shmaloogles | Параметры первоначального создания БД |
NUXT_PUBLIC_API_BASE | http://localhost:8080 | Адрес API, доступный браузеру; без завершающего / |
CORS_ORIGIN | http://localhost:3000 | Точный origin интерфейса: схема, хост и порт |
AI_MODE | mock | mock или openai |
OPENAI_API_KEY | пусто | Ключ провайдера для режима openai |
AI_MODEL | gpt-4.1-mini | Модель, настроенная в Compose |
AI_BASE_URL | https://api.openai.com/v1 | Базовый адрес провайдера; при необходимости добавьте в .env |
AI_TIMEOUT | 20s | Таймаут AI-запроса |
AI_FALLBACK | false | Разрешить переход на заглушку при ошибке реального AI |
DATABASE_URL | см. .env.example | Подключение при локальном запуске Go; Compose собирает свой URL из POSTGRES_* |
В Compose внутренний адрес API для Nuxt задан как NUXT_API_BASE=http://api:8080. Браузер использует отдельный NUXT_PUBLIC_API_BASE: имя контейнера api ему недоступно.
Для реального AI измените .env:
AI_MODE=openai
OPENAI_API_KEY=replace-with-your-key
AI_MODEL=gpt-4.1-mini
AI_FALLBACK=false
Примените настройки:
docker compose up -d
AI возвращает режим provider, mock или fallback. При разрешённом fallback ошибка провайдера может завершиться успешным ответом заглушки — учитывайте это на демонстрации. Промпты, контракты и обработка ошибок описаны в AI_SCORING.md.
Развёртывание на сервере
Существующие Dockerfile собирают Go-бинарник и production-сборку Nuxt. Compose запускает три сервиса: frontend, api, postgres, с проверками готовности API/БД и политикой restart: unless-stopped.
Закрытый демостенд
На сервере выполните быстрый запуск. Если открываете интерфейс непосредственно по IP сервера, задайте в его .env реальные адреса, например:
NUXT_PUBLIC_API_BASE=http://192.168.1.50:8080
CORS_ORIGIN=http://192.168.1.50:3000
После docker compose up -d открывайте http://192.168.1.50:3000. Замените пример на IP своего сервера. При изменении портов обновите и оба URL. localhost в браузере посетителя означает компьютер посетителя, а не сервер.
Для доступа через SSH-туннель можно оставить исходные URL. На своём компьютере выполните:
ssh -N -L 3000:127.0.0.1:3000 -L 8080:127.0.0.1:8080 user@server
Откройте http://localhost:3000. Сам туннель не закрывает опубликованные Docker-порты на сервере.
Перед публикацией в интернете
Текущий Compose — демонстрационная конфигурация: порты по умолчанию публикуются на всех интерфейсах, у API нет авторизации. Переключатель ролей не защищает операции записи.
- Ограничьте доступ к демостенду VPN, SSH или авторизацией на reverse proxy.
- Уберите внешнюю публикацию PostgreSQL. Для proxy на хосте привяжите порты frontend/API к
127.0.0.1в Compose. - Настройте HTTPS на reverse proxy; HTTPS-интерфейс должен обращаться к HTTPS API.
- Укажите публичный адрес API в
NUXT_PUBLIC_API_BASE, адрес интерфейса — вCORS_ORIGIN. - Замените демонстрационный пароль БД до её первого запуска. В текущем Compose пароль включается в URL, поэтому используйте URL-безопасное значение.
TLS, домен и авторизация на proxy в репозитории не настроены. Это необходимые отдельные шаги для внешнего стенда, а не готовые возможности Compose.
Обслуживание и данные
# Последние сообщения сервисов
docker compose logs --tail=100 api frontend postgres
# Следить за API
docker compose logs -f api
# Остановка с сохранением БД
docker compose down
# Пересборка после обновления исходников
docker compose up -d --build
Скрипты docker-entrypoint-initdb.d выполняются только на пустой БД. Пересборка контейнеров не применяет новые миграции к существующему volume. Изменение POSTGRES_PASSWORD в .env также не меняет пароль уже созданного пользователя.
Резервная копия из запущенного контейнера, команда выполняется из корня проекта:
docker compose exec -T postgres sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > most-backup.dump
Проверка читаемости архива:
docker compose exec -T postgres pg_restore --list < most-backup.dump
Храните копию отдельно от сервера. Проверка списка не заменяет пробное восстановление в отдельную БД.
Полный сброс только для ненужных демоданных:
# Удаляет volume и все данные проекта в нём
docker compose down -v
docker compose up -d --build
Локальная разработка
Для работы без контейнеров приложения: Go 1.22+, Node.js 22 и npm; PostgreSQL 16 можно оставить в Docker. Команды ниже предполагают стандартные порты и учётные данные из .env.example.
docker compose up -d postgres
Backend в отдельном терминале:
cd backend
export DATABASE_URL='postgres://shmaloogles:shmaloogles@localhost:5432/shmaloogles?sslmode=disable'
export CORS_ORIGIN='http://localhost:3000'
export AI_MODE=mock
go run ./cmd/api
Go-сервер читает переменные окружения, но сам не загружает корневой .env. При необходимости экспортируйте параметры реального AI. PORT задаёт порт локального Go-сервера; API_PORT используется Compose.
Frontend в другом терминале:
cd frontend
npm ci
npm run dev
Не запускайте контейнерные api/frontend одновременно с локальными процессами на тех же портах.
Проверки
Backend:
cd backend
test -z "$(gofmt -l .)"
go test ./... -count=1
go vet ./...
go build ./...
Для PostgreSQL-интеграционных тестов задайте AI_TEST_DATABASE_URL, указывающий на отдельную тестовую БД, предварительно применив к ней backend/db/migrations/000001_init.up.sql и backend/db/seed.sql. Без этой переменной проверки, зависящие от БД, могут быть пропущены. Готовая последовательность есть в backend CI.
Frontend:
cd frontend
npm ci
npm run typecheck
npm run build
В frontend/package.json нет отдельных команд lint и test. Существующий GitHub Actions workflow проверяет backend, включая тесты с PostgreSQL; он не подтверждает исправность frontend или полного браузерного сценария.
Архитектура
| Часть | Реализация и ответственность |
|---|---|
| Интерфейс | Nuxt 4, Vue 3, TypeScript; формы, каталог, карточки и отклики |
| Backend | Go, REST/JSON; жизненный цикл задач, валидация, AI, скоринг и отклики |
| Хранение | PostgreSQL 16, pgx; задачи, команды и предложения |
| AI | Уточнение описания и генерация карточки; mock либо внешний провайдер |
Браузер и серверная часть Nuxt обращаются к Go API; Go работает с PostgreSQL и AI-провайдером. Ключ AI находится только на backend.
Основные каталоги: frontend/app/, backend/cmd/api/, backend/internal/, backend/db/. Контракты REST: backend/API.md. Продуктовые требования: docs/SPEC.md.
Формула рейтинга и правила каталога
Рейтинг измеряет заполненность, а не достоверность фактов или смысловое качество текста. Его рассчитывает Go-код, не LLM. null, пустая строка и строка из пробелов дают 0.
| Категория | Правило | Максимум |
|---|---|---|
| Контекст и потребность | По 10 за context и need | 20 |
| Данные | Заполнено data | 20 |
| Ожидаемый результат | Заполнено expected_result | 15 |
| Критерии успеха | Заполнено success_criteria | 15 |
| Ограничения | Заполнено constraints | 10 |
| Пользователи | Заполнено users | 10 |
| Связь с бизнесом | По 5 за contact и interaction_format | 10 |
title и topic входят в карточку и подсказки, но не добавляют баллы.
| Баллы | Уровень |
|---|---|
| 0–39 | Draft — требует уточнения |
| 40–69 | Workable — рабочая |
| 70–89 | Ready — готовая |
| 90–100 | Priority — приоритетная |
Статусы публикации отдельные: draft → confirmed → published. Подтверждение не публикует задачу автоматически. Каталог показывает опубликованные задачи, по умолчанию сортирует по убыванию рейтинга, поддерживает фильтры topic, readiness_level и сортировку readiness_asc / readiness_desc. Значения фильтра уровня передаются в нижнем регистре.
Низкий рейтинг не блокирует публикацию и отклики. Бизнес принимает или отклоняет предложения вручную и может принять несколько команд.
Особенность текущей реализации: баллы пересчитываются при сохранении карточки и подтверждении. Редактирование уже подтверждённой или опубликованной задачи не сбрасывает статус. Таким образом, требование повторного подтверждения каждой правки пока не обеспечено полностью.
Демонстрация за 5 минут
- В роли бизнеса создайте задачу: «Теряем заявки клиентов в переписке. Хотим навести порядок».
- Получите уточняющие вопросы и ответьте на часть из них. Покажите, используется реальный AI или mock.
- Откройте сгенерированную карточку, проверьте сведения и исправьте текст.
- Покажите текущие баллы и недостающие поля. Допишите конкретный результат и критерии успеха, сохраните и покажите рост рейтинга.
- Подтвердите задачу, затем опубликуйте. Найдите её в каталоге, покажите сортировку и фильтр.
- Переключитесь на команду, отправьте идею, план, срок и ссылку на прототип.
- Вернитесь к бизнесу и примите либо отклоните предложение.
Дополнительные ручные проверки: публикация без подтверждения отклоняется; опубликованная задача с низким рейтингом видна; на неё можно откликнуться; два предложения можно принять независимо; пустое описание вызывает понятную ошибку.
Если что-то не работает
| Симптом | Что проверить |
|---|---|
port is already allocated | Занятый порт; измените *_PORT и соответствующие URL либо остановите другой процесс |
| Интерфейс открыт, запросы не проходят | NUXT_PUBLIC_API_BASE доступен с компьютера пользователя, API работает, CORS_ORIGIN точно совпадает с origin страницы |
| Работает серверный запрос, но не браузерный | Различие NUXT_API_BASE и NUXT_PUBLIC_API_BASE; HTTP API под HTTPS-интерфейсом |
| API unhealthy или не стартует | docker compose logs --tail=100 api postgres; доступность БД и фактический пароль существующего volume |
| Таблицы отсутствуют после изменения SQL | Инициализация не повторяется на существующем volume; нужна явная миграция |
| AI возвращает заглушку | AI_MODE, AI_FALLBACK, поле mode и причина fallback в ответе |
| AI падает при запуске или запросе | Ключ, модель, настройки провайдера, доступность сети и AI_TIMEOUT |
Инструкция сверена с исходниками main на коммите 5ff167b. Это сверка кода и конфигурации; она не означает, что развёртывание было выполнено в окружении автора README.
Авторы коммитов
История коммитов
- 2026-09-23 18:00dev: add Nix development shell for Go and NuxtMihail
- 2026-09-23 17:58docs: replace README with deployment and demo guideMihail
- 2026-09-23 17:54feat: finalize RU KK EN localization and task publication fixesmotya
- 2026-09-23 17:37merge: add backend maintenance and CImotya
- 2026-09-23 17:35chore: remove empty TZ documentmotya
- 2026-09-23 17:35Merge remote-tracking branch 'origin/main' into codex/backend-maintenancemotya
- 2026-09-23 17:33style: combine bridge illustration with project overviewMihail
- 2026-09-23 17:30Merge remote-tracking branch 'origin/main'n1k143
Все коммиты (57)
- 2026-09-23 17:30fix: polish backend-driven frontend UIn1k143
- 2026-09-23 17:25style: introduce project register and structured task briefsMihail
- 2026-09-23 17:24feat: add readiness maintenance, prototype URL validation and backend CImotya
- 2026-09-23 17:21style: refine MOST layout and weighted readiness presentationMihail
- 2026-09-23 17:12merge: harden backend integration and extend testsmotya
- 2026-09-23 17:10test: cover integrated backend flow and document APImotya
- 2026-09-23 17:09fix: make confirmation atomic and validate JSON bodiesmotya
- 2026-09-23 16:56Merge branch 'feat/frontend-backend-integration'n1k143
- 2026-09-23 16:54fix: align seeded readiness detailsn1k143
- 2026-09-23 16:48merge: add readiness preview to mainMihail
- 2026-09-23 16:43feat: connect frontend to backend APIn1k143
- 2026-09-23 16:32fix: make confirmation atomic and validate JSON bodiesmotya
- 2026-09-23 16:19Merge remote-tracking branch 'origin/main'n1k143
- 2026-09-23 16:18merge: add proposals API and frontend CORSmotya
- 2026-09-23 16:17fix layoutn1k143
- 2026-09-23 16:15feat: expose stateless readiness preview for task editingMihail
- 2026-09-23 16:15feat: add proposals API and frontend CORSmotya
- 2026-09-23 15:59merge: add unified backend Compose stackmotya
- 2026-09-23 15:59docs: add Docker Compose quick startmotya
- 2026-09-23 15:57fix: improve frontend text readabilityn1k143
- 2026-09-23 15:51chore: run API and PostgreSQL with Composemotya
- 2026-09-23 15:38merge: add frontend layoutn1k143
- 2026-09-23 15:32add full layoutn1k143
- 2026-09-23 15:30Merge backend-ai into main with task lifecycle integrationMihail
- 2026-09-23 15:23Switch AI provider to OpenAI Responses with strict structured outputMihail
- 2026-09-23 15:21merge: add task lifecycle and catalogmotya
- 2026-09-23 15:21feat: add task catalog and team listingmotya
- 2026-09-23 15:17Verify AI task flow against PostgreSQL with opt-in integration testMihail
- 2026-09-23 15:17Merge backend foundation updates and keep shared task card adapterMihail
- 2026-09-23 15:15feat: add task scoring and publication lifecyclemotya
- 2026-09-23 15:14Integrate AI routes and readiness with backend task contractsMihail
- 2026-09-23 15:11merge: add backend foundation and task CRUDmotya
- 2026-09-23 15:11refactor: share task card contractmotya
- 2026-09-23 15:09merge: integrate AI and scoring foundationmotya
- 2026-09-23 15:09Merge remote-tracking branch 'origin/codex/backend-foundation' into backend-aiMihail
- 2026-09-23 15:07Add validated AI clarification and card generation with explicit fallbackMihail
- 2026-09-23 15:02feat: add task draft CRUDmotya
- 2026-09-23 15:01Add shared task card contract and deterministic readiness scoringMihail
- 2026-09-23 14:55chore: ignore local hackathon briefmotya
- 2026-09-23 14:47feat: add base structuren1k143
- 2026-09-23 14:46feat: add backend database foundationmotya
- 2026-09-23 14:37merge: add database foundationmotya
- 2026-09-23 14:30chore: ignore local development filesmotya
- 2026-09-23 14:28feat: add PostgreSQL database setupmotya
- 2026-09-23 14:21feat: add barebones Go backendmotya
- 2026-09-23 14:18docs: add architecrure and spec descriptionMihail
- 2026-09-23 14:09docs: update AGENTS.mdMihail
- 2026-09-23 13:58add AGENTS.md and update README.mdmotya
- 2026-09-23 11:14docs: The Schmoogle updateMihail
Структура репозитория (106 файлов)
.env.example .gitignore AGENTS.md README.md backend/.dockerignore backend/AI_SCORING.md backend/API.md backend/Dockerfile backend/README.md backend/cmd/api/main.go backend/cmd/recalculate-readiness/main.go backend/db/migrations/000001_init.down.sql backend/db/migrations/000001_init.up.sql backend/db/seed.sql backend/go.mod backend/go.sum backend/internal/ai/ai.go backend/internal/ai/ai_test.go backend/internal/ai/mock.go backend/internal/ai/openai.go backend/internal/ai/openai_test.go backend/internal/ai/prompts/clarify.txt backend/internal/ai/prompts/generate.txt backend/internal/ai/testdata/clarify-input.json backend/internal/ai/testdata/clarify-output.json backend/internal/ai/testdata/generate-input.json backend/internal/ai/testdata/generate-output.json backend/internal/ai/validation.go backend/internal/database/database.go backend/internal/proposals/model.go backend/internal/proposals/store.go backend/internal/scoring/scoring.go backend/internal/scoring/scoring_test.go backend/internal/server/ai_handlers.go backend/internal/server/ai_handlers_test.go backend/internal/server/ai_postgres_test.go backend/internal/server/cors.go backend/internal/server/cors_test.go backend/internal/server/json_test.go backend/internal/server/proposal_handlers.go backend/internal/server/proposal_handlers_test.go backend/internal/server/scoring_handlers_test.go backend/internal/server/server.go backend/internal/server/server_test.go backend/internal/server/task_handlers.go backend/internal/server/task_handlers_test.go backend/internal/server/team_handlers.go backend/internal/server/team_handlers_test.go backend/internal/taskcard/card.go backend/internal/tasks/confirm_postgres_test.go backend/internal/tasks/model.go backend/internal/tasks/readiness.go backend/internal/tasks/readiness_test.go backend/internal/tasks/recalculate.go backend/internal/tasks/recalculate_postgres_test.go backend/internal/tasks/store.go backend/internal/teams/model.go backend/internal/teams/store.go docker-compose.yml docs/ARCHITECTURE.md docs/MVP.md docs/SPEC.md flake.nix frontend/.dockerignore frontend/.gitignore frontend/Dockerfile frontend/README.md frontend/app/app.vue frontend/app/assets/css/main.css frontend/app/components/AppIcon.vue frontend/app/components/BrandMark.vue frontend/app/components/ClarificationChat.vue frontend/app/components/EmptyState.vue frontend/app/components/HeroBridge.vue frontend/app/components/LanguageSwitcher.vue frontend/app/components/ProposalForm.vue frontend/app/components/ProposalList.vue frontend/app/components/ReadinessScore.vue frontend/app/components/RoleSwitcher.vue frontend/app/components/TaskCard.vue frontend/app/composables/useApi.ts frontend/app/composables/useLocale.ts frontend/app/composables/usePlatformApi.ts frontend/app/composables/useRole.ts frontend/app/i18n/messages.ts frontend/app/pages/catalog/[id].vue frontend/app/pages/catalog/index.vue frontend/app/pages/index.vue frontend/app/pages/proposals/index.vue frontend/app/pages/tasks/[id]/edit.vue frontend/app/pages/tasks/[id]/proposals.vue frontend/app/pages/tasks/index.vue frontend/app/pages/tasks/new.vue frontend/app/plugins/locale.ts frontend/app/plugins/role.client.ts frontend/app/types/api.ts frontend/app/types/task.ts frontend/app/utils/presentation.ts frontend/nuxt.config.ts frontend/package-lock.json frontend/package.json frontend/public/favicon.ico frontend/public/favicon.svg frontend/public/robots.txt frontend/scripts/check-locales.mjs frontend/tsconfig.json
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.