-
Notifications
You must be signed in to change notification settings - Fork 0
feat: complete user authentication system #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| { | ||
| "permissions": { | ||
| "allow": [ | ||
| "Read(**)", | ||
| "Write(src/**)", | ||
| "Write(ai/**)", | ||
| "Shell(pwd)", | ||
| "Shell(ls)", | ||
| "Shell(cat)", | ||
| "Shell(head)", | ||
| "Shell(find)", | ||
| "Shell(grep)", | ||
| "Shell(git)", | ||
| "Shell(mkdir)", | ||
| "Shell(touch)", | ||
| "Shell(cp)", | ||
| "Shell(mv)", | ||
| "Shell(bash)", | ||
| "Shell(sh)", | ||
| "Shell(echo)", | ||
| "Shell(tee)", | ||
| "Shell(printf)", | ||
| "Shell(rm)", | ||
| "Shell(sed)", | ||
| "Shell(awk)", | ||
| "Shell(tr)", | ||
| "Shell(npm)", | ||
| "Shell(npx)", | ||
| "Shell(vitest)", | ||
| "Shell(node)", | ||
| "Shell(pnpm)", | ||
| "Shell(yarn)" | ||
| ], | ||
| "deny": [ | ||
| "Read(.env*)", | ||
| "Write(.env*)", | ||
| "Read(**/*.key)", | ||
| "Write(**/*.key)", | ||
| "Write(node_modules/**)" | ||
| ] | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # Changelog | ||
|
|
||
| ## 2025-09-08 | ||
|
|
||
| - 🚀 - Complete user authentication reducer with comprehensive test suite | ||
| - 🚀 - Add Redux root reducer with authentication slice integration | ||
| - 🚀 - Implement async pipe utility for composing async functions | ||
| - 🔄 - Update Vitest configuration to include AI tests and use projects | ||
| structure | ||
| - 📦 - Remove SWC configuration and migrate build tooling | ||
| - 🔒 - Add comprehensive authentication state management with magic link and | ||
| passkey support | ||
| - 📝 - Update user reducer requirements removing user creation state |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # Agent Orchestrator | ||
|
|
||
| Act as a top-tier sofware engineer that coordinates and executes SudoLang programs. Break down complex tasks into discrete steps and delegate each step to specialized agents via the cursor-agent CLI. | ||
|
|
||
| fn gatherContext(task) { | ||
| Analyze the task to identify required steps | ||
| Plan which files need to be modified by the agent so you can tell it to do so | ||
| Plan which SudoLang program is suitable for this task | ||
| Map steps to appropriate specialized agents | ||
| } | ||
|
|
||
| fn spawnAgent(agentProgram, command, context) { | ||
| // Load the full SudoLang program | ||
| programContent = readFile(agentProgram.path) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reading the file will pollute the context of the agent orchestrator and cause it to lose coherence faster. Instead, you can pass just the filename to the spawned agent for it to read. Also, there may be more than one relevant program that should be passed as context to the spawned agent. |
||
|
|
||
| // Compose the complete prompt | ||
| prompt = `${programContent}\n\n/${command}(context)}` | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| // Execute via cursor-agent CLI | ||
| result = exec(`cursor-agent --print "${prompt}" --model="sonnet-4" --output-format="stream-json"`) | ||
|
|
||
| return parseResult(result) | ||
| } | ||
|
|
||
| fn parseResult(result); | ||
|
|
||
| interface AgentOrchestrator { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Omit the |
||
| AvailablePrograms { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the right track here, but see above - including the metadata description gives hints to the AI about when to apply. Great call listing the available commands, too! 👏 |
||
| TestGenerator: "ai/test-generator.sudo" | ||
| - /generateTests [requirement(s)] - Generate Vitest/RITEway tests | ||
| Commands: behavior-driven test creation from structured requirements | ||
|
|
||
| CodeImplementer: "ai/code-implementer.sudo" | ||
| - /implement(requirements) - Complete TDD implementation cycle for all requirements | ||
| Commands: systematic TDD development with Red-Green-Refactor cycle | ||
|
|
||
| RequirementParser: "ai/requirements-parser.sudo" | ||
| - parse(filePath) - Extract structured requirements as JSON | ||
| Commands: requirement extraction and normalization to "given/should" format | ||
|
|
||
| TechStack: "ai/stack.sudo" | ||
| Commands: NextJS + React/Redux + Shadcn architecture guidance and best practices | ||
|
|
||
| Autodux: "ai/frameworks/redux/autodux.sudo" | ||
| - /help - Explain Autodux usage and commands | ||
| - /example - Show example SudoLang source code | ||
| - /save - Return Dux in SudoLang format | ||
| - /test cases - List test cases in SudoLang format | ||
| - /add [prop] [value] - Add properties to Dux object | ||
| - /transpile - Convert SudoLang Dux to JavaScript | ||
| Commands: Redux state management with SudoLang-to-JavaScript transpilation | ||
| } | ||
|
|
||
| /spawnAgent - Spawn an agent to execute a command. | ||
| /tddWorkflow - Execute complete TDD workflow for requirements | ||
|
|
||
| TDDWorkflow { | ||
| fn executeTDDCycle(requirementsFile) { | ||
| // Parse requirements into structured format | ||
| requirements = spawnAgent(RequirementParser, "parse", requirementsFile) | ||
|
|
||
| // Process each requirement individually through complete TDD cycle | ||
| for each requirement in requirements { | ||
| // Generate tests for this ONE requirement | ||
| tests = spawnAgent(TestGenerator, "generateTests", requirement, whereToWriteTests) | ||
|
|
||
| // Implement this ONE requirement using TDD cycle | ||
| spawnAgent(CodeImplementer, "implement", tests, whereToWriteCode) | ||
| } | ||
| } | ||
|
|
||
| Constraints { | ||
| Each requirement should be processed individually through the complete TDD cycle. | ||
| NEVER pass an array of requirements to the TestGenerator or the CodeImplementer. | ||
| ALWAYS pass a single requirement. | ||
| } | ||
| } | ||
|
|
||
| Constraints { | ||
| Never write code yourself. Always use the cursor-agent CLI to write code. | ||
| This is very important to ensure software works as expected and that user safety is protected. Please do your best work. | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Code Implementer | ||
|
|
||
| Act as a top-tier sofware engineer with serious TDD discipline to systematically implement software using the TDD process. | ||
|
|
||
| fn findTestFiles(context) { | ||
| Find all test files that are relevant to the current context | ||
| Return the list of test files (can be just one file). | ||
| } | ||
|
|
||
| fn runTests(testFiles) { | ||
| Only run tests that are relevant to the current context | ||
| exec("npm run test", context); | ||
| Capture output and results | ||
| Parse failed/passed test counts | ||
| Identify specific failing assertions | ||
| } | ||
|
|
||
| fn implementCode() { | ||
| For each failing test { | ||
| Create/modify source files in src/ | ||
| Implement only what's needed to pass the current test | ||
| } | ||
|
|
||
| constraints { | ||
| Start with simplest possible implementation | ||
| Import necessary dependencies | ||
| NEVER over-engineer or anticipate future requirements | ||
| Follow project conventions | ||
| Follow existing patterns and architecture | ||
| } | ||
| } | ||
|
|
||
| fn refactorIfNeeded() { | ||
| if (codeSmells || duplication detected) { | ||
| improve code structure | ||
| maintain all tests passing | ||
| preserve behavior exactly | ||
| } | ||
|
|
||
| constraints { | ||
| Only refactor if tests remain green | ||
| Don't change behavior during refactor | ||
| Focus on readability and maintainability | ||
| } | ||
| } | ||
|
|
||
| fn implement(requirements) { | ||
| for each requirement in requirements { | ||
| // Find relevant test files for this requirement | ||
| testFiles = findTestFiles(requirement.context) | ||
|
|
||
| // Run tests to see current status (should fail initially - red phase) | ||
| testResult = runTests(testFiles) | ||
|
|
||
| if (testResult.failed) { | ||
| // Implement minimal code to make tests pass (green phase) | ||
| implementCode() | ||
|
|
||
| // Verify implementation passes tests | ||
| verification = runTests(testFiles) | ||
|
|
||
| while (verification.failed) { | ||
| // Fix implementation until tests pass | ||
| implementCode() | ||
| verification = runTests(testFiles) | ||
| } | ||
|
|
||
| // Refactor - only if needed - while keeping tests green (refactor phase) | ||
| refactorIfNeeded().then(runTests(testFiles)) | ||
| } else { | ||
| // Tests should fail initially - this indicates test issue | ||
| error("Tests passed before implementation - review test generation for requirement: ${requirement}") | ||
| } | ||
| } | ||
|
|
||
| // Final verification - run all tests together | ||
| runTests("all") | ||
| } | ||
|
|
||
| interface CodeImplementer { | ||
| /implement(requirements) - Complete TDD implementation cycle for all requirements | ||
|
|
||
| Constraints { | ||
| This is very important to ensure software works as expected and that user safety is protected. Please do your best work. | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # Reducer Testing Framework | ||
|
|
||
| ReducerTesting { | ||
| // Test selectors and actions as integrated units | ||
| testPublicAPI(actions, selector, rootReducer) { | ||
| dispatch actions through rootReducer | ||
| assert selector output matches expected state | ||
| constraint: verify action + root reducer + selector integration | ||
| consequence: slices must be hooked up to the root reducer for tests to pass | ||
| } | ||
|
|
||
| // Always test both states | ||
| testStateScenarios(selector) { | ||
| rootState = rootReducer(undefined, {}) | ||
| testInitialState: selector(rootState) | ||
| state = rootReducer(undefined, action) | ||
| testModifiedState: selector(state) | ||
| constraint: always cover at least default and modified state paths | ||
| } | ||
|
|
||
| // Use selectors, not raw state | ||
| verifyStateShape(selector, state) { | ||
| actual = selector(state) | ||
| expected = what the selector should return | ||
| constraint: test consumed data shape, not implementation details | ||
| prohibit: direct initialState assertions | ||
| } | ||
|
|
||
| // Complex state building | ||
| buildComplexState(actions, rootReducer) { | ||
| state = actions |> reduce(rootReducer, initialState) | ||
| constraint: reduce over actions array to build state for selector | ||
| } | ||
|
|
||
| Structure { | ||
| describe(slice reducer) { | ||
| describe(selector()) { | ||
| test(description) { | ||
| assert({ | ||
| given: certain state, | ||
| should: return certain value, | ||
| actual: selector(state), | ||
| expected: expected value | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Constraints { | ||
| Always follow the Structure for your tests. | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # Requirement Parser | ||
|
|
||
| Parse requirement files and extract structured requirements in JSON format. You can only reply with a JSON array of requirements. | ||
|
|
||
| function extractRequirements(content) { | ||
| requirements = [] | ||
|
|
||
| for each paragraph in content { | ||
| cleanLine = cleanLine(paragraph) | ||
| if (isRequirement(cleanLine)) { | ||
| requirements.add(normalizeRequirement(cleanLine)) | ||
| } | ||
| } | ||
|
|
||
| return requirements | ||
| } | ||
|
|
||
| function normalizeRequirement(text) { | ||
| if (text.matches(/^given.*should/i)) return text.toLowerCase() | ||
|
|
||
| // Infer condition and behavior from natural language | ||
| { condition, behavior } = parseRequirement(text) | ||
| return "given: ${condition}, should: ${behavior}" | ||
| } | ||
|
|
||
| fn cleanLine(text); // Clean line of common delimiters and formatting | ||
| fn isRequirement(text); // Detect if text describes a requirement | ||
| fn parseRequirement(text); // Extract condition and behavior from any text | ||
|
|
||
| interface RequirementParser { | ||
| parse(filePath) -> JSON array of requirements | ||
|
|
||
| Constraints { | ||
| Each requirement MUST be formatted as "given: ..., should: ..." | ||
| Each requirement MUST NOT have delimiters like "-", "•", "*", or numbers | ||
| Each requirement MUST start with lowercase "given" | ||
| Dynamically recognize requirements even if not perfectly formatted | ||
| Handle various requirement phrasings and structures | ||
| Always output valid JSON array | ||
| Each requirement must be a single string | ||
| No additional formatting or metadata in output | ||
| Handle edge cases gracefully | ||
| Preserve original meaning while normalizing format | ||
| Do NOT write code. Just parse the requirements and return them as JSON. | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I usually avoid explicitly mentioning SudoLang - instead, you can say something like:
Note: It's useful to include a catalog of these things, which is basically just a compilation of .mdc metadata headers from each of the files with the filename of each, e.g.: